Skip to content

Commit b49ba75

Browse files
trondmypdgregkh
authored andcommitted
NFSv4: Fix open create exclusive when the server reboots
[ Upstream commit 8fd1ab7 ] If the server that does not implement NFSv4.1 persistent session semantics reboots while we are performing an exclusive create, then the return value of NFS4ERR_DELAY when we replay the open during the grace period causes us to lose the verifier. When the grace period expires, and we present a new verifier, the server will then correctly reply NFS4ERR_EXIST. This commit ensures that we always present the same verifier when replaying the OPEN. Reported-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent c5b430e commit b49ba75

1 file changed

Lines changed: 26 additions & 15 deletions

File tree

fs/nfs/nfs4proc.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,12 @@ struct nfs4_opendata {
997997
int cancelled;
998998
};
999999

1000+
struct nfs4_open_createattrs {
1001+
struct nfs4_label *label;
1002+
struct iattr *sattr;
1003+
const __u32 verf[2];
1004+
};
1005+
10001006
static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server,
10011007
int err, struct nfs4_exception *exception)
10021008
{
@@ -1066,15 +1072,15 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
10661072

10671073
static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
10681074
struct nfs4_state_owner *sp, fmode_t fmode, int flags,
1069-
const struct iattr *attrs,
1070-
struct nfs4_label *label,
1075+
const struct nfs4_open_createattrs *c,
10711076
enum open_claim_type4 claim,
10721077
gfp_t gfp_mask)
10731078
{
10741079
struct dentry *parent = dget_parent(dentry);
10751080
struct inode *dir = d_inode(parent);
10761081
struct nfs_server *server = NFS_SERVER(dir);
10771082
struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
1083+
struct nfs4_label *label = (c != NULL) ? c->label : NULL;
10781084
struct nfs4_opendata *p;
10791085

10801086
p = kzalloc(sizeof(*p), gfp_mask);
@@ -1131,15 +1137,11 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
11311137
case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
11321138
p->o_arg.fh = NFS_FH(d_inode(dentry));
11331139
}
1134-
if (attrs != NULL && attrs->ia_valid != 0) {
1135-
__u32 verf[2];
1136-
1140+
if (c != NULL && c->sattr != NULL && c->sattr->ia_valid != 0) {
11371141
p->o_arg.u.attrs = &p->attrs;
1138-
memcpy(&p->attrs, attrs, sizeof(p->attrs));
1142+
memcpy(&p->attrs, c->sattr, sizeof(p->attrs));
11391143

1140-
verf[0] = jiffies;
1141-
verf[1] = current->pid;
1142-
memcpy(p->o_arg.u.verifier.data, verf,
1144+
memcpy(p->o_arg.u.verifier.data, c->verf,
11431145
sizeof(p->o_arg.u.verifier.data));
11441146
}
11451147
p->c_arg.fh = &p->o_res.fh;
@@ -1653,7 +1655,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
16531655
struct nfs4_opendata *opendata;
16541656

16551657
opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0,
1656-
NULL, NULL, claim, GFP_NOFS);
1658+
NULL, claim, GFP_NOFS);
16571659
if (opendata == NULL)
16581660
return ERR_PTR(-ENOMEM);
16591661
opendata->state = state;
@@ -2488,8 +2490,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
24882490
static int _nfs4_do_open(struct inode *dir,
24892491
struct nfs_open_context *ctx,
24902492
int flags,
2491-
struct iattr *sattr,
2492-
struct nfs4_label *label,
2493+
const struct nfs4_open_createattrs *c,
24932494
int *opened)
24942495
{
24952496
struct nfs4_state_owner *sp;
@@ -2501,6 +2502,8 @@ static int _nfs4_do_open(struct inode *dir,
25012502
struct nfs4_threshold **ctx_th = &ctx->mdsthreshold;
25022503
fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC);
25032504
enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL;
2505+
struct iattr *sattr = c->sattr;
2506+
struct nfs4_label *label = c->label;
25042507
struct nfs4_label *olabel = NULL;
25052508
int status;
25062509

@@ -2519,8 +2522,8 @@ static int _nfs4_do_open(struct inode *dir,
25192522
status = -ENOMEM;
25202523
if (d_really_is_positive(dentry))
25212524
claim = NFS4_OPEN_CLAIM_FH;
2522-
opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr,
2523-
label, claim, GFP_KERNEL);
2525+
opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags,
2526+
c, claim, GFP_KERNEL);
25242527
if (opendata == NULL)
25252528
goto err_put_state_owner;
25262529

@@ -2596,10 +2599,18 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
25962599
struct nfs_server *server = NFS_SERVER(dir);
25972600
struct nfs4_exception exception = { };
25982601
struct nfs4_state *res;
2602+
struct nfs4_open_createattrs c = {
2603+
.label = label,
2604+
.sattr = sattr,
2605+
.verf = {
2606+
[0] = (__u32)jiffies,
2607+
[1] = (__u32)current->pid,
2608+
},
2609+
};
25992610
int status;
26002611

26012612
do {
2602-
status = _nfs4_do_open(dir, ctx, flags, sattr, label, opened);
2613+
status = _nfs4_do_open(dir, ctx, flags, &c, opened);
26032614
res = ctx->state;
26042615
trace_nfs4_open_file(ctx, flags, status);
26052616
if (status == 0)

0 commit comments

Comments
 (0)