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.c95
1 files changed, 45 insertions, 50 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 405bd95c1f58..69dc20a743f9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -370,11 +370,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
370 case -NFS4ERR_DELEG_REVOKED: 370 case -NFS4ERR_DELEG_REVOKED:
371 case -NFS4ERR_ADMIN_REVOKED: 371 case -NFS4ERR_ADMIN_REVOKED:
372 case -NFS4ERR_BAD_STATEID: 372 case -NFS4ERR_BAD_STATEID:
373 if (inode != NULL && nfs4_have_delegation(inode, FMODE_READ)) {
374 nfs_remove_bad_delegation(inode);
375 exception->retry = 1;
376 break;
377 }
378 if (state == NULL) 373 if (state == NULL)
379 break; 374 break;
380 ret = nfs4_schedule_stateid_recovery(server, state); 375 ret = nfs4_schedule_stateid_recovery(server, state);
@@ -1654,7 +1649,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
1654 nfs_inode_find_state_and_recover(state->inode, 1649 nfs_inode_find_state_and_recover(state->inode,
1655 stateid); 1650 stateid);
1656 nfs4_schedule_stateid_recovery(server, state); 1651 nfs4_schedule_stateid_recovery(server, state);
1657 return 0; 1652 return -EAGAIN;
1658 case -NFS4ERR_DELAY: 1653 case -NFS4ERR_DELAY:
1659 case -NFS4ERR_GRACE: 1654 case -NFS4ERR_GRACE:
1660 set_bit(NFS_DELEGATED_STATE, &state->flags); 1655 set_bit(NFS_DELEGATED_STATE, &state->flags);
@@ -2109,46 +2104,60 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
2109 return ret; 2104 return ret;
2110} 2105}
2111 2106
2107static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state)
2108{
2109 nfs_remove_bad_delegation(state->inode);
2110 write_seqlock(&state->seqlock);
2111 nfs4_stateid_copy(&state->stateid, &state->open_stateid);
2112 write_sequnlock(&state->seqlock);
2113 clear_bit(NFS_DELEGATED_STATE, &state->flags);
2114}
2115
2116static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
2117{
2118 if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
2119 nfs_finish_clear_delegation_stateid(state);
2120}
2121
2122static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
2123{
2124 /* NFSv4.0 doesn't allow for delegation recovery on open expire */
2125 nfs40_clear_delegation_stateid(state);
2126 return nfs4_open_expired(sp, state);
2127}
2128
2112#if defined(CONFIG_NFS_V4_1) 2129#if defined(CONFIG_NFS_V4_1)
2113static void nfs41_clear_delegation_stateid(struct nfs4_state *state) 2130static void nfs41_check_delegation_stateid(struct nfs4_state *state)
2114{ 2131{
2115 struct nfs_server *server = NFS_SERVER(state->inode); 2132 struct nfs_server *server = NFS_SERVER(state->inode);
2116 nfs4_stateid *stateid = &state->stateid; 2133 nfs4_stateid stateid;
2117 struct nfs_delegation *delegation; 2134 struct nfs_delegation *delegation;
2118 struct rpc_cred *cred = NULL; 2135 struct rpc_cred *cred;
2119 int status = -NFS4ERR_BAD_STATEID; 2136 int status;
2120
2121 /* If a state reset has been done, test_stateid is unneeded */
2122 if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
2123 return;
2124 2137
2125 /* Get the delegation credential for use by test/free_stateid */ 2138 /* Get the delegation credential for use by test/free_stateid */
2126 rcu_read_lock(); 2139 rcu_read_lock();
2127 delegation = rcu_dereference(NFS_I(state->inode)->delegation); 2140 delegation = rcu_dereference(NFS_I(state->inode)->delegation);
2128 if (delegation != NULL && 2141 if (delegation == NULL) {
2129 nfs4_stateid_match(&delegation->stateid, stateid)) {
2130 cred = get_rpccred(delegation->cred);
2131 rcu_read_unlock();
2132 status = nfs41_test_stateid(server, stateid, cred);
2133 trace_nfs4_test_delegation_stateid(state, NULL, status);
2134 } else
2135 rcu_read_unlock(); 2142 rcu_read_unlock();
2143 return;
2144 }
2145
2146 nfs4_stateid_copy(&stateid, &delegation->stateid);
2147 cred = get_rpccred(delegation->cred);
2148 rcu_read_unlock();
2149 status = nfs41_test_stateid(server, &stateid, cred);
2150 trace_nfs4_test_delegation_stateid(state, NULL, status);
2136 2151
2137 if (status != NFS_OK) { 2152 if (status != NFS_OK) {
2138 /* Free the stateid unless the server explicitly 2153 /* Free the stateid unless the server explicitly
2139 * informs us the stateid is unrecognized. */ 2154 * informs us the stateid is unrecognized. */
2140 if (status != -NFS4ERR_BAD_STATEID) 2155 if (status != -NFS4ERR_BAD_STATEID)
2141 nfs41_free_stateid(server, stateid, cred); 2156 nfs41_free_stateid(server, &stateid, cred);
2142 nfs_remove_bad_delegation(state->inode); 2157 nfs_finish_clear_delegation_stateid(state);
2143
2144 write_seqlock(&state->seqlock);
2145 nfs4_stateid_copy(&state->stateid, &state->open_stateid);
2146 write_sequnlock(&state->seqlock);
2147 clear_bit(NFS_DELEGATED_STATE, &state->flags);
2148 } 2158 }
2149 2159
2150 if (cred != NULL) 2160 put_rpccred(cred);
2151 put_rpccred(cred);
2152} 2161}
2153 2162
2154/** 2163/**
@@ -2192,7 +2201,7 @@ static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
2192{ 2201{
2193 int status; 2202 int status;
2194 2203
2195 nfs41_clear_delegation_stateid(state); 2204 nfs41_check_delegation_stateid(state);
2196 status = nfs41_check_open_stateid(state); 2205 status = nfs41_check_open_stateid(state);
2197 if (status != NFS_OK) 2206 if (status != NFS_OK)
2198 status = nfs4_open_expired(sp, state); 2207 status = nfs4_open_expired(sp, state);
@@ -2231,19 +2240,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
2231 seq = raw_seqcount_begin(&sp->so_reclaim_seqcount); 2240 seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
2232 2241
2233 ret = _nfs4_proc_open(opendata); 2242 ret = _nfs4_proc_open(opendata);
2234 if (ret != 0) { 2243 if (ret != 0)
2235 if (ret == -ENOENT) {
2236 dentry = opendata->dentry;
2237 if (dentry->d_inode)
2238 d_delete(dentry);
2239 else if (d_unhashed(dentry))
2240 d_add(dentry, NULL);
2241
2242 nfs_set_verifier(dentry,
2243 nfs_save_change_attribute(opendata->dir->d_inode));
2244 }
2245 goto out; 2244 goto out;
2246 }
2247 2245
2248 state = nfs4_opendata_to_nfs4_state(opendata); 2246 state = nfs4_opendata_to_nfs4_state(opendata);
2249 ret = PTR_ERR(state); 2247 ret = PTR_ERR(state);
@@ -4841,9 +4839,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
4841 case -NFS4ERR_DELEG_REVOKED: 4839 case -NFS4ERR_DELEG_REVOKED:
4842 case -NFS4ERR_ADMIN_REVOKED: 4840 case -NFS4ERR_ADMIN_REVOKED:
4843 case -NFS4ERR_BAD_STATEID: 4841 case -NFS4ERR_BAD_STATEID:
4844 if (state == NULL)
4845 break;
4846 nfs_remove_bad_delegation(state->inode);
4847 case -NFS4ERR_OPENMODE: 4842 case -NFS4ERR_OPENMODE:
4848 if (state == NULL) 4843 if (state == NULL)
4849 break; 4844 break;
@@ -8341,7 +8336,7 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
8341static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { 8336static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
8342 .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, 8337 .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
8343 .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, 8338 .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
8344 .recover_open = nfs4_open_expired, 8339 .recover_open = nfs40_open_expired,
8345 .recover_lock = nfs4_lock_expired, 8340 .recover_lock = nfs4_lock_expired,
8346 .establish_clid = nfs4_init_clientid, 8341 .establish_clid = nfs4_init_clientid,
8347}; 8342};
@@ -8408,8 +8403,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
8408 | NFS_CAP_CHANGE_ATTR 8403 | NFS_CAP_CHANGE_ATTR
8409 | NFS_CAP_POSIX_LOCK 8404 | NFS_CAP_POSIX_LOCK
8410 | NFS_CAP_STATEID_NFSV41 8405 | NFS_CAP_STATEID_NFSV41
8411 | NFS_CAP_ATOMIC_OPEN_V1 8406 | NFS_CAP_ATOMIC_OPEN_V1,
8412 | NFS_CAP_SEEK,
8413 .init_client = nfs41_init_client, 8407 .init_client = nfs41_init_client,
8414 .shutdown_client = nfs41_shutdown_client, 8408 .shutdown_client = nfs41_shutdown_client,
8415 .match_stateid = nfs41_match_stateid, 8409 .match_stateid = nfs41_match_stateid,
@@ -8431,7 +8425,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
8431 | NFS_CAP_CHANGE_ATTR 8425 | NFS_CAP_CHANGE_ATTR
8432 | NFS_CAP_POSIX_LOCK 8426 | NFS_CAP_POSIX_LOCK
8433 | NFS_CAP_STATEID_NFSV41 8427 | NFS_CAP_STATEID_NFSV41
8434 | NFS_CAP_ATOMIC_OPEN_V1, 8428 | NFS_CAP_ATOMIC_OPEN_V1
8429 | NFS_CAP_SEEK,
8435 .init_client = nfs41_init_client, 8430 .init_client = nfs41_init_client,
8436 .shutdown_client = nfs41_shutdown_client, 8431 .shutdown_client = nfs41_shutdown_client,
8437 .match_stateid = nfs41_match_stateid, 8432 .match_stateid = nfs41_match_stateid,