Skip to content

Commit 56ce272

Browse files
committed
NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn
jira LE-1907 Rebuild_History Non-Buildable kernel-rt-5.14.0-284.30.1.rt14.315.el9_2 commit-author Trond Myklebust <trond.myklebust@hammerspace.com> commit 51069e4 If we're asked to recover open state while a delegation return is outstanding, then the state manager thread cannot use a cached open, so if the server returns a delegation, we can end up deadlocked behind the pending delegreturn. To avoid this problem, let's just ask the server not to give us a delegation unless we're explicitly reclaiming one. Fixes: be36e18 ("NFSv4: nfs4_open_recover_helper() must set share access") Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> (cherry picked from commit 51069e4) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 5fa8cf6 commit 56ce272

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

fs/nfs/nfs4proc.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2125,18 +2125,18 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
21252125
}
21262126

21272127
static int nfs4_open_recover_helper(struct nfs4_opendata *opendata,
2128-
fmode_t fmode)
2128+
fmode_t fmode)
21292129
{
21302130
struct nfs4_state *newstate;
2131+
struct nfs_server *server = NFS_SB(opendata->dentry->d_sb);
2132+
int openflags = opendata->o_arg.open_flags;
21312133
int ret;
21322134

21332135
if (!nfs4_mode_match_open_stateid(opendata->state, fmode))
21342136
return 0;
2135-
opendata->o_arg.open_flags = 0;
21362137
opendata->o_arg.fmode = fmode;
2137-
opendata->o_arg.share_access = nfs4_map_atomic_open_share(
2138-
NFS_SB(opendata->dentry->d_sb),
2139-
fmode, 0);
2138+
opendata->o_arg.share_access =
2139+
nfs4_map_atomic_open_share(server, fmode, openflags);
21402140
memset(&opendata->o_res, 0, sizeof(opendata->o_res));
21412141
memset(&opendata->c_res, 0, sizeof(opendata->c_res));
21422142
nfs4_init_opendata_res(opendata);
@@ -2718,10 +2718,15 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
27182718
struct nfs4_opendata *opendata;
27192719
int ret;
27202720

2721-
opendata = nfs4_open_recoverdata_alloc(ctx, state,
2722-
NFS4_OPEN_CLAIM_FH);
2721+
opendata = nfs4_open_recoverdata_alloc(ctx, state, NFS4_OPEN_CLAIM_FH);
27232722
if (IS_ERR(opendata))
27242723
return PTR_ERR(opendata);
2724+
/*
2725+
* We're not recovering a delegation, so ask for no delegation.
2726+
* Otherwise the recovery thread could deadlock with an outstanding
2727+
* delegation return.
2728+
*/
2729+
opendata->o_arg.open_flags = O_DIRECT;
27252730
ret = nfs4_open_recover(opendata, state);
27262731
if (ret == -ESTALE)
27272732
d_drop(ctx->dentry);

0 commit comments

Comments
 (0)