From: NeilBrown Both raid1 and multipath have a "retry_list" which is global, so all raid1 arrays (for example) us the same list. This is rather ugly, and it is simple enough to make it per-array, so this patch does that. It also changes to multipath code to use list.h lists instead of roll-your-own. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton --- 25-akpm/drivers/md/multipath.c | 28 ++++++++++++---------------- 25-akpm/drivers/md/raid1.c | 18 +++++++++--------- 25-akpm/include/linux/raid/multipath.h | 3 ++- 25-akpm/include/linux/raid/raid1.h | 1 + 4 files changed, 24 insertions(+), 26 deletions(-) diff -puN drivers/md/multipath.c~md-make-retry_list-non-global-in-raid1-and-multipath drivers/md/multipath.c --- 25/drivers/md/multipath.c~md-make-retry_list-non-global-in-raid1-and-multipath 2004-09-07 19:58:56.973708592 -0700 +++ 25-akpm/drivers/md/multipath.c 2004-09-07 19:58:56.981707376 -0700 @@ -36,8 +36,6 @@ static mdk_personality_t multipath_personality; -static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED; -struct multipath_bh *multipath_retry_list = NULL, **multipath_retry_tail; static void *mp_pool_alloc(int gfp_flags, void *data) @@ -101,14 +99,11 @@ static void multipath_reschedule_retry ( { unsigned long flags; mddev_t *mddev = mp_bh->mddev; + multipath_conf_t *conf = mddev_to_conf(mddev); - spin_lock_irqsave(&retry_list_lock, flags); - if (multipath_retry_list == NULL) - multipath_retry_tail = &multipath_retry_list; - *multipath_retry_tail = mp_bh; - multipath_retry_tail = &mp_bh->next_mp; - mp_bh->next_mp = NULL; - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_lock_irqsave(&conf->device_lock, flags); + list_add(&mp_bh->retry_list, &conf->retry_list); + spin_unlock_irqrestore(&conf->device_lock, flags); md_wakeup_thread(mddev->thread); } @@ -399,18 +394,18 @@ static void multipathd (mddev_t *mddev) struct bio *bio; unsigned long flags; multipath_conf_t *conf = mddev_to_conf(mddev); + struct list_head *head = &conf->retry_list; md_check_recovery(mddev); for (;;) { char b[BDEVNAME_SIZE]; - spin_lock_irqsave(&retry_list_lock, flags); - mp_bh = multipath_retry_list; - if (!mp_bh) + spin_lock_irqsave(&conf->device_lock, flags); + if (list_empty(head)) break; - multipath_retry_list = mp_bh->next_mp; - spin_unlock_irqrestore(&retry_list_lock, flags); + mp_bh = list_entry(head->prev, struct multipath_bh, retry_list); + list_del(head->prev); + spin_unlock_irqrestore(&conf->device_lock, flags); - mddev = mp_bh->mddev; bio = &mp_bh->bio; bio->bi_sector = mp_bh->master_bio->bi_sector; @@ -433,7 +428,7 @@ static void multipathd (mddev_t *mddev) generic_make_request(bio); } } - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_unlock_irqrestore(&conf->device_lock, flags); } static int multipath_run (mddev_t *mddev) @@ -506,6 +501,7 @@ static int multipath_run (mddev_t *mddev mddev->sb_dirty = 1; conf->mddev = mddev; conf->device_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&conf->retry_list); if (!conf->working_disks) { printk(KERN_ERR "multipath: no operational IO paths for %s\n", diff -puN drivers/md/raid1.c~md-make-retry_list-non-global-in-raid1-and-multipath drivers/md/raid1.c --- 25/drivers/md/raid1.c~md-make-retry_list-non-global-in-raid1-and-multipath 2004-09-07 19:58:56.975708288 -0700 +++ 25-akpm/drivers/md/raid1.c 2004-09-07 19:58:56.983707072 -0700 @@ -30,8 +30,6 @@ #define NR_RAID1_BIOS 256 static mdk_personality_t raid1_personality; -static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED; -static LIST_HEAD(retry_list_head); static void unplug_slaves(mddev_t *mddev); @@ -188,10 +186,11 @@ static void reschedule_retry(r1bio_t *r1 { unsigned long flags; mddev_t *mddev = r1_bio->mddev; + conf_t *conf = mddev_to_conf(mddev); - spin_lock_irqsave(&retry_list_lock, flags); - list_add(&r1_bio->retry_list, &retry_list_head); - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_lock_irqsave(&conf->device_lock, flags); + list_add(&r1_bio->retry_list, &conf->retry_list); + spin_unlock_irqrestore(&conf->device_lock, flags); md_wakeup_thread(mddev->thread); } @@ -904,11 +903,11 @@ static void sync_request_write(mddev_t * static void raid1d(mddev_t *mddev) { - struct list_head *head = &retry_list_head; r1bio_t *r1_bio; struct bio *bio; unsigned long flags; conf_t *conf = mddev_to_conf(mddev); + struct list_head *head = &conf->retry_list; int unplug=0; mdk_rdev_t *rdev; @@ -917,12 +916,12 @@ static void raid1d(mddev_t *mddev) for (;;) { char b[BDEVNAME_SIZE]; - spin_lock_irqsave(&retry_list_lock, flags); + spin_lock_irqsave(&conf->device_lock, flags); if (list_empty(head)) break; r1_bio = list_entry(head->prev, r1bio_t, retry_list); list_del(head->prev); - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_unlock_irqrestore(&conf->device_lock, flags); mddev = r1_bio->mddev; conf = mddev_to_conf(mddev); @@ -956,7 +955,7 @@ static void raid1d(mddev_t *mddev) } } } - spin_unlock_irqrestore(&retry_list_lock, flags); + spin_unlock_irqrestore(&conf->device_lock, flags); if (unplug) unplug_slaves(mddev); } @@ -1205,6 +1204,7 @@ static int run(mddev_t *mddev) conf->raid_disks = mddev->raid_disks; conf->mddev = mddev; conf->device_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&conf->retry_list); if (conf->working_disks == 1) mddev->recovery_cp = MaxSector; diff -puN include/linux/raid/multipath.h~md-make-retry_list-non-global-in-raid1-and-multipath include/linux/raid/multipath.h --- 25/include/linux/raid/multipath.h~md-make-retry_list-non-global-in-raid1-and-multipath 2004-09-07 19:58:56.976708136 -0700 +++ 25-akpm/include/linux/raid/multipath.h 2004-09-07 19:58:56.983707072 -0700 @@ -14,6 +14,7 @@ struct multipath_private_data { int working_disks; spinlock_t device_lock; unsigned long last_fail_event; + struct list_head retry_list; mempool_t *pool; }; @@ -37,6 +38,6 @@ struct multipath_bh { struct bio *master_bio; struct bio bio; int path; - struct multipath_bh *next_mp; /* next for retry */ + struct list_head retry_list; }; #endif diff -puN include/linux/raid/raid1.h~md-make-retry_list-non-global-in-raid1-and-multipath include/linux/raid/raid1.h --- 25/include/linux/raid/raid1.h~md-make-retry_list-non-global-in-raid1-and-multipath 2004-09-07 19:58:56.977707984 -0700 +++ 25-akpm/include/linux/raid/raid1.h 2004-09-07 19:58:56.983707072 -0700 @@ -35,6 +35,7 @@ struct r1_private_data_s { sector_t next_seq_sect; spinlock_t device_lock; + struct list_head retry_list; /* for use when syncing mirrors: */ spinlock_t resync_lock; _