Index: linux-2.6.18-rc7/drivers/md/dm-raid1.c =================================================================== --- linux-2.6.18-rc7.orig/drivers/md/dm-raid1.c 2006-10-13 17:10:20.000000000 +0100 +++ linux-2.6.18-rc7/drivers/md/dm-raid1.c 2006-10-13 17:10:22.000000000 +0100 @@ -22,14 +22,6 @@ #define DM_MSG_PREFIX "raid1" -static struct workqueue_struct *_kmirrord_wq; -static struct work_struct _kmirrord_work; - -static inline void wake(void) -{ - queue_work(_kmirrord_wq, &_kmirrord_work); -} - /*----------------------------------------------------------------- * Region hash * @@ -134,6 +126,9 @@ struct mirror_set { struct mirror *default_mirror; /* Default mirror */ + struct workqueue_struct *kmirrord_wq; + struct work_struct kmirrord_work; + unsigned int nr_mirrors; struct mirror mirror[0]; }; @@ -151,6 +146,11 @@ static inline sector_t region_to_sector( return region << rh->region_shift; } +static inline void wake(struct mirror_set *ms) +{ + queue_work(ms->kmirrord_wq, &ms->kmirrord_work); +} + /* FIXME move this */ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); @@ -457,7 +457,7 @@ static void rh_dec(struct region_hash *r spin_unlock_irqrestore(&rh->region_lock, flags); if (should_wake) - wake(); + wake(rh->ms); } /* @@ -534,7 +534,7 @@ static void rh_recovery_end(struct regio list_add(®->list, ®->rh->recovered_regions); spin_unlock_irq(&rh->region_lock); - wake(); + wake(rh->ms); } static void rh_flush(struct region_hash *rh) @@ -568,7 +568,7 @@ static void rh_start_recovery(struct reg for (i = 0; i < MAX_RECOVERY; i++) up(&rh->recovery_count); - wake(); + wake(rh->ms); } /* @@ -849,8 +849,9 @@ static void do_writes(struct mirror_set static LIST_HEAD(_mirror_sets); static DECLARE_RWSEM(_mirror_sets_lock); -static void do_mirror(struct mirror_set *ms) +static void do_mirror(void *data) { + struct mirror_set *ms = data; struct bio_list reads, writes; spin_lock(&ms->lock); @@ -866,16 +867,6 @@ static void do_mirror(struct mirror_set do_writes(ms, &writes); } -static void do_work(void *ignored) -{ - struct mirror_set *ms; - - down_read(&_mirror_sets_lock); - list_for_each_entry (ms, &_mirror_sets, list) - do_mirror(ms); - up_read(&_mirror_sets_lock); -} - /*----------------------------------------------------------------- * Target functions *---------------------------------------------------------------*/ @@ -959,7 +950,7 @@ static int add_mirror_set(struct mirror_ down_write(&_mirror_sets_lock); list_add_tail(&ms->list, &_mirror_sets); up_write(&_mirror_sets_lock); - wake(); + wake(ms); return 0; } @@ -1069,11 +1060,20 @@ static int mirror_ctr(struct dm_target * argc -= 2; } + ms->kmirrord_wq = create_singlethread_workqueue("kmirrord"); + if (!ms->kmirrord_wq) { + DMERR("couldn't start kmirrord"); + free_context(ms, ti, m); + return -ENOMEM; + } + INIT_WORK(&ms->kmirrord_work, do_mirror, ms); + ti->private = ms; ti->split_io = ms->rh.region_size; r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); if (r) { + destroy_workqueue(ms->kmirrord_wq); free_context(ms, ti, ms->nr_mirrors); return r; } @@ -1088,6 +1088,7 @@ static void mirror_dtr(struct dm_target del_mirror_set(ms); kcopyd_client_destroy(ms->kcopyd_client); + destroy_workqueue(ms->kmirrord_wq); free_context(ms, ti, ms->nr_mirrors); } @@ -1103,7 +1104,7 @@ static void queue_bio(struct mirror_set spin_unlock(&ms->lock); if (should_wake) - wake(); + wake(ms); } /* @@ -1241,20 +1242,11 @@ static int __init dm_mirror_init(void) if (r) return r; - _kmirrord_wq = create_singlethread_workqueue("kmirrord"); - if (!_kmirrord_wq) { - DMERR("couldn't start kmirrord"); - dm_dirty_log_exit(); - return r; - } - INIT_WORK(&_kmirrord_work, do_work, NULL); - r = dm_register_target(&mirror_target); if (r < 0) { DMERR("%s: Failed to register mirror target", mirror_target.name); dm_dirty_log_exit(); - destroy_workqueue(_kmirrord_wq); } return r; @@ -1268,7 +1260,6 @@ static void __exit dm_mirror_exit(void) if (r < 0) DMERR("%s: unregister failed %d", mirror_target.name, r); - destroy_workqueue(_kmirrord_wq); dm_dirty_log_exit(); }