Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 139933
b: refs/heads/master
c: b522adc
h: refs/heads/master
i:
  139931: 535644f
v: v3
  • Loading branch information
Dan Williams committed Mar 31, 2009
1 parent 48e9b24 commit 200bc8c
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1f403624bde3c678a166984b1e6a727a0ce06f2b
refs/heads/master: b522adcde9c4d3fb7b579cfa9160d8bde7744be8
112 changes: 105 additions & 7 deletions trunk/drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ static inline int mddev_lock(mddev_t * mddev)
return mutex_lock_interruptible(&mddev->reconfig_mutex);
}

static inline int mddev_is_locked(mddev_t *mddev)
{
return mutex_is_locked(&mddev->reconfig_mutex);
}

static inline int mddev_trylock(mddev_t * mddev)
{
return mutex_trylock(&mddev->reconfig_mutex);
Expand Down Expand Up @@ -2282,16 +2287,34 @@ static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2)
return 1;
}

static int strict_blocks_to_sectors(const char *buf, sector_t *sectors)
{
unsigned long long blocks;
sector_t new;

if (strict_strtoull(buf, 10, &blocks) < 0)
return -EINVAL;

if (blocks & 1ULL << (8 * sizeof(blocks) - 1))
return -EINVAL; /* sector conversion overflow */

new = blocks * 2;
if (new != blocks * 2)
return -EINVAL; /* unsigned long long to sector_t overflow */

*sectors = new;
return 0;
}

