Skip to content

Commit 0460253

Browse files
author
Trond Myklebust
committed
NFSv4: nfs4_do_open() is incorrectly triggering state recovery
We're seeing spurious calls to nfs4_schedule_stateid_recovery() from nfs4_do_open() in situations where there is no trigger coming from the server. In theory the code path being triggered is supposed to notice that state recovery happened while we were processing the open call result from the server, before the open stateid is published. However in the years since that code was added, we've also added the 'session draining' mechanism, which ensures that the state recovery will wait until all the session slots have been returned. In nfs4_do_open() the session slot is only returned on exit of the function, so we don't need the legacy mechanism. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent 2fdbc20 commit 0460253

File tree

4 files changed

+8
-16
lines changed

4 files changed

+8
-16
lines changed

fs/nfs/delegation.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@ static int nfs_delegation_claim_opens(struct inode *inode,
181181
struct nfs_open_context *ctx;
182182
struct nfs4_state_owner *sp;
183183
struct nfs4_state *state;
184-
unsigned int seq;
185184
int err;
186185

187186
again:
@@ -202,12 +201,9 @@ static int nfs_delegation_claim_opens(struct inode *inode,
202201
sp = state->owner;
203202
/* Block nfs4_proc_unlck */
204203
mutex_lock(&sp->so_delegreturn_mutex);
205-
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
206204
err = nfs4_open_delegation_recall(ctx, state, stateid);
207205
if (!err)
208206
err = nfs_delegation_claim_locks(state, stateid);
209-
if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
210-
err = -EAGAIN;
211207
mutex_unlock(&sp->so_delegreturn_mutex);
212208
put_nfs_open_context(ctx);
213209
if (err != 0)

fs/nfs/nfs4_fs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ struct nfs4_state_owner {
120120
unsigned long so_flags;
121121
struct list_head so_states;
122122
struct nfs_seqid_counter so_seqid;
123-
seqcount_spinlock_t so_reclaim_seqcount;
124123
struct mutex so_delegreturn_mutex;
125124
};
126125

fs/nfs/nfs4proc.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3069,10 +3069,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
30693069
fmode_t acc_mode = _nfs4_ctx_to_accessmode(ctx);
30703070
struct inode *dir = d_inode(opendata->dir);
30713071
unsigned long dir_verifier;
3072-
unsigned int seq;
30733072
int ret;
30743073

3075-
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
30763074
dir_verifier = nfs_save_change_attribute(dir);
30773075

30783076
ret = _nfs4_proc_open(opendata, ctx);
@@ -3125,11 +3123,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
31253123
if (ret != 0)
31263124
goto out;
31273125

3128-
if (d_inode(dentry) == state->inode) {
3126+
if (d_inode(dentry) == state->inode)
31293127
nfs_inode_attach_open_context(ctx);
3130-
if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
3131-
nfs4_schedule_stateid_recovery(server, state);
3132-
}
31333128

31343129
out:
31353130
if (!opendata->cancelled) {

fs/nfs/nfs4state.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,6 @@ nfs4_alloc_state_owner(struct nfs_server *server,
513513
nfs4_init_seqid_counter(&sp->so_seqid);
514514
atomic_set(&sp->so_count, 1);
515515
INIT_LIST_HEAD(&sp->so_lru);
516-
seqcount_spinlock_init(&sp->so_reclaim_seqcount, &sp->so_lock);
517516
mutex_init(&sp->so_delegreturn_mutex);
518517
return sp;
519518
}
@@ -1667,7 +1666,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp,
16671666
* server that doesn't support a grace period.
16681667
*/
16691668
spin_lock(&sp->so_lock);
1670-
raw_write_seqcount_begin(&sp->so_reclaim_seqcount);
16711669
restart:
16721670
list_for_each_entry(state, &sp->so_states, open_states) {
16731671
if (!test_and_clear_bit(ops->state_flag_bit, &state->flags))
@@ -1735,7 +1733,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp,
17351733
spin_lock(&sp->so_lock);
17361734
goto restart;
17371735
}
1738-
raw_write_seqcount_end(&sp->so_reclaim_seqcount);
17391736
spin_unlock(&sp->so_lock);
17401737
#ifdef CONFIG_NFS_V4_2
17411738
if (found_ssc_copy_state)
@@ -1745,7 +1742,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp,
17451742
out_err:
17461743
nfs4_put_open_state(state);
17471744
spin_lock(&sp->so_lock);
1748-
raw_write_seqcount_end(&sp->so_reclaim_seqcount);
17491745
spin_unlock(&sp->so_lock);
17501746
return status;
17511747
}
@@ -1928,9 +1924,12 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
19281924
struct nfs_server *server;
19291925
struct rb_node *pos;
19301926
LIST_HEAD(freeme);
1931-
int status = 0;
19321927
int lost_locks = 0;
1928+
int status;
19331929

1930+
status = nfs4_begin_drain_session(clp);
1931+
if (status < 0)
1932+
return status;
19341933
restart:
19351934
rcu_read_lock();
19361935
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
@@ -2694,6 +2693,9 @@ static void nfs4_state_manager(struct nfs_client *clp)
26942693
/* Detect expired delegations... */
26952694
if (test_and_clear_bit(NFS4CLNT_DELEGATION_EXPIRED, &clp->cl_state)) {
26962695
section = "detect expired delegations";
2696+
status = nfs4_begin_drain_session(clp);
2697+
if (status < 0)
2698+
goto out_error;
26972699
nfs_reap_expired_delegations(clp);
26982700
continue;
26992701
}

0 commit comments

Comments
 (0)