diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-14 16:25:11 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-12-28 14:32:40 -0500 |
commit | 2e5b29f0448be9ea8da3ee0412a2043fee59e131 (patch) | |
tree | bba96a3ec2ae66890652f52552aeab9472824950 /fs/nfs | |
parent | 141b9b59ed8ae2602b2c285149ec8d4f6b05c4d9 (diff) |
pNFS/flexfiles: Don't prevent flexfiles client from retrying LAYOUTGET
Fix a bug in which flexfiles clients are falling back to I/O through the
MDS even when the FF_FLAGS_NO_IO_THRU_MDS flag is set.
The flexfiles client will always report errors through the LAYOUTRETURN
and/or LAYOUTERROR mechanisms, so it should normally be safe for it
to retry the LAYOUTGET until it fails or succeeds.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 4 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayoutdev.c | 16 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 18 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 21 |
4 files changed, 6 insertions, 53 deletions
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 5ede5c26c757..1da19d709458 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -1399,11 +1399,9 @@ static int ff_layout_write_done_cb(struct rpc_task *task, | |||
1399 | 1399 | ||
1400 | switch (err) { | 1400 | switch (err) { |
1401 | case -NFS4ERR_RESET_TO_PNFS: | 1401 | case -NFS4ERR_RESET_TO_PNFS: |
1402 | pnfs_set_retry_layoutget(hdr->lseg->pls_layout); | ||
1403 | ff_layout_reset_write(hdr, true); | 1402 | ff_layout_reset_write(hdr, true); |
1404 | return task->tk_status; | 1403 | return task->tk_status; |
1405 | case -NFS4ERR_RESET_TO_MDS: | 1404 | case -NFS4ERR_RESET_TO_MDS: |
1406 | pnfs_clear_retry_layoutget(hdr->lseg->pls_layout); | ||
1407 | ff_layout_reset_write(hdr, false); | 1405 | ff_layout_reset_write(hdr, false); |
1408 | return task->tk_status; | 1406 | return task->tk_status; |
1409 | case -EAGAIN: | 1407 | case -EAGAIN: |
@@ -1438,11 +1436,9 @@ static int ff_layout_commit_done_cb(struct rpc_task *task, | |||
1438 | 1436 | ||
1439 | switch (err) { | 1437 | switch (err) { |
1440 | case -NFS4ERR_RESET_TO_PNFS: | 1438 | case -NFS4ERR_RESET_TO_PNFS: |
1441 | pnfs_set_retry_layoutget(data->lseg->pls_layout); | ||
1442 | pnfs_generic_prepare_to_resend_writes(data); | 1439 | pnfs_generic_prepare_to_resend_writes(data); |
1443 | return -EAGAIN; | 1440 | return -EAGAIN; |
1444 | case -NFS4ERR_RESET_TO_MDS: | 1441 | case -NFS4ERR_RESET_TO_MDS: |
1445 | pnfs_clear_retry_layoutget(data->lseg->pls_layout); | ||
1446 | pnfs_generic_prepare_to_resend_writes(data); | 1442 | pnfs_generic_prepare_to_resend_writes(data); |
1447 | return -EAGAIN; | 1443 | return -EAGAIN; |
1448 | case -EAGAIN: | 1444 | case -EAGAIN: |
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c index e125e55de86d..bd0327541366 100644 --- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c | |||
@@ -429,22 +429,14 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx, | |||
429 | mirror, lseg->pls_range.offset, | 429 | mirror, lseg->pls_range.offset, |
430 | lseg->pls_range.length, NFS4ERR_NXIO, | 430 | lseg->pls_range.length, NFS4ERR_NXIO, |
431 | OP_ILLEGAL, GFP_NOIO); | 431 | OP_ILLEGAL, GFP_NOIO); |
432 | if (fail_return) { | 432 | if (!fail_return) { |
433 | pnfs_error_mark_layout_for_return(ino, lseg); | ||
434 | if (ff_layout_has_available_ds(lseg)) | ||
435 | pnfs_set_retry_layoutget(lseg->pls_layout); | ||
436 | else | ||
437 | pnfs_clear_retry_layoutget(lseg->pls_layout); | ||
438 | |||
439 | } else { | ||
440 | if (ff_layout_has_available_ds(lseg)) | 433 | if (ff_layout_has_available_ds(lseg)) |
441 | set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, | 434 | set_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, |
442 | &lseg->pls_layout->plh_flags); | 435 | &lseg->pls_layout->plh_flags); |
443 | else { | 436 | else |
444 | pnfs_error_mark_layout_for_return(ino, lseg); | 437 | pnfs_error_mark_layout_for_return(ino, lseg); |
445 | pnfs_clear_retry_layoutget(lseg->pls_layout); | 438 | } else |
446 | } | 439 | pnfs_error_mark_layout_for_return(ino, lseg); |
447 | } | ||
448 | } | 440 | } |
449 | out_update_creds: | 441 | out_update_creds: |
450 | if (ff_layout_update_mirror_cred(mirror, ds)) | 442 | if (ff_layout_update_mirror_cred(mirror, ds)) |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 580207bc52a5..6b42362cdbb0 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -618,7 +618,6 @@ pnfs_destroy_layout(struct nfs_inode *nfsi) | |||
618 | pnfs_get_layout_hdr(lo); | 618 | pnfs_get_layout_hdr(lo); |
619 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); | 619 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RO_FAILED); |
620 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); | 620 | pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED); |
621 | pnfs_clear_retry_layoutget(lo); | ||
622 | spin_unlock(&nfsi->vfs_inode.i_lock); | 621 | spin_unlock(&nfsi->vfs_inode.i_lock); |
623 | pnfs_free_lseg_list(&tmp_list); | 622 | pnfs_free_lseg_list(&tmp_list); |
624 | pnfs_put_layout_hdr(lo); | 623 | pnfs_put_layout_hdr(lo); |
@@ -1094,7 +1093,6 @@ bool pnfs_roc(struct inode *ino) | |||
1094 | &lo->plh_flags)) | 1093 | &lo->plh_flags)) |
1095 | layoutreturn = pnfs_prepare_layoutreturn(lo); | 1094 | layoutreturn = pnfs_prepare_layoutreturn(lo); |
1096 | 1095 | ||
1097 | pnfs_clear_retry_layoutget(lo); | ||
1098 | list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) | 1096 | list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) |
1099 | /* If we are sending layoutreturn, invalidate all valid lsegs */ | 1097 | /* If we are sending layoutreturn, invalidate all valid lsegs */ |
1100 | if (layoutreturn || test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { | 1098 | if (layoutreturn || test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) { |
@@ -1457,25 +1455,15 @@ static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx, | |||
1457 | return ret; | 1455 | return ret; |
1458 | } | 1456 | } |
1459 | 1457 | ||
1460 | /* stop waiting if someone clears NFS_LAYOUT_RETRY_LAYOUTGET bit. */ | ||
1461 | static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key, int mode) | ||
1462 | { | ||
1463 | if (!test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, key->flags)) | ||
1464 | return 1; | ||
1465 | return nfs_wait_bit_killable(key, mode); | ||
1466 | } | ||
1467 | |||
1468 | static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo) | 1458 | static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo) |
1469 | { | 1459 | { |
1470 | if (!pnfs_should_retry_layoutget(lo)) | ||
1471 | return false; | ||
1472 | /* | 1460 | /* |
1473 | * send layoutcommit as it can hold up layoutreturn due to lseg | 1461 | * send layoutcommit as it can hold up layoutreturn due to lseg |
1474 | * reference | 1462 | * reference |
1475 | */ | 1463 | */ |
1476 | pnfs_layoutcommit_inode(lo->plh_inode, false); | 1464 | pnfs_layoutcommit_inode(lo->plh_inode, false); |
1477 | return !wait_on_bit_action(&lo->plh_flags, NFS_LAYOUT_RETURN, | 1465 | return !wait_on_bit_action(&lo->plh_flags, NFS_LAYOUT_RETURN, |
1478 | pnfs_layoutget_retry_bit_wait, | 1466 | nfs_wait_bit_killable, |
1479 | TASK_UNINTERRUPTIBLE); | 1467 | TASK_UNINTERRUPTIBLE); |
1480 | } | 1468 | } |
1481 | 1469 | ||
@@ -1550,8 +1538,7 @@ lookup_again: | |||
1550 | } | 1538 | } |
1551 | 1539 | ||
1552 | /* if LAYOUTGET already failed once we don't try again */ | 1540 | /* if LAYOUTGET already failed once we don't try again */ |
1553 | if (pnfs_layout_io_test_failed(lo, iomode) && | 1541 | if (pnfs_layout_io_test_failed(lo, iomode)) { |
1554 | !pnfs_should_retry_layoutget(lo)) { | ||
1555 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, | 1542 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, |
1556 | PNFS_UPDATE_LAYOUT_IO_TEST_FAIL); | 1543 | PNFS_UPDATE_LAYOUT_IO_TEST_FAIL); |
1557 | goto out_unlock; | 1544 | goto out_unlock; |
@@ -1628,7 +1615,6 @@ lookup_again: | |||
1628 | arg.length = PAGE_CACHE_ALIGN(arg.length); | 1615 | arg.length = PAGE_CACHE_ALIGN(arg.length); |
1629 | 1616 | ||
1630 | lseg = send_layoutget(lo, ctx, &arg, gfp_flags); | 1617 | lseg = send_layoutget(lo, ctx, &arg, gfp_flags); |
1631 | pnfs_clear_retry_layoutget(lo); | ||
1632 | atomic_dec(&lo->plh_outstanding); | 1618 | atomic_dec(&lo->plh_outstanding); |
1633 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, | 1619 | trace_pnfs_update_layout(ino, pos, count, iomode, lo, |
1634 | PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET); | 1620 | PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET); |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index d1990e90e7a0..6916ff4e86f9 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -98,7 +98,6 @@ enum { | |||
98 | NFS_LAYOUT_RETURN_BEFORE_CLOSE, /* Return this layout before close */ | 98 | NFS_LAYOUT_RETURN_BEFORE_CLOSE, /* Return this layout before close */ |
99 | NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */ | 99 | NFS_LAYOUT_INVALID_STID, /* layout stateid id is invalid */ |
100 | NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */ | 100 | NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */ |
101 | NFS_LAYOUT_RETRY_LAYOUTGET, /* Retry layoutget */ | ||
102 | }; | 101 | }; |
103 | 102 | ||
104 | enum layoutdriver_policy_flags { | 103 | enum layoutdriver_policy_flags { |
@@ -379,26 +378,6 @@ nfs4_get_deviceid(struct nfs4_deviceid_node *d) | |||
379 | return d; | 378 | return d; |
380 | } | 379 | } |
381 | 380 | ||
382 | static inline void pnfs_set_retry_layoutget(struct pnfs_layout_hdr *lo) | ||
383 | { | ||
384 | if (!test_and_set_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags)) | ||
385 | atomic_inc(&lo->plh_refcount); | ||
386 | } | ||
387 | |||
388 | static inline void pnfs_clear_retry_layoutget(struct pnfs_layout_hdr *lo) | ||
389 | { | ||
390 | if (test_and_clear_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags)) { | ||
391 | atomic_dec(&lo->plh_refcount); | ||
392 | /* wake up waiters for LAYOUTRETURN as that is not needed */ | ||
393 | wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | static inline bool pnfs_should_retry_layoutget(struct pnfs_layout_hdr *lo) | ||
398 | { | ||
399 | return test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags); | ||
400 | } | ||
401 | |||
402 | static inline struct pnfs_layout_segment * | 381 | static inline struct pnfs_layout_segment * |
403 | pnfs_get_lseg(struct pnfs_layout_segment *lseg) | 382 | pnfs_get_lseg(struct pnfs_layout_segment *lseg) |
404 | { | 383 | { |