diff options
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/dlmglue.c | 37 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 6 |
2 files changed, 37 insertions, 6 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 21262f2b1654..953f4eb75fa7 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -861,8 +861,13 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo | |||
861 | * We set the OCFS2_LOCK_UPCONVERT_FINISHING flag before clearing | 861 | * We set the OCFS2_LOCK_UPCONVERT_FINISHING flag before clearing |
862 | * the OCFS2_LOCK_BUSY flag to prevent the dc thread from | 862 | * the OCFS2_LOCK_BUSY flag to prevent the dc thread from |
863 | * downconverting the lock before the upconvert has fully completed. | 863 | * downconverting the lock before the upconvert has fully completed. |
864 | * Do not prevent the dc thread from downconverting if NONBLOCK lock | ||
865 | * had already returned. | ||
864 | */ | 866 | */ |
865 | lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING); | 867 | if (!(lockres->l_flags & OCFS2_LOCK_NONBLOCK_FINISHED)) |
868 | lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING); | ||
869 | else | ||
870 | lockres_clear_flags(lockres, OCFS2_LOCK_NONBLOCK_FINISHED); | ||
866 | 871 | ||
867 | lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); | 872 | lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); |
868 | } | 873 | } |
@@ -1324,13 +1329,12 @@ static void lockres_add_mask_waiter(struct ocfs2_lock_res *lockres, | |||
1324 | 1329 | ||
1325 | /* returns 0 if the mw that was removed was already satisfied, -EBUSY | 1330 | /* returns 0 if the mw that was removed was already satisfied, -EBUSY |
1326 | * if the mask still hadn't reached its goal */ | 1331 | * if the mask still hadn't reached its goal */ |
1327 | static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, | 1332 | static int __lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, |
1328 | struct ocfs2_mask_waiter *mw) | 1333 | struct ocfs2_mask_waiter *mw) |
1329 | { | 1334 | { |
1330 | unsigned long flags; | ||
1331 | int ret = 0; | 1335 | int ret = 0; |
1332 | 1336 | ||
1333 | spin_lock_irqsave(&lockres->l_lock, flags); | 1337 | assert_spin_locked(&lockres->l_lock); |
1334 | if (!list_empty(&mw->mw_item)) { | 1338 | if (!list_empty(&mw->mw_item)) { |
1335 | if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal) | 1339 | if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal) |
1336 | ret = -EBUSY; | 1340 | ret = -EBUSY; |
@@ -1338,6 +1342,18 @@ static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, | |||
1338 | list_del_init(&mw->mw_item); | 1342 | list_del_init(&mw->mw_item); |
1339 | init_completion(&mw->mw_complete); | 1343 | init_completion(&mw->mw_complete); |
1340 | } | 1344 | } |
1345 | |||
1346 | return ret; | ||
1347 | } | ||
1348 | |||
1349 | static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, | ||
1350 | struct ocfs2_mask_waiter *mw) | ||
1351 | { | ||
1352 | unsigned long flags; | ||
1353 | int ret = 0; | ||
1354 | |||
1355 | spin_lock_irqsave(&lockres->l_lock, flags); | ||
1356 | ret = __lockres_remove_mask_waiter(lockres, mw); | ||
1341 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 1357 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
1342 | 1358 | ||
1343 | return ret; | 1359 | return ret; |
@@ -1373,6 +1389,7 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb, | |||
1373 | unsigned long flags; | 1389 | unsigned long flags; |
1374 | unsigned int gen; | 1390 | unsigned int gen; |
1375 | int noqueue_attempted = 0; | 1391 | int noqueue_attempted = 0; |
1392 | int dlm_locked = 0; | ||
1376 | 1393 | ||
1377 | ocfs2_init_mask_waiter(&mw); | 1394 | ocfs2_init_mask_waiter(&mw); |
1378 | 1395 | ||
@@ -1481,6 +1498,7 @@ again: | |||
1481 | ocfs2_recover_from_dlm_error(lockres, 1); | 1498 | ocfs2_recover_from_dlm_error(lockres, 1); |
1482 | goto out; | 1499 | goto out; |
1483 | } | 1500 | } |
1501 | dlm_locked = 1; | ||
1484 | 1502 | ||
1485 | mlog(0, "lock %s, successful return from ocfs2_dlm_lock\n", | 1503 | mlog(0, "lock %s, successful return from ocfs2_dlm_lock\n", |
1486 | lockres->l_name); | 1504 | lockres->l_name); |
@@ -1514,10 +1532,17 @@ out: | |||
1514 | if (wait && arg_flags & OCFS2_LOCK_NONBLOCK && | 1532 | if (wait && arg_flags & OCFS2_LOCK_NONBLOCK && |
1515 | mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKED)) { | 1533 | mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKED)) { |
1516 | wait = 0; | 1534 | wait = 0; |
1517 | if (lockres_remove_mask_waiter(lockres, &mw)) | 1535 | spin_lock_irqsave(&lockres->l_lock, flags); |
1536 | if (__lockres_remove_mask_waiter(lockres, &mw)) { | ||
1537 | if (dlm_locked) | ||
1538 | lockres_or_flags(lockres, | ||
1539 | OCFS2_LOCK_NONBLOCK_FINISHED); | ||
1540 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
1518 | ret = -EAGAIN; | 1541 | ret = -EAGAIN; |
1519 | else | 1542 | } else { |
1543 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
1520 | goto again; | 1544 | goto again; |
1545 | } | ||
1521 | } | 1546 | } |
1522 | if (wait) { | 1547 | if (wait) { |
1523 | ret = ocfs2_wait_for_mask(&mw); | 1548 | ret = ocfs2_wait_for_mask(&mw); |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index bbec539230fd..7d6b7d090452 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -144,6 +144,12 @@ enum ocfs2_unlock_action { | |||
144 | * before the upconvert | 144 | * before the upconvert |
145 | * has completed */ | 145 | * has completed */ |
146 | 146 | ||
147 | #define OCFS2_LOCK_NONBLOCK_FINISHED (0x00001000) /* NONBLOCK cluster | ||
148 | * lock has already | ||
149 | * returned, do not block | ||
150 | * dc thread from | ||
151 | * downconverting */ | ||
152 | |||
147 | struct ocfs2_lock_res_ops; | 153 | struct ocfs2_lock_res_ops; |
148 | 154 | ||
149 | typedef void (*ocfs2_lock_callback)(int status, unsigned long data); | 155 | typedef void (*ocfs2_lock_callback)(int status, unsigned long data); |