diff options
| -rw-r--r-- | drivers/md/md.c | 62 |
1 files changed, 32 insertions, 30 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 2920fd004865..58f531f8dcc2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -3280,9 +3280,9 @@ level_store(struct mddev *mddev, const char *buf, size_t len) | |||
| 3280 | { | 3280 | { |
| 3281 | char clevel[16]; | 3281 | char clevel[16]; |
| 3282 | ssize_t rv = len; | 3282 | ssize_t rv = len; |
| 3283 | struct md_personality *pers; | 3283 | struct md_personality *pers, *oldpers; |
| 3284 | long level; | 3284 | long level; |
| 3285 | void *priv; | 3285 | void *priv, *oldpriv; |
| 3286 | struct md_rdev *rdev; | 3286 | struct md_rdev *rdev; |
| 3287 | 3287 | ||
| 3288 | if (mddev->pers == NULL) { | 3288 | if (mddev->pers == NULL) { |
| @@ -3374,9 +3374,35 @@ level_store(struct mddev *mddev, const char *buf, size_t len) | |||
| 3374 | /* Looks like we have a winner */ | 3374 | /* Looks like we have a winner */ |
| 3375 | mddev_suspend(mddev); | 3375 | mddev_suspend(mddev); |
| 3376 | mddev_detach(mddev); | 3376 | mddev_detach(mddev); |
| 3377 | mddev->pers->free(mddev, mddev->private); | 3377 | oldpers = mddev->pers; |
| 3378 | oldpriv = mddev->private; | ||
| 3379 | mddev->pers = pers; | ||
| 3380 | mddev->private = priv; | ||
| 3381 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); | ||
| 3382 | mddev->level = mddev->new_level; | ||
| 3383 | mddev->layout = mddev->new_layout; | ||
| 3384 | mddev->chunk_sectors = mddev->new_chunk_sectors; | ||
| 3385 | mddev->delta_disks = 0; | ||
| 3386 | mddev->reshape_backwards = 0; | ||
| 3387 | mddev->degraded = 0; | ||
| 3388 | |||
| 3389 | if (oldpers->sync_request == NULL && | ||
| 3390 | mddev->external) { | ||
| 3391 | /* We are converting from a no-redundancy array | ||
| 3392 | * to a redundancy array and metadata is managed | ||
| 3393 | * externally so we need to be sure that writes | ||
| 3394 | * won't block due to a need to transition | ||
| 3395 | * clean->dirty | ||
| 3396 | * until external management is started. | ||
| 3397 | */ | ||
| 3398 | mddev->in_sync = 0; | ||
| 3399 | mddev->safemode_delay = 0; | ||
| 3400 | mddev->safemode = 0; | ||
| 3401 | } | ||
| 3378 | 3402 | ||
| 3379 | if (mddev->pers->sync_request == NULL && | 3403 | oldpers->free(mddev, oldpriv); |
| 3404 | |||
| 3405 | if (oldpers->sync_request == NULL && | ||
| 3380 | pers->sync_request != NULL) { | 3406 | pers->sync_request != NULL) { |
| 3381 | /* need to add the md_redundancy_group */ | 3407 | /* need to add the md_redundancy_group */ |
| 3382 | if (sysfs_create_group(&mddev->kobj, &md_redundancy_group)) | 3408 | if (sysfs_create_group(&mddev->kobj, &md_redundancy_group)) |
| @@ -3385,27 +3411,13 @@ level_store(struct mddev *mddev, const char *buf, size_t len) | |||
| 3385 | mdname(mddev)); | 3411 | mdname(mddev)); |
| 3386 | mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action"); | 3412 | mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action"); |
| 3387 | } | 3413 | } |
| 3388 | if (mddev->pers->sync_request != NULL && | 3414 | if (oldpers->sync_request != NULL && |
| 3389 | pers->sync_request == NULL) { | 3415 | pers->sync_request == NULL) { |
| 3390 | /* need to remove the md_redundancy_group */ | 3416 | /* need to remove the md_redundancy_group */ |
| 3391 | if (mddev->to_remove == NULL) | 3417 | if (mddev->to_remove == NULL) |
| 3392 | mddev->to_remove = &md_redundancy_group; | 3418 | mddev->to_remove = &md_redundancy_group; |
| 3393 | } | 3419 | } |
| 3394 | 3420 | ||
| 3395 | if (mddev->pers->sync_request == NULL && | ||
| 3396 | mddev->external) { | ||
| 3397 | /* We are converting from a no-redundancy array | ||
| 3398 | * to a redundancy array and metadata is managed | ||
| 3399 | * externally so we need to be sure that writes | ||
| 3400 | * won't block due to a need to transition | ||
| 3401 | * clean->dirty | ||
| 3402 | * until external management is started. | ||
| 3403 | */ | ||
| 3404 | mddev->in_sync = 0; | ||
| 3405 | mddev->safemode_delay = 0; | ||
| 3406 | mddev->safemode = 0; | ||
| 3407 | } | ||
| 3408 | |||
| 3409 | rdev_for_each(rdev, mddev) { | 3421 | rdev_for_each(rdev, mddev) { |
| 3410 | if (rdev->raid_disk < 0) | 3422 | if (rdev->raid_disk < 0) |
| 3411 | continue; | 3423 | continue; |
| @@ -3431,17 +3443,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len) | |||
| 3431 | } | 3443 | } |
| 3432 | } | 3444 | } |
| 3433 | 3445 | ||
| 3434 | module_put(mddev->pers->owner); | 3446 | if (pers->sync_request == NULL) { |
| 3435 | mddev->pers = pers; | ||
| 3436 | mddev->private = priv; | ||
| 3437 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); | ||
| 3438 | mddev->level = mddev->new_level; | ||
| 3439 | mddev->layout = mddev->new_layout; | ||
| 3440 | mddev->chunk_sectors = mddev->new_chunk_sectors; | ||
| 3441 | mddev->delta_disks = 0; | ||
| 3442 | mddev->reshape_backwards = 0; | ||
| 3443 | mddev->degraded = 0; | ||
| 3444 | if (mddev->pers->sync_request == NULL) { | ||
| 3445 | /* this is now an array without redundancy, so | 3447 | /* this is now an array without redundancy, so |
| 3446 | * it must always be in_sync | 3448 | * it must always be in_sync |
| 3447 | */ | 3449 | */ |
