diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 127 |
1 files changed, 82 insertions, 45 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 693b903b48bd..f93b9cdb4934 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1127,6 +1127,21 @@ static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task) | |||
1127 | return ret; | 1127 | return ret; |
1128 | } | 1128 | } |
1129 | 1129 | ||
1130 | static bool nfs4_mode_match_open_stateid(struct nfs4_state *state, | ||
1131 | fmode_t fmode) | ||
1132 | { | ||
1133 | switch(fmode & (FMODE_READ|FMODE_WRITE)) { | ||
1134 | case FMODE_READ|FMODE_WRITE: | ||
1135 | return state->n_rdwr != 0; | ||
1136 | case FMODE_WRITE: | ||
1137 | return state->n_wronly != 0; | ||
1138 | case FMODE_READ: | ||
1139 | return state->n_rdonly != 0; | ||
1140 | } | ||
1141 | WARN_ON_ONCE(1); | ||
1142 | return false; | ||
1143 | } | ||
1144 | |||
1130 | static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode) | 1145 | static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode) |
1131 | { | 1146 | { |
1132 | int ret = 0; | 1147 | int ret = 0; |
@@ -1571,17 +1586,13 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context | |||
1571 | return opendata; | 1586 | return opendata; |
1572 | } | 1587 | } |
1573 | 1588 | ||
1574 | static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmode, struct nfs4_state **res) | 1589 | static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, |
1590 | fmode_t fmode) | ||
1575 | { | 1591 | { |
1576 | struct nfs4_state *newstate; | 1592 | struct nfs4_state *newstate; |
1577 | int ret; | 1593 | int ret; |
1578 | 1594 | ||
1579 | if ((opendata->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR || | 1595 | if (!nfs4_mode_match_open_stateid(opendata->state, fmode)) |
1580 | opendata->o_arg.claim == NFS4_OPEN_CLAIM_DELEG_CUR_FH) && | ||
1581 | (opendata->o_arg.u.delegation_type & fmode) != fmode) | ||
1582 | /* This mode can't have been delegated, so we must have | ||
1583 | * a valid open_stateid to cover it - not need to reclaim. | ||
1584 | */ | ||
1585 | return 0; | 1596 | return 0; |
1586 | opendata->o_arg.open_flags = 0; | 1597 | opendata->o_arg.open_flags = 0; |
1587 | opendata->o_arg.fmode = fmode; | 1598 | opendata->o_arg.fmode = fmode; |
@@ -1597,14 +1608,14 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod | |||
1597 | newstate = nfs4_opendata_to_nfs4_state(opendata); | 1608 | newstate = nfs4_opendata_to_nfs4_state(opendata); |
1598 | if (IS_ERR(newstate)) | 1609 | if (IS_ERR(newstate)) |
1599 | return PTR_ERR(newstate); | 1610 | return PTR_ERR(newstate); |
1611 | if (newstate != opendata->state) | ||
1612 | ret = -ESTALE; | ||
1600 | nfs4_close_state(newstate, fmode); | 1613 | nfs4_close_state(newstate, fmode); |
1601 | *res = newstate; | 1614 | return ret; |
1602 | return 0; | ||
1603 | } | 1615 | } |
1604 | 1616 | ||
1605 | static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state) | 1617 | static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state) |
1606 | { | 1618 | { |
1607 | struct nfs4_state *newstate; | ||
1608 | int ret; | 1619 | int ret; |
1609 | 1620 | ||
1610 | /* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */ | 1621 | /* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */ |
@@ -1615,27 +1626,15 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
1615 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 1626 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
1616 | clear_bit(NFS_OPEN_STATE, &state->flags); | 1627 | clear_bit(NFS_OPEN_STATE, &state->flags); |
1617 | smp_rmb(); | 1628 | smp_rmb(); |
1618 | if (state->n_rdwr != 0) { | 1629 | ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE); |
1619 | ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate); | 1630 | if (ret != 0) |
1620 | if (ret != 0) | 1631 | return ret; |
1621 | return ret; | 1632 | ret = nfs4_open_recover_helper(opendata, FMODE_WRITE); |
1622 | if (newstate != state) | 1633 | if (ret != 0) |
1623 | return -ESTALE; | 1634 | return ret; |
1624 | } | 1635 | ret = nfs4_open_recover_helper(opendata, FMODE_READ); |
1625 | if (state->n_wronly != 0) { | 1636 | if (ret != 0) |
1626 | ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate); | 1637 | return ret; |
1627 | if (ret != 0) | ||
1628 | return ret; | ||
1629 | if (newstate != state) | ||
1630 | return -ESTALE; | ||
1631 | } | ||
1632 | if (state->n_rdonly != 0) { | ||
1633 | ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate); | ||
1634 | if (ret != 0) | ||
1635 | return ret; | ||
1636 | if (newstate != state) | ||
1637 | return -ESTALE; | ||
1638 | } | ||
1639 | /* | 1638 | /* |
1640 | * We may have performed cached opens for all three recoveries. | 1639 | * We may have performed cached opens for all three recoveries. |
1641 | * Check if we need to update the current stateid. | 1640 | * Check if we need to update the current stateid. |
@@ -1759,18 +1758,32 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct | |||
1759 | return err; | 1758 | return err; |
1760 | } | 1759 | } |
1761 | 1760 | ||
1762 | int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) | 1761 | int nfs4_open_delegation_recall(struct nfs_open_context *ctx, |
1762 | struct nfs4_state *state, const nfs4_stateid *stateid, | ||
1763 | fmode_t type) | ||
1763 | { | 1764 | { |
1764 | struct nfs_server *server = NFS_SERVER(state->inode); | 1765 | struct nfs_server *server = NFS_SERVER(state->inode); |
1765 | struct nfs4_opendata *opendata; | 1766 | struct nfs4_opendata *opendata; |
1766 | int err; | 1767 | int err = 0; |
1767 | 1768 | ||
1768 | opendata = nfs4_open_recoverdata_alloc(ctx, state, | 1769 | opendata = nfs4_open_recoverdata_alloc(ctx, state, |
1769 | NFS4_OPEN_CLAIM_DELEG_CUR_FH); | 1770 | NFS4_OPEN_CLAIM_DELEG_CUR_FH); |
1770 | if (IS_ERR(opendata)) | 1771 | if (IS_ERR(opendata)) |
1771 | return PTR_ERR(opendata); | 1772 | return PTR_ERR(opendata); |
1772 | nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid); | 1773 | nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid); |
1773 | err = nfs4_open_recover(opendata, state); | 1774 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
1775 | switch (type & (FMODE_READ|FMODE_WRITE)) { | ||
1776 | case FMODE_READ|FMODE_WRITE: | ||
1777 | case FMODE_WRITE: | ||
1778 | err = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE); | ||
1779 | if (err) | ||
1780 | break; | ||
1781 | err = nfs4_open_recover_helper(opendata, FMODE_WRITE); | ||
1782 | if (err) | ||
1783 | break; | ||
1784 | case FMODE_READ: | ||
1785 | err = nfs4_open_recover_helper(opendata, FMODE_READ); | ||
1786 | } | ||
1774 | nfs4_opendata_put(opendata); | 1787 | nfs4_opendata_put(opendata); |
1775 | return nfs4_handle_delegation_recall_error(server, state, stateid, err); | 1788 | return nfs4_handle_delegation_recall_error(server, state, stateid, err); |
1776 | } | 1789 | } |
@@ -2645,6 +2658,15 @@ out: | |||
2645 | return err; | 2658 | return err; |
2646 | } | 2659 | } |
2647 | 2660 | ||
2661 | static bool | ||
2662 | nfs4_wait_on_layoutreturn(struct inode *inode, struct rpc_task *task) | ||
2663 | { | ||
2664 | if (inode == NULL || !nfs_have_layout(inode)) | ||
2665 | return false; | ||
2666 | |||
2667 | return pnfs_wait_on_layoutreturn(inode, task); | ||
2668 | } | ||
2669 | |||
2648 | struct nfs4_closedata { | 2670 | struct nfs4_closedata { |
2649 | struct inode *inode; | 2671 | struct inode *inode; |
2650 | struct nfs4_state *state; | 2672 | struct nfs4_state *state; |
@@ -2763,6 +2785,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2763 | goto out_no_action; | 2785 | goto out_no_action; |
2764 | } | 2786 | } |
2765 | 2787 | ||
2788 | if (nfs4_wait_on_layoutreturn(inode, task)) { | ||
2789 | nfs_release_seqid(calldata->arg.seqid); | ||
2790 | goto out_wait; | ||
2791 | } | ||
2792 | |||
2766 | if (calldata->arg.fmode == 0) | 2793 | if (calldata->arg.fmode == 0) |
2767 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; | 2794 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; |
2768 | if (calldata->roc) | 2795 | if (calldata->roc) |
@@ -5308,6 +5335,9 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | |||
5308 | 5335 | ||
5309 | d_data = (struct nfs4_delegreturndata *)data; | 5336 | d_data = (struct nfs4_delegreturndata *)data; |
5310 | 5337 | ||
5338 | if (nfs4_wait_on_layoutreturn(d_data->inode, task)) | ||
5339 | return; | ||
5340 | |||
5311 | if (d_data->roc) | 5341 | if (d_data->roc) |
5312 | pnfs_roc_get_barrier(d_data->inode, &d_data->roc_barrier); | 5342 | pnfs_roc_get_barrier(d_data->inode, &d_data->roc_barrier); |
5313 | 5343 | ||
@@ -7800,39 +7830,46 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
7800 | dprintk("%s: NFS4ERR_RECALLCONFLICT waiting %lu\n", | 7830 | dprintk("%s: NFS4ERR_RECALLCONFLICT waiting %lu\n", |
7801 | __func__, delay); | 7831 | __func__, delay); |
7802 | rpc_delay(task, delay); | 7832 | rpc_delay(task, delay); |
7803 | task->tk_status = 0; | 7833 | /* Do not call nfs4_async_handle_error() */ |
7804 | rpc_restart_call_prepare(task); | 7834 | goto out_restart; |
7805 | goto out; /* Do not call nfs4_async_handle_error() */ | ||
7806 | } | 7835 | } |
7807 | break; | 7836 | break; |
7808 | case -NFS4ERR_EXPIRED: | 7837 | case -NFS4ERR_EXPIRED: |
7809 | case -NFS4ERR_BAD_STATEID: | 7838 | case -NFS4ERR_BAD_STATEID: |
7810 | spin_lock(&inode->i_lock); | 7839 | spin_lock(&inode->i_lock); |
7811 | lo = NFS_I(inode)->layout; | 7840 | if (nfs4_stateid_match(&lgp->args.stateid, |
7812 | if (!lo || list_empty(&lo->plh_segs)) { | 7841 | &lgp->args.ctx->state->stateid)) { |
7813 | spin_unlock(&inode->i_lock); | 7842 | spin_unlock(&inode->i_lock); |
7814 | /* If the open stateid was bad, then recover it. */ | 7843 | /* If the open stateid was bad, then recover it. */ |
7815 | state = lgp->args.ctx->state; | 7844 | state = lgp->args.ctx->state; |
7816 | } else { | 7845 | break; |
7846 | } | ||
7847 | lo = NFS_I(inode)->layout; | ||
7848 | if (lo && nfs4_stateid_match(&lgp->args.stateid, | ||
7849 | &lo->plh_stateid)) { | ||
7817 | LIST_HEAD(head); | 7850 | LIST_HEAD(head); |
7818 | 7851 | ||
7819 | /* | 7852 | /* |
7820 | * Mark the bad layout state as invalid, then retry | 7853 | * Mark the bad layout state as invalid, then retry |
7821 | * with the current stateid. | 7854 | * with the current stateid. |
7822 | */ | 7855 | */ |
7856 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | ||
7823 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); | 7857 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); |
7824 | spin_unlock(&inode->i_lock); | 7858 | spin_unlock(&inode->i_lock); |
7825 | pnfs_free_lseg_list(&head); | 7859 | pnfs_free_lseg_list(&head); |
7826 | 7860 | } else | |
7827 | task->tk_status = 0; | 7861 | spin_unlock(&inode->i_lock); |
7828 | rpc_restart_call_prepare(task); | 7862 | goto out_restart; |
7829 | } | ||
7830 | } | 7863 | } |
7831 | if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) | 7864 | if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN) |
7832 | rpc_restart_call_prepare(task); | 7865 | goto out_restart; |
7833 | out: | 7866 | out: |
7834 | dprintk("<-- %s\n", __func__); | 7867 | dprintk("<-- %s\n", __func__); |
7835 | return; | 7868 | return; |
7869 | out_restart: | ||
7870 | task->tk_status = 0; | ||
7871 | rpc_restart_call_prepare(task); | ||
7872 | return; | ||
7836 | out_overflow: | 7873 | out_overflow: |
7837 | task->tk_status = -EOVERFLOW; | 7874 | task->tk_status = -EOVERFLOW; |
7838 | goto out; | 7875 | goto out; |