diff options
author | Peng Tao <tao.peng@primarydata.com> | 2014-11-30 19:22:23 -0500 |
---|---|---|
committer | Tom Haynes <loghyr@primarydata.com> | 2015-02-03 14:06:51 -0500 |
commit | aa8a45ee974dfe3ffe290daaf5db457afae56fde (patch) | |
tree | 10d2b6eb4a9530f2d1a3433627b401d907c3bdb7 /fs/nfs/pnfs.c | |
parent | 012fa16dca0da6c487dd066829ff0b0954925fe6 (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>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 39 |
1 files changed, 38 insertions, 1 deletions
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. */ | ||
1402 | static 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 | |||
1409 | static 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); |