Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 Feb 2009 16:51:19 +0100
From:      Luigi Rizzo <rizzo@iet.unipi.it>
To:        arch@freebsd.org, Luigi Rizzo <rizzo@iet.unipi.it>, Fabio Checconi <fabio@gandalf.sssup.it>, pjd@freebsd.org, kmacy@freebsd.org
Subject:   Re: RFC: upcoming fixes to bioq_disksort() and friends.
Message-ID:  <20090207155119.GC44298@onelab2.iet.unipi.it>

next in thread | raw e-mail | index | archive | help
As a followup, below is the core of the new bioq routines,
as you can see they are extremely simple.

An additional feature that might be useful, and trivial to implement,
is let bioq_insert_tail() act as a barrier, so you have the guarantee
that all new bioq_disksort() will be inserted after that.

The necessart changes are in the #ifdef BARRIER/#endif blocks,
and as you can see they are totally straightforward.

If there are no objections, i am going to add them as well
so the insert_tail() has a well-specified behaviour when
intermixed with bioq_disksort() calls.

	cheers
	luigi

---- new implementation of bioq routines -------------


static inline uoff_t
bioq_bio_key(struct bio_queue_head *head, struct bio *bp)
{

        return ((uoff_t)(bp->bio_offset - head->last_offset));
}

void
bioq_disksort(struct bio_queue_head *head, struct bio *bp)
{
        struct bio *cur, *prev = NULL;
        uoff_t key = bioq_bio_key(head, bp);

        cur = TAILQ_FIRST(&head->queue);

#ifdef BARRIER
	if (head->insert_point)
		cur = head->insert_point;
#endif /* BARRIER */

        while (cur != NULL && key >= bioq_bio_key(head, cur)) {
                prev = cur;
                cur = TAILQ_NEXT(cur, bio_queue);
        }
        if (prev == NULL)
                TAILQ_INSERT_HEAD(&head->queue, bp, bio_queue);
        else
                TAILQ_INSERT_AFTER(&head->queue, prev, bp, bio_queue);
}

void
bioq_remove(struct bio_queue_head *head, struct bio *bp)
{

        if (bp == TAILQ_FIRST(&head->queue))
                head->last_offset = bp->bio_offset + bp->bio_length;

#ifdef BARRIER
	if (bp == head->insert_point)
		head->insert_point = NULL;
#endif /* BARRIER */

        TAILQ_REMOVE(&head->queue, bp, bio_queue);
    }

struct bio *
bioq_first(struct bio_queue_head *head)
{

        return (TAILQ_FIRST(&head->queue));
}

struct bio *
bioq_takefirst(struct bio_queue_head *head)
{
        struct bio *bp = TAILQ_FIRST(&head->queue);

        if (bp != NULL)
                bioq_remove(head, bp);
        return (bp);
}

void
bioq_insert_head(struct bio_queue_head *head, struct bio *bp)
{

        head->last_offset = bp->bio_offset;
        TAILQ_INSERT_HEAD(&head->queue, bp, bio_queue);
}

void
bioq_insert_tail(struct bio_queue_head *head, struct bio *bp)
{

        TAILQ_INSERT_TAIL(&head->queue, bp, bio_queue);

#ifdef BARRIER
	head->insert_point = bp;
#endif
}


void
bioq_init(struct bio_queue_head *head)
{

        TAILQ_INIT(&head->queue);
        head->last_offset = 0;
        head->insert_point = NULL;      /* Unused or barrier */
}

---------------------------------------------------------------------



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090207155119.GC44298>