static ssize_t
rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
{
mddev_t *my_mddev = rdev->mddev;
sector_t oldsectors = rdev->sectors;
unsigned long long sectors;
sector_t sectors;

if (strict_strtoull(buf, 10, &sectors) < 0)
if (strict_blocks_to_sectors(buf, &sectors) < 0)
return -EINVAL;
sectors *= 2;
if (my_mddev->pers && rdev->raid_disk >= 0) {
if (my_mddev->persistent) {
sectors = super_types[my_mddev->major_version].
Expand Down Expand Up @@ -3182,12 +3205,11 @@ size_store(mddev_t *mddev, const char *buf, size_t len)
* not increase it (except from 0).
* If array is active, we can try an on-line resize
*/
unsigned long long sectors;
int err = strict_strtoull(buf, 10, &sectors);
sector_t sectors;
int err = strict_blocks_to_sectors(buf, &sectors);

if (err < 0)
return err;
sectors *= 2;
if (mddev->pers) {
err = update_size(mddev, sectors);
md_update_sb(mddev, 1);
Expand Down Expand Up @@ -3627,6 +3649,57 @@ static struct md_sysfs_entry md_reshape_position =
__ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show,
reshape_position_store);

static ssize_t
array_size_show(mddev_t *mddev, char *page)
{
if (mddev->external_size)
return sprintf(page, "%llu\n",
(unsigned long long)mddev->array_sectors/2);
else
return sprintf(page, "default\n");
}

static ssize_t
array_size_store(mddev_t *mddev, const char *buf, size_t len)
{
sector_t sectors;

if (strncmp(buf, "default", 7) == 0) {
if (mddev->pers)
sectors = mddev->pers->size(mddev, 0, 0);
else
sectors = mddev->array_sectors;

mddev->external_size = 0;
} else {
if (strict_blocks_to_sectors(buf, &sectors) < 0)
return -EINVAL;
if (mddev->pers && mddev->pers->size(mddev, 0, 0) < sectors)
return -EINVAL;

mddev->external_size = 1;
}

mddev->array_sectors = sectors;
set_capacity(mddev->gendisk, mddev->array_sectors);
if (mddev->pers) {
struct block_device *bdev = bdget_disk(mddev->gendisk, 0);

if (bdev) {
mutex_lock(&bdev->bd_inode->i_mutex);
i_size_write(bdev->bd_inode,
(loff_t)mddev->array_sectors << 9);
mutex_unlock(&bdev->bd_inode->i_mutex);
bdput(bdev);
}
}

return len;
}

static struct md_sysfs_entry md_array_size =
__ATTR(array_size, S_IRUGO|S_IWUSR, array_size_show,
array_size_store);

static struct attribute *md_default_attrs[] = {
&md_level.attr,
Expand All @@ -3640,6 +3713,7 @@ static struct attribute *md_default_attrs[] = {
&md_safe_delay.attr,
&md_array_state.attr,
&md_reshape_position.attr,
&md_array_size.attr,
NULL,
};

Expand Down Expand Up @@ -4045,7 +4119,17 @@ static int do_md_run(mddev_t * mddev)
err = mddev->pers->run(mddev);
if (err)
printk(KERN_ERR "md: pers->run() failed ...\n");
else if (mddev->pers->sync_request) {
else if (mddev->pers->size(mddev, 0, 0) < mddev->array_sectors) {
WARN_ONCE(!mddev->external_size, "%s: default size too small,"
" but 'external_size' not in effect?\n", __func__);
printk(KERN_ERR
"md: invalid array_size %llu > default size %llu\n",
(unsigned long long)mddev->array_sectors / 2,
(unsigned long long)mddev->pers->size(mddev, 0, 0) / 2);
err = -EINVAL;
mddev->pers->stop(mddev);
}
if (err == 0 && mddev->pers->sync_request) {
err = bitmap_create(mddev);
if (err) {
printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
Expand Down Expand Up @@ -4281,6 +4365,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
export_array(mddev);

mddev->array_sectors = 0;
mddev->external_size = 0;
mddev->dev_sectors = 0;
mddev->raid_disks = 0;
mddev->recovery_cp = 0;
Expand Down Expand Up @@ -4979,10 +5064,23 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)

void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors)
{
WARN(!mddev_is_locked(mddev), "%s: unlocked mddev!\n", __func__);

if (mddev->external_size)
return;

mddev->array_sectors = array_sectors;
}
EXPORT_SYMBOL(md_set_array_sectors);

void md_set_array_sectors_lock(mddev_t *mddev, sector_t array_sectors)
{
mddev_lock(mddev);
md_set_array_sectors(mddev, array_sectors);
mddev_unlock(mddev);
}
EXPORT_SYMBOL(md_set_array_sectors_lock);

static int update_size(mddev_t *mddev, sector_t num_sectors)
{
mdk_rdev_t *rdev;
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/md/md.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ struct mddev_s
sector_t dev_sectors; /* used size of
* component devices */
sector_t array_sectors; /* exported array size */
int external_size; /* size managed
* externally */
__u64 events;

char uuid[16];
Expand Down Expand Up @@ -431,3 +433,4 @@ extern void md_new_event(mddev_t *mddev);
extern int md_allow_write(mddev_t *mddev);
extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
extern void md_set_array_sectors_lock(mddev_t *mddev, sector_t array_sectors);
2 changes: 1 addition & 1 deletion trunk/drivers/md/raid0.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ static int raid0_run (mddev_t *mddev)
printk(KERN_INFO "raid0 : conf->spacing is %llu sectors.\n",
(unsigned long long)conf->spacing);
{
sector_t s = mddev->array_sectors;
sector_t s = raid0_size(mddev, 0, 0);
sector_t space = conf->spacing;
int round;
conf->sector_shift = 0;
Expand Down
6 changes: 4 additions & 2 deletions trunk/drivers/md/raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -2125,14 +2125,16 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
* worth it.
*/
md_set_array_sectors(mddev, raid1_size(mddev, sectors, 0));
if (mddev->array_sectors > raid1_size(mddev, sectors, 0))
return -EINVAL;
set_capacity(mddev->gendisk, mddev->array_sectors);
mddev->changed = 1;
if (mddev->array_sectors > mddev->dev_sectors &&
if (sectors > mddev->dev_sectors &&
mddev->recovery_cp == MaxSector) {
mddev->recovery_cp = mddev->dev_sectors;
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
}
mddev->dev_sectors = mddev->array_sectors;
mddev->dev_sectors = sectors;
mddev->resync_max_sectors = sectors;
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/md/raid10.c
Original file line number Diff line number Diff line change
Expand Up @@ -2194,7 +2194,7 @@ static int run(mddev_t *mddev)
* Ok, everything is just fine now
*/
md_set_array_sectors(mddev, raid10_size(mddev, 0, 0));
mddev->resync_max_sectors = mddev->array_sectors;
mddev->resync_max_sectors = raid10_size(mddev, 0, 0);

mddev->queue->unplug_fn = raid10_unplug;
mddev->queue->backing_dev_info.congested_fn = raid10_congested;
Expand Down
9 changes: 7 additions & 2 deletions trunk/drivers/md/raid5.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 200bc8c

Please sign in to comment.