Commit a35b0d695d44410eb1734c9abb632725a3138628

Authored by NeilBrown
Committed by Linus Torvalds
1 parent 3b34380ae8

[PATCH] md: allow md array component size to be accessed and set via sysfs

Signed-off-by: Neil Brown <neilb@suse.de>
Acked-by: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 2 changed files with 98 additions and 42 deletions Side-by-side Diff

Documentation/md.txt
... ... @@ -174,6 +174,15 @@
174 174 The size should be atleast PAGE_SIZE (4k) and should be a power
175 175 of 2. This can only be set while assembling an array
176 176  
  177 + component_size
  178 + For arrays with data redundancy (i.e. not raid0, linear, faulty,
  179 + multipath), all components must be the same size - or at least
  180 + there must a size that they all provide space for. This is a key
  181 + part or the geometry of the array. It is measured in sectors
  182 + and can be read from here. Writing to this value may resize
  183 + the array if the personality supports it (raid1, raid5, raid6),
  184 + and if the component drives are large enough.
  185 +
177 186 As component devices are added to an md array, they appear in the 'md'
178 187 directory as new directories named
179 188 dev-XXX
... ... @@ -1820,6 +1820,44 @@
1820 1820  
1821 1821  
1822 1822 static ssize_t
  1823 +size_show(mddev_t *mddev, char *page)
  1824 +{
  1825 + return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
  1826 +}
  1827 +
  1828 +static int update_size(mddev_t *mddev, unsigned long size);
  1829 +
  1830 +static ssize_t
  1831 +size_store(mddev_t *mddev, const char *buf, size_t len)
  1832 +{
  1833 + /* If array is inactive, we can reduce the component size, but
  1834 + * not increase it (except from 0).
  1835 + * If array is active, we can try an on-line resize
  1836 + */
  1837 + char *e;
  1838 + int err = 0;
  1839 + unsigned long long size = simple_strtoull(buf, &e, 10);
  1840 + if (!*buf || *buf == '\n' ||
  1841 + (*e && *e != '\n'))
  1842 + return -EINVAL;
  1843 +
  1844 + if (mddev->pers) {
  1845 + err = update_size(mddev, size);
  1846 + md_update_sb(mddev);
  1847 + } else {
  1848 + if (mddev->size == 0 ||
  1849 + mddev->size > size)
  1850 + mddev->size = size;
  1851 + else
  1852 + err = -ENOSPC;
  1853 + }
  1854 + return err ? err : len;
  1855 +}
  1856 +
  1857 +static struct md_sysfs_entry md_size =
  1858 +__ATTR(component_size, 0644, size_show, size_store);
  1859 +
  1860 +static ssize_t
