aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/drbd/drbd_nl.c6
-rw-r--r--drivers/block/drbd/drbd_worker.c15
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();