diff options
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 6 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 15 |
2 files changed, 18 insertions, 3 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 39e9a91a8f31..9e3f441e7e84 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -1381,6 +1381,12 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | |||
1381 | goto fail; | 1381 | goto fail; |
1382 | } | 1382 | } |
1383 | 1383 | ||
1384 | write_lock_irq(&global_state_lock); | ||
1385 | retcode = drbd_resync_after_valid(mdev, new_disk_conf->resync_after); | ||
1386 | write_unlock_irq(&global_state_lock); | ||
1387 | if (retcode != NO_ERROR) | ||
1388 | goto fail; | ||
1389 | |||
1384 | rcu_read_lock(); | 1390 | rcu_read_lock(); |
1385 | nc = rcu_dereference(mdev->tconn->net_conf); | 1391 | nc = rcu_dereference(mdev->tconn->net_conf); |
1386 | if (nc) { | 1392 | if (nc) { |
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 7f51f88b0a80..891c0ecaa292 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -1426,7 +1426,7 @@ static int _drbd_may_sync_now(struct drbd_conf *mdev) | |||
1426 | int resync_after; | 1426 | int resync_after; |
1427 | 1427 | ||
1428 | while (1) { | 1428 | while (1) { |
1429 | if (!odev->ldev) | 1429 | if (!odev->ldev || odev->state.disk == D_DISKLESS) |
1430 | return 1; | 1430 | return 1; |
1431 | rcu_read_lock(); | 1431 | rcu_read_lock(); |
1432 | resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after; | 1432 | resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after; |
@@ -1434,7 +1434,7 @@ static int _drbd_may_sync_now(struct drbd_conf *mdev) | |||
1434 | if (resync_after == -1) | 1434 | if (resync_after == -1) |
1435 | return 1; | 1435 | return 1; |
1436 | odev = minor_to_mdev(resync_after); | 1436 | odev = minor_to_mdev(resync_after); |
1437 | if (!expect(odev)) | 1437 | if (!odev) |
1438 | return 1; | 1438 | return 1; |
1439 | if ((odev->state.conn >= C_SYNC_SOURCE && | 1439 | if ((odev->state.conn >= C_SYNC_SOURCE && |
1440 | odev->state.conn <= C_PAUSED_SYNC_T) || | 1440 | odev->state.conn <= C_PAUSED_SYNC_T) || |
@@ -1516,7 +1516,7 @@ enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor) | |||
1516 | 1516 | ||
1517 | if (o_minor == -1) | 1517 | if (o_minor == -1) |
1518 | return NO_ERROR; | 1518 | return NO_ERROR; |
1519 | if (o_minor < -1 || minor_to_mdev(o_minor) == NULL) | 1519 | if (o_minor < -1 || o_minor > MINORMASK) |
1520 | return ERR_RESYNC_AFTER; | 1520 | return ERR_RESYNC_AFTER; |
1521 | 1521 | ||
1522 | /* check for loops */ | 1522 | /* check for loops */ |
@@ -1525,6 +1525,15 @@ enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor) | |||
1525 | if (odev == mdev) | 1525 | if (odev == mdev) |
1526 | return ERR_RESYNC_AFTER_CYCLE; | 1526 | return ERR_RESYNC_AFTER_CYCLE; |
1527 | 1527 | ||
1528 | /* You are free to depend on diskless, non-existing, | ||
1529 | * or not yet/no longer existing minors. | ||
1530 | * We only reject dependency loops. | ||
1531 | * We cannot follow the dependency chain beyond a detached or | ||
1532 | * missing minor. | ||
1533 | */ | ||
1534 | if (!odev || !odev->ldev || odev->state.disk == D_DISKLESS) | ||
1535 | return NO_ERROR; | ||
1536 | |||
1528 | rcu_read_lock(); | 1537 | rcu_read_lock(); |
1529 | resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after; | 1538 | resync_after = rcu_dereference(odev->ldev->disk_conf)->resync_after; |
1530 | rcu_read_unlock(); | 1539 | rcu_read_unlock(); |