1823 1861 action_show(mddev_t *mddev, char *page)
1824 1862 {
1825 1863 char *type = "idle";
... ... @@ -1887,6 +1925,7 @@
1887 1925 &md_level.attr,
1888 1926 &md_raid_disks.attr,
1889 1927 &md_chunk_size.attr,
  1928 + &md_size.attr,
1890 1929 NULL,
1891 1930 };
1892 1931  
... ... @@ -3005,6 +3044,54 @@
3005 3044 return 0;
3006 3045 }
3007 3046  
  3047 +static int update_size(mddev_t *mddev, unsigned long size)
  3048 +{
  3049 + mdk_rdev_t * rdev;
  3050 + int rv;
  3051 + struct list_head *tmp;
  3052 +
  3053 + if (mddev->pers->resize == NULL)
  3054 + return -EINVAL;
  3055 + /* The "size" is the amount of each device that is used.
  3056 + * This can only make sense for arrays with redundancy.
  3057 + * linear and raid0 always use whatever space is available
  3058 + * We can only consider changing the size if no resync
  3059 + * or reconstruction is happening, and if the new size
  3060 + * is acceptable. It must fit before the sb_offset or,
  3061 + * if that is <data_offset, it must fit before the
  3062 + * size of each device.
  3063 + * If size is zero, we find the largest size that fits.
  3064 + */
  3065 + if (mddev->sync_thread)
  3066 + return -EBUSY;
  3067 + ITERATE_RDEV(mddev,rdev,tmp) {
  3068 + sector_t avail;
  3069 + int fit = (size == 0);
  3070 + if (rdev->sb_offset > rdev->data_offset)
  3071 + avail = (rdev->sb_offset*2) - rdev->data_offset;
  3072 + else
  3073 + avail = get_capacity(rdev->bdev->bd_disk)
  3074 + - rdev->data_offset;
  3075 + if (fit && (size == 0 || size > avail/2))
  3076 + size = avail/2;
  3077 + if (avail < ((sector_t)size << 1))
  3078 + return -ENOSPC;
  3079 + }
  3080 + rv = mddev->pers->resize(mddev, (sector_t)size *2);
  3081 + if (!rv) {
  3082 + struct block_device *bdev;
  3083 +
  3084 + bdev = bdget_disk(mddev->gendisk, 0);
  3085 + if (bdev) {
  3086 + down(&bdev->bd_inode->i_sem);
  3087 + i_size_write(bdev->bd_inode, mddev->array_size << 10);
  3088 + up(&bdev->bd_inode->i_sem);
  3089 + bdput(bdev);
  3090 + }
  3091 + }
  3092 + return rv;
  3093 +}
  3094 +
3008 3095 /*
3009 3096 * update_array_info is used to change the configuration of an
3010 3097 * on-line array.
3011 3098  
... ... @@ -3053,49 +3140,9 @@
3053 3140 else
3054 3141 return mddev->pers->reconfig(mddev, info->layout, -1);
3055 3142 }
3056   - if (mddev->size != info->size) {
3057   - mdk_rdev_t * rdev;
3058   - struct list_head *tmp;
3059   - if (mddev->pers->resize == NULL)
3060   - return -EINVAL;
3061   - /* The "size" is the amount of each device that is used.
3062   - * This can only make sense for arrays with redundancy.
3063   - * linear and raid0 always use whatever space is available
3064   - * We can only consider changing the size if no resync
3065   - * or reconstruction is happening, and if the new size
3066   - * is acceptable. It must fit before the sb_offset or,
3067   - * if that is <data_offset, it must fit before the
3068   - * size of each device.
3069   - * If size is zero, we find the largest size that fits.
3070   - */
3071   - if (mddev->sync_thread)
3072   - return -EBUSY;
3073   - ITERATE_RDEV(mddev,rdev,tmp) {
3074   - sector_t avail;
3075   - int fit = (info->size == 0);
3076   - if (rdev->sb_offset > rdev->data_offset)
3077   - avail = (rdev->sb_offset*2) - rdev->data_offset;
3078   - else
3079   - avail = get_capacity(rdev->bdev->bd_disk)
3080   - - rdev->data_offset;
3081   - if (fit && (info->size == 0 || info->size > avail/2))
3082   - info->size = avail/2;
3083   - if (avail < ((sector_t)info->size << 1))
3084   - return -ENOSPC;
3085   - }
3086   - rv = mddev->pers->resize(mddev, (sector_t)info->size *2);
3087   - if (!rv) {
3088   - struct block_device *bdev;
  3143 + if (mddev->size != info->size)
  3144 + rv = update_size(mddev, info->size);
3089 3145  
3090   - bdev = bdget_disk(mddev->gendisk, 0);
3091   - if (bdev) {
3092   - down(&bdev->bd_inode->i_sem);
3093   - i_size_write(bdev->bd_inode, mddev->array_size << 10);
3094   - up(&bdev->bd_inode->i_sem);
3095   - bdput(bdev);
3096   - }
3097   - }
3098   - }
3099 3146 if (mddev->raid_disks != info->raid_disks) {
3100 3147 /* change the number of raid disks */
3101 3148 if (mddev->pers->reshape == NULL)