Commit 3be260cc authored by NeilBrown's avatar NeilBrown

md/linear: remove rcu protections in favour of suspend/resume

The use of 'rcu' to protect accesses to ->private_data so that
the ->private_data could be updated predates the introduction
of mddev_suspend/mddev_resume.
These are a cleaner mechanism for providing stability while
swapping in a new ->private data - it is used by level_store()
to support changing of raid levels.

So get rid of the RCU stuff and just use mddev_suspend, mddev_resume.

As these function call ->quiesce(), we add an empty function for
linear just like for raid0.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent 64590f45
...@@ -34,7 +34,7 @@ static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector) ...@@ -34,7 +34,7 @@ static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector)
lo = 0; lo = 0;
hi = mddev->raid_disks - 1; hi = mddev->raid_disks - 1;
conf = rcu_dereference(mddev->private); conf = mddev->private;
/* /*
* Binary Search * Binary Search
...@@ -70,7 +70,6 @@ static int linear_mergeable_bvec(struct mddev *mddev, ...@@ -70,7 +70,6 @@ static int linear_mergeable_bvec(struct mddev *mddev,
int maxbytes = biovec->bv_len; int maxbytes = biovec->bv_len;
struct request_queue *subq; struct request_queue *subq;
rcu_read_lock();
dev0 = which_dev(mddev, sector); dev0 = which_dev(mddev, sector);
maxsectors = dev0->end_sector - sector; maxsectors = dev0->end_sector - sector;
subq = bdev_get_queue(dev0->rdev->bdev); subq = bdev_get_queue(dev0->rdev->bdev);
...@@ -80,7 +79,6 @@ static int linear_mergeable_bvec(struct mddev *mddev, ...@@ -80,7 +79,6 @@ static int linear_mergeable_bvec(struct mddev *mddev,
maxbytes = min(maxbytes, subq->merge_bvec_fn(subq, bvm, maxbytes = min(maxbytes, subq->merge_bvec_fn(subq, bvm,
biovec)); biovec));
} }
rcu_read_unlock();
if (maxsectors < bio_sectors) if (maxsectors < bio_sectors)
maxsectors = 0; maxsectors = 0;
...@@ -101,15 +99,13 @@ static int linear_congested(struct mddev *mddev, int bits) ...@@ -101,15 +99,13 @@ static int linear_congested(struct mddev *mddev, int bits)
struct linear_conf *conf; struct linear_conf *conf;
int i, ret = 0; int i, ret = 0;
rcu_read_lock(); conf = mddev->private;
conf = rcu_dereference(mddev->private);
for (i = 0; i < mddev->raid_disks && !ret ; i++) { for (i = 0; i < mddev->raid_disks && !ret ; i++) {
struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev); struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
ret |= bdi_congested(&q->backing_dev_info, bits); ret |= bdi_congested(&q->backing_dev_info, bits);
} }
rcu_read_unlock();
return ret; return ret;
} }
...@@ -118,12 +114,10 @@ static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disk ...@@ -118,12 +114,10 @@ static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disk
struct linear_conf *conf; struct linear_conf *conf;
sector_t array_sectors; sector_t array_sectors;
rcu_read_lock(); conf = mddev->private;
conf = rcu_dereference(mddev->private);
WARN_ONCE(sectors || raid_disks, WARN_ONCE(sectors || raid_disks,
"%s does not support generic reshape\n", __func__); "%s does not support generic reshape\n", __func__);
array_sectors = conf->array_sectors; array_sectors = conf->array_sectors;
rcu_read_unlock();
return array_sectors; return array_sectors;
} }
...@@ -243,33 +237,22 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev) ...@@ -243,33 +237,22 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
if (!newconf) if (!newconf)
return -ENOMEM; return -ENOMEM;
oldconf = rcu_dereference_protected(mddev->private, mddev_suspend(mddev);
lockdep_is_held( oldconf = mddev->private;
&mddev->reconfig_mutex));
mddev->raid_disks++; mddev->raid_disks++;
rcu_assign_pointer(mddev->private, newconf); mddev->private = newconf;
md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
set_capacity(mddev->gendisk, mddev->array_sectors); set_capacity(mddev->gendisk, mddev->array_sectors);
mddev_resume(mddev);
revalidate_disk(mddev->gendisk); revalidate_disk(mddev->gendisk);
kfree_rcu(oldconf, rcu); kfree(oldconf);
return 0; return 0;
} }
static int linear_stop (struct mddev *mddev) static int linear_stop (struct mddev *mddev)
{ {
struct linear_conf *conf = struct linear_conf *conf = mddev->private;
rcu_dereference_protected(mddev->private,
lockdep_is_held(
&mddev->reconfig_mutex));
/*
* We do not require rcu protection here since
* we hold reconfig_mutex for both linear_add and
* linear_stop, so they cannot race.
* We should make sure any old 'conf's are properly
* freed though.
*/
rcu_barrier();
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf); kfree(conf);
mddev->private = NULL; mddev->private = NULL;
...@@ -290,16 +273,12 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio) ...@@ -290,16 +273,12 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)
} }
do { do {
rcu_read_lock();
tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector); tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector);
start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
end_sector = tmp_dev->end_sector; end_sector = tmp_dev->end_sector;
data_offset = tmp_dev->rdev->data_offset; data_offset = tmp_dev->rdev->data_offset;
bio->bi_bdev = tmp_dev->rdev->bdev; bio->bi_bdev = tmp_dev->rdev->bdev;
rcu_read_unlock();
if (unlikely(bio->bi_iter.bi_sector >= end_sector || if (unlikely(bio->bi_iter.bi_sector >= end_sector ||
bio->bi_iter.bi_sector < start_sector)) bio->bi_iter.bi_sector < start_sector))
goto out_of_bounds; goto out_of_bounds;
...@@ -346,6 +325,10 @@ static void linear_status (struct seq_file *seq, struct mddev *mddev) ...@@ -346,6 +325,10 @@ static void linear_status (struct seq_file *seq, struct mddev *mddev)
seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2); seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
} }
static void linear_quiesce(struct mddev *mddev, int state)
{
}
static struct md_personality linear_personality = static struct md_personality linear_personality =
{ {
.name = "linear", .name = "linear",
...@@ -357,6 +340,7 @@ static struct md_personality linear_personality = ...@@ -357,6 +340,7 @@ static struct md_personality linear_personality =
.status = linear_status, .status = linear_status,
.hot_add_disk = linear_add, .hot_add_disk = linear_add,
.size = linear_size, .size = linear_size,
.quiesce = linear_quiesce,
.congested = linear_congested, .congested = linear_congested,
.mergeable_bvec = linear_mergeable_bvec, .mergeable_bvec = linear_mergeable_bvec,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment