aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c127
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
1130static 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
1130static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode) 1145static 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
1574static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmode, struct nfs4_state **res) 1589static 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
1605static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state) 1617static 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
1762int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) 1761int 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
2661static bool
2662nfs4_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
2648struct nfs4_closedata { 2670struct 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;
7833out: 7866out:
7834 dprintk("<-- %s\n", __func__); 7867 dprintk("<-- %s\n", __func__);
7835 return; 7868 return;
7869out_restart:
7870 task->tk_status = 0;
7871 rpc_restart_call_prepare(task);
7872 return;
7836out_overflow: 7873out_overflow:
7837 task->tk_status = -EOVERFLOW; 7874 task->tk_status = -EOVERFLOW;
7838 goto out; 7875 goto out;