aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-12-14 20:56:58 -0500
committerNeilBrown <neilb@suse.de>2015-02-03 16:35:53 -0500
commitdb721d32b74b51a5ac9ec9fab1d85cba90dbdbd3 (patch)
tree84e1a94956eb212bd0313e0bb9d0f21e9ae5adef
parentafa0f557cb15176570a18fb2a093e348a793afd4 (diff)
md: level_store: group all important changes into one place.
Gather all the changes that can happen atomically and might be relevant to other code into one place. This will make it easier to refine the locking. Note that this puts quite a few things between mddev_detach() and ->free(). Enabling this was the point of some recent patches. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/md.c62
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 */