And here I modified dm.c, dm-raid1.c, dm-snap.c and dm-crypt.c to use the functions in dm-bio-list.h. --- linux.orig/drivers/md/dm.c 2004-01-10 20:42:24.327708960 +0100 +++ linux/drivers/md/dm.c 2004-01-10 20:54:47.899668840 +0100 @@ -5,6 +5,7 @@ */ #include "dm.h" +#include "dm-bio-list.h" // FIXME: remove this #include "dm-log.h" @@ -63,8 +64,7 @@ */ atomic_t pending; wait_queue_head_t wait; - struct bio *deferred_head; - struct bio *deferred_tail; + struct bio_list deferred; /* * The current mapping. @@ -231,13 +231,7 @@ return 1; } - bio->bi_next = NULL; - - if (md->deferred_tail) - md->deferred_tail->bi_next = bio; - else - md->deferred_head = bio; - md->deferred_tail = bio; + bio_list_add(&md->deferred, bio); up_write(&md->lock); return 0; /* deferred successfully */ @@ -897,8 +891,7 @@ clear_bit(DMF_SUSPENDED, &md->flags); clear_bit(DMF_BLOCK_IO, &md->flags); - def = md->deferred_head; - md->deferred_head = md->deferred_tail = NULL; + def = bio_list_get(&md->deferred); __flush_deferred_io(md, def); up_write(&md->lock); --- linux.orig/drivers/md/dm-crypt.c 2004-01-10 16:28:23.000000000 +0100 +++ linux/drivers/md/dm-crypt.c 2004-01-10 16:28:17.000000000 +0100 @@ -15,6 +15,7 @@ #include <asm/scatterlist.h> #include "dm.h" +#include "dm-bio-list.h" #include "dm-daemon.h" /* @@ -335,8 +336,7 @@ * queued here. */ static spinlock_t _kcryptd_lock = SPIN_LOCK_UNLOCKED; -static struct bio *_kcryptd_bio_head; -static struct bio *_kcryptd_bio_tail; +static struct bio_list _kcryptd_bios; static struct dm_daemon _kcryptd; @@ -348,9 +348,7 @@ struct bio *bio; spin_lock_irq(&_kcryptd_lock); - bio = _kcryptd_bio_head; - if (bio) - _kcryptd_bio_head = _kcryptd_bio_tail = NULL; + bio = bio_list_get(&_kcryptd_bios); spin_unlock_irq(&_kcryptd_lock); return bio; @@ -363,13 +361,8 @@ { unsigned long flags; - bio->bi_next = NULL; spin_lock_irqsave(&_kcryptd_lock, flags); - if (_kcryptd_bio_tail) - _kcryptd_bio_tail->bi_next = bio; - else - _kcryptd_bio_head = bio; - _kcryptd_bio_tail = bio; + bio_list_add(&_kcryptd_bios, bio); spin_unlock_irqrestore(&_kcryptd_lock, flags); } --- linux.orig/drivers/md/dm-raid1.c 2004-01-10 16:12:08.000000000 +0100 +++ linux/drivers/md/dm-raid1.c 2004-01-10 16:28:54.000000000 +0100 @@ -5,6 +5,7 @@ */ #include "dm.h" +#include "dm-bio-list.h" #include "dm-daemon.h" #include "dm-io.h" #include "dm-log.h" @@ -22,49 +23,6 @@ static struct dm_daemon _kmirrord; /*----------------------------------------------------------------- - * buffer lists: - * - * We play with singly linked lists of bios, but we want to be - * careful to add new bios to the back of the list, to avoid - * buffers being starved of attention. - *---------------------------------------------------------------*/ -struct bio_list { - struct bio *head; - struct bio *tail; -}; - -static inline void bio_list_init(struct bio_list *bl) -{ - bl->head = bl->tail = NULL; -} - -static inline void bio_list_add(struct bio_list *bl, struct bio *bio) -{ - bio->bi_next = NULL; - - if (bl->tail) { - bl->tail->bi_next = bio; - bl->tail = bio; - } else - bl->head = bl->tail = bio; -} - -static struct bio *bio_list_pop(struct bio_list *bl) -{ - struct bio *bio = bl->head; - - if (bio) { - bl->head = bl->head->bi_next; - if (!bl->head) - bl->tail = NULL; - - bio->bi_next = NULL; - } - - return bio; -} - -/*----------------------------------------------------------------- * Region hash * * The mirror splits itself up into discrete regions. Each --- linux.orig/drivers/md/dm-snap.c 2004-01-10 16:12:08.000000000 +0100 +++ linux/drivers/md/dm-snap.c 2004-01-10 18:07:10.000000000 +0100 @@ -20,6 +20,7 @@ #include <linux/vmalloc.h> #include "dm-snap.h" +#include "dm-bio-list.h" #include "kcopyd.h" /* @@ -52,10 +53,10 @@ /* * Origin buffers waiting for this to complete are held - * in a list (using b_reqnext). + * in a bio list */ - struct bio *origin_bios; - struct bio *snapshot_bios; + struct bio_list origin_bios; + struct bio_list snapshot_bios; /* * Other pending_exceptions that are processing this @@ -570,26 +571,6 @@ } /* - * We hold lists of bios, using the bi_next field. - */ -static void queue_bio(struct bio **queue, struct bio *bio) -{ - bio->bi_next = *queue; - *queue = bio; -} - -/* - * FIXME: inefficient. - */ -static void queue_bios(struct bio **queue, struct bio *bios) -{ - while (*queue) - queue = &((*queue)->bi_next); - - *queue = bios; -} - -/* * Flush a list of buffers. */ static void flush_bios(struct bio *bio) @@ -628,7 +609,7 @@ struct pending_exception *sibling; if (list_empty(&pe->siblings)) - return pe->origin_bios; + return bio_list_get(&pe->origin_bios); sibling = list_entry(pe->siblings.next, struct pending_exception, siblings); @@ -636,7 +617,7 @@ list_del(&pe->siblings); /* FIXME: I think there's a race on SMP machines here, add spin lock */ - queue_bios(&sibling->origin_bios, pe->origin_bios); + bio_list_merge(&sibling->origin_bios, &pe->origin_bios); return NULL; } @@ -680,7 +661,7 @@ flush = __flush_bios(pe); up_write(&s->lock); - error_bios(pe->snapshot_bios); + error_bios(bio_list_get(&pe->snapshot_bios)); goto out; } memcpy(e, &pe->e, sizeof(*e)); @@ -697,7 +678,7 @@ /* Submit any pending write BHs */ up_write(&s->lock); - flush_bios(pe->snapshot_bios); + flush_bios(bio_list_get(&pe->snapshot_bios)); DMDEBUG("Exception completed successfully."); /* Notify any interested parties */ @@ -714,7 +695,7 @@ flush = __flush_bios(pe); up_write(&s->lock); - error_bios(pe->snapshot_bios); + error_bios(bio_list_get(&pe->snapshot_bios)); dm_table_event(s->table); DMDEBUG("Exception failed."); @@ -815,7 +796,8 @@ pe = list_entry(e, struct pending_exception, e); } else { pe->e.old_chunk = chunk; - pe->origin_bios = pe->snapshot_bios = NULL; + bio_list_init(&pe->origin_bios); + bio_list_init(&pe->snapshot_bios); INIT_LIST_HEAD(&pe->siblings); pe->snap = s; pe->started = 0; @@ -883,7 +865,7 @@ up_write(&s->lock); } else { remap_exception(s, &pe->e, bio); - queue_bio(&pe->snapshot_bios, bio); + bio_list_add(&pe->snapshot_bios, bio); if (!pe->started) { /* this is protected by snap->lock */ @@ -1053,7 +1035,7 @@ do { down_write(&pe->snap->lock); if (first) - queue_bio(&pe->origin_bios, bio); + bio_list_add(&pe->origin_bios, bio); if (!pe->started) { pe->started = 1; up_write(&pe->snap->lock);