Hi, Am Freitag, 27. Juni 2008 08:51 schrieb NeilBrown: > From: Chris Webb <chris@xxxxxxxxxxxx> > Allow /sys/block/mdX/md/rdY/size to change on running arrays, moving the > superblock if necessary for this metadata version. We prevent the available > space from shrinking to less than the used size, and allow it to be set to > zero to fill all the available space on the underlying device. I'm very happy of this new feature. But I'm a little confused how to use it correctly. Can md now recognize the change by itself and I only have to run mdadm --grow? Or have I manually update /sys/block/mdX/md/rdY/size and afterwards run mdadm --grow? To be on the safe side I'd first lvresize one disk of the raid1, then do mdadm --grow to let md update/move the superblock of this disk. And after this is successful, lvresize the other disk and do mdadm --grow. So in case of a failure i wouldn't loose the whole raid1!? Am I correct or am I missing something? > Signed-off-by: Chris Webb <chris@xxxxxxxxxxxx> > Signed-off-by: Neil Brown <neilb@xxxxxxx> > > ### Diffstat output > ./drivers/md/md.c | 100 > ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 87 > insertions(+), 13 deletions(-) > > diff .prev/drivers/md/md.c ./drivers/md/md.c > --- .prev/drivers/md/md.c 2008-06-27 16:22:03.000000000 +1000 > +++ ./drivers/md/md.c 2008-06-27 16:22:03.000000000 +1000 > @@ -658,11 +658,14 @@ static unsigned int calc_sb_csum(mdp_sup > */ > > struct super_type { > - char *name; > - struct module *owner; > - int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int > minor_version); - int (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev); > - void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev); > + char *name; > + struct module *owner; > + int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev, > + int minor_version); > + int (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev); > + void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev); > + unsigned long long (*rdev_size_change)(mdk_rdev_t *rdev, > + unsigned long long size); > }; > > /* > @@ -1004,6 +1007,27 @@ static void super_90_sync(mddev_t *mddev > } > > /* > + * rdev_size_change for 0.90.0 > + */ > +static unsigned long long > +super_90_rdev_size_change(mdk_rdev_t *rdev, unsigned long long size) > +{ > + if (size && size < rdev->mddev->size) > + return 0; /* component must fit device */ > + size *= 2; /* convert to sectors */ > + if (rdev->mddev->bitmap_offset) > + return 0; /* can't move bitmap */ > + rdev->sb_offset = calc_dev_sboffset(rdev->bdev); > + if (!size || size > rdev->sb_offset*2) > + size = rdev->sb_offset*2; > + md_super_write(rdev->mddev, rdev, rdev->sb_offset << 1, rdev->sb_size, > + rdev->sb_page); > + md_super_wait(rdev->mddev); > + return size/2; /* kB for sysfs */ > +} > + > + > +/* > * version 1 superblock > */ > > @@ -1328,21 +1352,59 @@ static void super_1_sync(mddev_t *mddev, > sb->sb_csum = calc_sb_1_csum(sb); > } > > +static unsigned long long > +super_1_rdev_size_change(mdk_rdev_t *rdev, unsigned long long size) > +{ > + struct mdp_superblock_1 *sb; > + unsigned long long max_size; > + if (size && size < rdev->mddev->size) > + return 0; /* component must fit device */ > + size *= 2; /* convert to sectors */ > + if (rdev->sb_offset < rdev->data_offset/2) { > + /* minor versions 1 and 2; superblock before data */ > + max_size = (rdev->bdev->bd_inode->i_size >> 9); > + max_size -= rdev->data_offset; > + if (!size || size > max_size) > + size = max_size; > + } else if (rdev->mddev->bitmap_offset) { > + /* minor version 0 with bitmap we can't move */ > + return 0; > + } else { > + /* minor version 0; superblock after data */ > + sector_t sb_offset; > + sb_offset = (rdev->bdev->bd_inode->i_size >> 9) - 8*2; > + sb_offset &= ~(sector_t)(4*2 - 1); > + max_size = rdev->size*2 + sb_offset - rdev->sb_offset*2; > + if (!size || size > max_size) > + size = max_size; > + rdev->sb_offset = sb_offset/2; > + } > + sb = (struct mdp_superblock_1 *) page_address(rdev->sb_page); > + sb->data_size = cpu_to_le64(size); > + sb->super_offset = rdev->sb_offset*2; > + sb->sb_csum = calc_sb_1_csum(sb); > + md_super_write(rdev->mddev, rdev, rdev->sb_offset << 1, rdev->sb_size, > + rdev->sb_page); > + md_super_wait(rdev->mddev); > + return size/2; /* kB for sysfs */ > +} > > static struct super_type super_types[] = { > [0] = { > .name = "0.90.0", > .owner = THIS_MODULE, > - .load_super = super_90_load, > - .validate_super = super_90_validate, > - .sync_super = super_90_sync, > + .load_super = super_90_load, > + .validate_super = super_90_validate, > + .sync_super = super_90_sync, > + .rdev_size_change = super_90_rdev_size_change, > }, > [1] = { > .name = "md-1", > .owner = THIS_MODULE, > - .load_super = super_1_load, > - .validate_super = super_1_validate, > - .sync_super = super_1_sync, > + .load_super = super_1_load, > + .validate_super = super_1_validate, > + .sync_super = super_1_sync, > + .rdev_size_change = super_1_rdev_size_change, > }, > }; > > @@ -2060,8 +2122,20 @@ rdev_size_store(mdk_rdev_t *rdev, const > > if (e==buf || (*e && *e != '\n')) > return -EINVAL; > - if (my_mddev->pers && rdev->raid_disk >= 0) > - return -EBUSY; > + if (my_mddev->pers && rdev->raid_disk >= 0) { > + if (rdev->mddev->persistent) { > + size = super_types[rdev->mddev->major_version]. > + rdev_size_change(rdev, size); > + if (!size) > + return -EBUSY; > + } else if (!size) { > + size = (rdev->bdev->bd_inode->i_size >> 10); > + size -= rdev->data_offset/2; > + } > + if (size < rdev->mddev->size) > + return -EINVAL; /* component must fit device */ > + } > + > rdev->size = size; > if (size > oldsize && rdev->mddev->external) { > /* need to check that all other rdevs with the same ->bdev > -- > To unsubscribe from this list: send the line "unsubscribe linux-raid" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- greetings eMHa
Attachment:
pgp50jVVdjA9P.pgp
Description: PGP signature