diff options
author | NeilBrown <neilb@suse.de> | 2009-12-14 12:49:51 +1100 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-12-14 12:51:40 +1100 |
commit | 6eef4b21ffc9207b78fdd718154f5b004644b97d (patch) | |
tree | 554d8dafa2cd8ff7a9e719b12bd2f07c9745e7be /drivers/md/raid1.c | |
parent | 729a18663a30a9c8076e3adc2b3e4c866974f935 (diff) |
md: add honouring of suspend_{lo,hi} to raid1.
This will allow us to stop writeout to portions of the array
while they are resynced by someone else - e.g. another node in
a cluster.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r-- | drivers/md/raid1.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index e07ce2e033a9..35b2d8646ae9 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -801,6 +801,25 @@ static int make_request(struct request_queue *q, struct bio * bio) md_write_start(mddev, bio); /* wait on superblock update early */ + if (bio_data_dir(bio) == WRITE && + bio->bi_sector + bio->bi_size/512 > mddev->suspend_lo && + bio->bi_sector < mddev->suspend_hi) { + /* As the suspend_* range is controlled by + * userspace, we want an interruptible + * wait. + */ + DEFINE_WAIT(w); + for (;;) { + flush_signals(current); + prepare_to_wait(&conf->wait_barrier, + &w, TASK_INTERRUPTIBLE); + if (bio->bi_sector + bio->bi_size/512 <= mddev->suspend_lo || + bio->bi_sector >= mddev->suspend_hi) + break; + schedule(); + } + finish_wait(&conf->wait_barrier, &w); + } if (unlikely(!mddev->barriers_work && bio_rw_flagged(bio, BIO_RW_BARRIER))) { if (rw == WRITE) @@ -2271,6 +2290,9 @@ static void raid1_quiesce(mddev_t *mddev, int state) conf_t *conf = mddev->private; switch(state) { + case 2: /* wake for suspend */ + wake_up(&conf->wait_barrier); + break; case 1: raise_barrier(conf); break; |