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>