aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/dlmglue.c37
-rw-r--r--fs/ocfs2/ocfs2.h6
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 */
1327static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, 1332static 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
1349static 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
147struct ocfs2_lock_res_ops; 153struct ocfs2_lock_res_ops;
148 154
149typedef void (*ocfs2_lock_callback)(int status, unsigned long data); 155typedef void (*ocfs2_lock_callback)(int status, unsigned long data);