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: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
64590f45dd
commit
3be260cc18
|
@ -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,
|
||||||
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,
|
||||||
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)
|
||||||
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
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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 =
|
||||||
.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,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue