diff options
author | NeilBrown <neilb@suse.de> | 2009-03-31 14:39:39 +1100 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-03-31 14:39:39 +1100 |
commit | 409c57f3801701dfee27a28103dda4831306cb20 (patch) | |
tree | 430c8e4ebe879b27250e061dc1a1171b12aaadf0 /drivers/md/raid1.c | |
parent | e0cf8f045b2023b0b3f919ee93eb94345f648434 (diff) |
md: enable suspend/resume of md devices.
To be able to change the 'level' of an md/raid array, we need to
suspend the device so that no requests are active - then move some
pointers around etc.
The code already keeps counts of active requests and the ->quiesce
function can be used to wait until those counts hit zero.
However the quiesce function blocks new requests once they are all
ready 'inside' the personality module, and that is too late if we want
to replace the personality modules.
So make all md requests come in through a common md_make_request
function that keeps track of how many requests have entered the
modules but may not yet be on the internal reference counts.
Allow md_make_request to be blocked when we want to suspend the
device, and make it possible to wait for all those in-transit requests
to be added to internal lists so that ->quiesce can wait for them.
There is still a problem that when a request completes, we drop the
ref count inside the personality code so there is a short time between
when the refcount hits zero, and when the personality code is no
longer being used.
The personality code never blocks (schedule or spinlock) between
dropping the refcount and exiting the routine, so this should be safe
(as put_module calls synchronize_sched() before unmapping the module
code).
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r-- | drivers/md/raid1.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 779958705abf..7eaca3209364 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2092,6 +2092,9 @@ static int stop(mddev_t *mddev) /* need to kick something here to make sure I/O goes? */ } + raise_barrier(conf); + lower_barrier(conf); + md_unregister_thread(mddev->thread); mddev->thread = NULL; blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |