diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 70 |
1 files changed, 63 insertions, 7 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index bad324171cad..65814b0340cb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -274,6 +274,7 @@ static mddev_t * mddev_find(dev_t unit) | |||
274 | atomic_set(&new->active, 1); | 274 | atomic_set(&new->active, 1); |
275 | spin_lock_init(&new->write_lock); | 275 | spin_lock_init(&new->write_lock); |
276 | init_waitqueue_head(&new->sb_wait); | 276 | init_waitqueue_head(&new->sb_wait); |
277 | new->reshape_position = MaxSector; | ||
277 | 278 | ||
278 | new->queue = blk_alloc_queue(GFP_KERNEL); | 279 | new->queue = blk_alloc_queue(GFP_KERNEL); |
279 | if (!new->queue) { | 280 | if (!new->queue) { |
@@ -2242,6 +2243,10 @@ static ssize_t | |||
2242 | layout_show(mddev_t *mddev, char *page) | 2243 | layout_show(mddev_t *mddev, char *page) |
2243 | { | 2244 | { |
2244 | /* just a number, not meaningful for all levels */ | 2245 | /* just a number, not meaningful for all levels */ |
2246 | if (mddev->reshape_position != MaxSector && | ||
2247 | mddev->layout != mddev->new_layout) | ||
2248 | return sprintf(page, "%d (%d)\n", | ||
2249 | mddev->new_layout, mddev->layout); | ||
2245 | return sprintf(page, "%d\n", mddev->layout); | 2250 | return sprintf(page, "%d\n", mddev->layout); |
2246 | } | 2251 | } |
2247 | 2252 | ||
@@ -2250,13 +2255,16 @@ layout_store(mddev_t *mddev, const char *buf, size_t len) | |||
2250 | { | 2255 | { |
2251 | char *e; | 2256 | char *e; |
2252 | unsigned long n = simple_strtoul(buf, &e, 10); | 2257 | unsigned long n = simple_strtoul(buf, &e, 10); |
2253 | if (mddev->pers) | ||
2254 | return -EBUSY; | ||
2255 | 2258 | ||
2256 | if (!*buf || (*e && *e != '\n')) | 2259 | if (!*buf || (*e && *e != '\n')) |
2257 | return -EINVAL; | 2260 | return -EINVAL; |
2258 | 2261 | ||
2259 | mddev->layout = n; | 2262 | if (mddev->pers) |
2263 | return -EBUSY; | ||
2264 | if (mddev->reshape_position != MaxSector) | ||
2265 | mddev->new_layout = n; | ||
2266 | else | ||
2267 | mddev->layout = n; | ||
2260 | return len; | 2268 | return len; |
2261 | } | 2269 | } |
2262 | static struct md_sysfs_entry md_layout = | 2270 | static struct md_sysfs_entry md_layout = |
@@ -2268,6 +2276,10 @@ raid_disks_show(mddev_t *mddev, char *page) | |||
2268 | { | 2276 | { |
2269 | if (mddev->raid_disks == 0) | 2277 | if (mddev->raid_disks == 0) |
2270 | return 0; | 2278 | return 0; |
2279 | if (mddev->reshape_position != MaxSector && | ||
2280 | mddev->delta_disks != 0) | ||
2281 | return sprintf(page, "%d (%d)\n", mddev->raid_disks, | ||
2282 | mddev->raid_disks - mddev->delta_disks); | ||
2271 | return sprintf(page, "%d\n", mddev->raid_disks); | 2283 | return sprintf(page, "%d\n", mddev->raid_disks); |
2272 | } | 2284 | } |
2273 | 2285 | ||
@@ -2285,7 +2297,11 @@ raid_disks_store(mddev_t *mddev, const char *buf, size_t len) | |||
2285 | 2297 | ||
2286 | if (mddev->pers) | 2298 | if (mddev->pers) |
2287 | rv = update_raid_disks(mddev, n); | 2299 | rv = update_raid_disks(mddev, n); |
2288 | else | 2300 | else if (mddev->reshape_position != MaxSector) { |
2301 | int olddisks = mddev->raid_disks - mddev->delta_disks; | ||
2302 | mddev->delta_disks = n - olddisks; | ||
2303 | mddev->raid_disks = n; | ||
2304 | } else | ||
2289 | mddev->raid_disks = n; | 2305 | mddev->raid_disks = n; |
2290 | return rv ? rv : len; | 2306 | return rv ? rv : len; |
2291 | } | 2307 | } |
@@ -2295,6 +2311,10 @@ __ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store); | |||
2295 | static ssize_t | 2311 | static ssize_t |
2296 | chunk_size_show(mddev_t *mddev, char *page) | 2312 | chunk_size_show(mddev_t *mddev, char *page) |
2297 | { | 2313 | { |
2314 | if (mddev->reshape_position != MaxSector && | ||
2315 | mddev->chunk_size != mddev->new_chunk) | ||
2316 | return sprintf(page, "%d (%d)\n", mddev->new_chunk, | ||
2317 | mddev->chunk_size); | ||
2298 | return sprintf(page, "%d\n", mddev->chunk_size); | 2318 | return sprintf(page, "%d\n", mddev->chunk_size); |
2299 | } | 2319 | } |
2300 | 2320 | ||
@@ -2305,12 +2325,15 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len) | |||
2305 | char *e; | 2325 | char *e; |
2306 | unsigned long n = simple_strtoul(buf, &e, 10); | 2326 | unsigned long n = simple_strtoul(buf, &e, 10); |
2307 | 2327 | ||
2308 | if (mddev->pers) | ||
2309 | return -EBUSY; | ||
2310 | if (!*buf || (*e && *e != '\n')) | 2328 | if (!*buf || (*e && *e != '\n')) |
2311 | return -EINVAL; | 2329 | return -EINVAL; |
2312 | 2330 | ||
2313 | mddev->chunk_size = n; | 2331 | if (mddev->pers) |
2332 | return -EBUSY; | ||
2333 | else if (mddev->reshape_position != MaxSector) | ||
2334 | mddev->new_chunk = n; | ||
2335 | else | ||
2336 | mddev->chunk_size = n; | ||
2314 | return len; | 2337 | return len; |
2315 | } | 2338 | } |
2316 | static struct md_sysfs_entry md_chunk_size = | 2339 | static struct md_sysfs_entry md_chunk_size = |
@@ -2896,6 +2919,37 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) | |||
2896 | static struct md_sysfs_entry md_suspend_hi = | 2919 | static struct md_sysfs_entry md_suspend_hi = |
2897 | __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); | 2920 | __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); |
2898 | 2921 | ||
2922 | static ssize_t | ||
2923 | reshape_position_show(mddev_t *mddev, char *page) | ||
2924 | { | ||
2925 | if (mddev->reshape_position != MaxSector) | ||
2926 | return sprintf(page, "%llu\n", | ||
2927 | (unsigned long long)mddev->reshape_position); | ||
2928 | strcpy(page, "none\n"); | ||
2929 | return 5; | ||
2930 | } | ||
2931 | |||
2932 | static ssize_t | ||
2933 | reshape_position_store(mddev_t *mddev, const char *buf, size_t len) | ||
2934 | { | ||
2935 | char *e; | ||
2936 | unsigned long long new = simple_strtoull(buf, &e, 10); | ||
2937 | if (mddev->pers) | ||
2938 | return -EBUSY; | ||
2939 | if (buf == e || (*e && *e != '\n')) | ||
2940 | return -EINVAL; | ||
2941 | mddev->reshape_position = new; | ||
2942 | mddev->delta_disks = 0; | ||
2943 | mddev->new_level = mddev->level; | ||
2944 | mddev->new_layout = mddev->layout; | ||
2945 | mddev->new_chunk = mddev->chunk_size; | ||
2946 | return len; | ||
2947 | } | ||
2948 | |||
2949 | static struct md_sysfs_entry md_reshape_position = | ||
2950 | __ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show, | ||
2951 | reshape_position_store); | ||
2952 | |||
2899 | 2953 | ||
2900 | static struct attribute *md_default_attrs[] = { | 2954 | static struct attribute *md_default_attrs[] = { |
2901 | &md_level.attr, | 2955 | &md_level.attr, |
@@ -2908,6 +2962,7 @@ static struct attribute *md_default_attrs[] = { | |||
2908 | &md_new_device.attr, | 2962 | &md_new_device.attr, |
2909 | &md_safe_delay.attr, | 2963 | &md_safe_delay.attr, |
2910 | &md_array_state.attr, | 2964 | &md_array_state.attr, |
2965 | &md_reshape_position.attr, | ||
2911 | NULL, | 2966 | NULL, |
2912 | }; | 2967 | }; |
2913 | 2968 | ||
@@ -3446,6 +3501,7 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3446 | mddev->size = 0; | 3501 | mddev->size = 0; |
3447 | mddev->raid_disks = 0; | 3502 | mddev->raid_disks = 0; |
3448 | mddev->recovery_cp = 0; | 3503 | mddev->recovery_cp = 0; |
3504 | mddev->reshape_position = MaxSector; | ||
3449 | 3505 | ||
3450 | } else if (mddev->pers) | 3506 | } else if (mddev->pers) |
3451 | printk(KERN_INFO "md: %s switched to read-only mode.\n", | 3507 | printk(KERN_INFO "md: %s switched to read-only mode.\n", |