diff options
author | Dan Williams <dan.j.williams@intel.com> | 2009-03-31 15:00:31 +1100 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2009-03-31 15:00:31 +1100 |
commit | b522adcde9c4d3fb7b579cfa9160d8bde7744be8 (patch) | |
tree | 4208e3dcec3ebdfa6ad9bc153f76129400532717 /drivers/md/raid5.c | |
parent | 1f403624bde3c678a166984b1e6a727a0ce06f2b (diff) | |
download | blackbird-op-linux-b522adcde9c4d3fb7b579cfa9160d8bde7744be8.tar.gz blackbird-op-linux-b522adcde9c4d3fb7b579cfa9160d8bde7744be8.zip |
md: 'array_size' sysfs attribute
Allow userspace to set the size of the array according to the following
semantics:
1/ size must be <= to the size returned by mddev->pers->size(mddev, 0, 0)
a) If size is set before the array is running, do_md_run will fail
if size is greater than the default size
b) A reshape attempt that reduces the default size to less than the set
array size should be blocked
2/ once userspace sets the size the kernel will not change it
3/ writing 'default' to this attribute returns control of the size to the
kernel and reverts to the size reported by the personality
Also, convert locations that need to know the default size from directly
reading ->array_sectors to <pers>_size. Resync/reshape operations
always follow the default size.
Finally, fixup other locations that read a number of 1k-blocks from
userspace to use strict_blocks_to_sectors() which checks for unsigned
long long to sector_t overflow and blocks to sectors overflow.
Reviewed-by: Andre Noll <maan@systemlinux.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2930fc26a852..1aebd3ef80b7 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3703,6 +3703,8 @@ static int make_request(struct request_queue *q, struct bio * bi) return 0; } +static sector_t raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks); + static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped) { /* reshaping is quite different to recovery/resync so it is @@ -3781,7 +3783,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped j == sh->qd_idx) continue; s = compute_blocknr(sh, j); - if (s < mddev->array_sectors) { + if (s < raid5_size(mddev, 0, 0)) { skipped = 1; continue; } @@ -4700,6 +4702,9 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) sectors &= ~((sector_t)mddev->chunk_size/512 - 1); md_set_array_sectors(mddev, raid5_size(mddev, sectors, mddev->raid_disks)); + if (mddev->array_sectors > + raid5_size(mddev, sectors, mddev->raid_disks)) + return -EINVAL; set_capacity(mddev->gendisk, mddev->array_sectors); mddev->changed = 1; if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) { @@ -4837,7 +4842,7 @@ static void end_reshape(raid5_conf_t *conf) if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { mddev_t *mddev = conf->mddev; - md_set_array_sectors(mddev, raid5_size(mddev, 0, + md_set_array_sectors_lock(mddev, raid5_size(mddev, 0, conf->raid_disks)); set_capacity(mddev->gendisk, mddev->array_sectors); mddev->changed = 1; |