aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorXue jiufei <xuejiufei@huawei.com>2014-12-10 18:41:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:03 -0500
commitd1e78238741491d24177d99453091439c90ac70e (patch)
treed292b52cc80dc07c44f9bb472fc6c9074de0232b /fs/ocfs2
parentdc17158060fb57f49c310a7def12fdaeddf35b19 (diff)
ocfs2: do not set OCFS2_LOCK_UPCONVERT_FINISHING if nonblocking lock can not be granted at once
ocfs2_readpages() use nonblocking flag to avoid page lock inversion. It will trigger cluster hang because that flag OCFS2_LOCK_UPCONVERT_FINISHING is not cleared if nonblocking lock cannot be granted at once. The flag would prevent dc thread from downconverting. So other nodes cannot acheive this lockres for ever. So we should not set OCFS2_LOCK_UPCONVERT_FINISHING when receiving ast if nonblocking lock had already returned. Signed-off-by: joyce.xue <xuejiufei@huawei.com> Reviewed-by: Junxiao Bi <junxiao.bi@oracle.com> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Joel Becker <jlbec@evilplan.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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);