aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeng Tao <tao.peng@primarydata.com>2014-11-30 19:22:23 -0500
committerTom Haynes <loghyr@primarydata.com>2015-02-03 14:06:51 -0500
commitaa8a45ee974dfe3ffe290daaf5db457afae56fde (patch)
tree10d2b6eb4a9530f2d1a3433627b401d907c3bdb7
parent012fa16dca0da6c487dd066829ff0b0954925fe6 (diff)
nfs41: wait for LAYOUTRETURN before retrying LAYOUTGET
Also take care to stop waiting if someone clears retry bit. Signed-off-by: Peng Tao <tao.peng@primarydata.com>
-rw-r--r--fs/nfs/nfs4proc.c4
-rw-r--r--fs/nfs/pnfs.c39
-rw-r--r--fs/nfs/pnfs.h5
3 files changed, 45 insertions, 3 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 7e1a97a54f99..44c600aac907 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7796,7 +7796,9 @@ static void nfs4_layoutreturn_release(void *calldata)
7796 spin_lock(&lo->plh_inode->i_lock); 7796 spin_lock(&lo->plh_inode->i_lock);
7797 if (lrp->res.lrs_present) 7797 if (lrp->res.lrs_present)
7798 pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); 7798 pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
7799 clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags); 7799 clear_bit_unlock(NFS_LAYOUT_RETURN, &lo->plh_flags);
7800 smp_mb__after_atomic();
7801 wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN);
7800 clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags); 7802 clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags);
7801 rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq); 7803 rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq);
7802 lo->plh_block_lgets--; 7804 lo->plh_block_lgets--;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 893f6b5afe6a..c4c9fe606ae6 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1398,6 +1398,26 @@ static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx,
1398 return ret; 1398 return ret;
1399} 1399}
1400 1400
1401/* stop waiting if someone clears NFS_LAYOUT_RETRY_LAYOUTGET bit. */
1402static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key)
1403{
1404 if (!test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, key->flags))
1405 return 1;
1406 return nfs_wait_bit_killable(key);
1407}
1408
1409static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)
1410{
1411 /*
1412 * send layoutcommit as it can hold up layoutreturn due to lseg
1413 * reference
1414 */
1415 pnfs_layoutcommit_inode(lo->plh_inode, false);
1416 return !wait_on_bit_action(&lo->plh_flags, NFS_LAYOUT_RETURN,
1417 pnfs_layoutget_retry_bit_wait,
1418 TASK_UNINTERRUPTIBLE);
1419}
1420
1401/* 1421/*
1402 * Layout segment is retreived from the server if not cached. 1422 * Layout segment is retreived from the server if not cached.
1403 * The appropriate layout segment is referenced and returned to the caller. 1423 * The appropriate layout segment is referenced and returned to the caller.
@@ -1444,7 +1464,8 @@ lookup_again:
1444 } 1464 }
1445 1465
1446 /* if LAYOUTGET already failed once we don't try again */ 1466 /* if LAYOUTGET already failed once we don't try again */
1447 if (pnfs_layout_io_test_failed(lo, iomode)) 1467 if (pnfs_layout_io_test_failed(lo, iomode) &&
1468 !pnfs_should_retry_layoutget(lo))
1448 goto out_unlock; 1469 goto out_unlock;
1449 1470
1450 first = list_empty(&lo->plh_segs); 1471 first = list_empty(&lo->plh_segs);
@@ -1469,6 +1490,22 @@ lookup_again:
1469 goto out_unlock; 1490 goto out_unlock;
1470 } 1491 }
1471 1492
1493 /*
1494 * Because we free lsegs before sending LAYOUTRETURN, we need to wait
1495 * for LAYOUTRETURN even if first is true.
1496 */
1497 if (!lseg && pnfs_should_retry_layoutget(lo) &&
1498 test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) {
1499 spin_unlock(&ino->i_lock);
1500 dprintk("%s wait for layoutreturn\n", __func__);
1501 if (pnfs_prepare_to_retry_layoutget(lo)) {
1502 pnfs_put_layout_hdr(lo);
1503 dprintk("%s retrying\n", __func__);
1504 goto lookup_again;
1505 }
1506 goto out_put_layout_hdr;
1507 }
1508
1472 if (pnfs_layoutgets_blocked(lo, &arg, 0)) 1509 if (pnfs_layoutgets_blocked(lo, &arg, 0))
1473 goto out_unlock; 1510 goto out_unlock;
1474 atomic_inc(&lo->plh_outstanding); 1511 atomic_inc(&lo->plh_outstanding);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index fed6ae067acb..49a466708400 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -359,8 +359,11 @@ static inline void pnfs_set_retry_layoutget(struct pnfs_layout_hdr *lo)
359 359
360static inline void pnfs_clear_retry_layoutget(struct pnfs_layout_hdr *lo) 360static inline void pnfs_clear_retry_layoutget(struct pnfs_layout_hdr *lo)
361{ 361{
362 if (test_and_clear_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags)) 362 if (test_and_clear_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags)) {
363 atomic_dec(&lo->plh_refcount); 363 atomic_dec(&lo->plh_refcount);
364 /* wake up waiters for LAYOUTRETURN as that is not needed */
365 wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN);
366 }
364} 367}
365 368
366static inline bool pnfs_should_retry_layoutget(struct pnfs_layout_hdr *lo) 369static inline bool pnfs_should_retry_layoutget(struct pnfs_layout_hdr *lo)