Skip to content

Commit 44ea8df

Browse files
author
Trond Myklebust
committed
NFS/pnfs: Reference the layout cred in pnfs_prepare_layoutreturn()
When we're sending a layoutreturn, ensure that we reference the layout cred atomically with the copy of the stateid. Signed-off-by: Trond Myklebust <[email protected]>
1 parent 97a728f commit 44ea8df

File tree

2 files changed

+34
-19
lines changed

2 files changed

+34
-19
lines changed

fs/nfs/nfs4proc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9297,6 +9297,7 @@ static void nfs4_layoutreturn_release(void *calldata)
92979297
lrp->ld_private.ops->free(&lrp->ld_private);
92989298
pnfs_put_layout_hdr(lrp->args.layout);
92999299
nfs_iput_and_deactive(lrp->inode);
9300+
put_cred(lrp->cred);
93009301
kfree(calldata);
93019302
dprintk("<-- %s\n", __func__);
93029303
}

fs/nfs/pnfs.c

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,7 @@ void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
11441144
static bool
11451145
pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo,
11461146
nfs4_stateid *stateid,
1147+
const struct cred **cred,
11471148
enum pnfs_iomode *iomode)
11481149
{
11491150
/* Serialise LAYOUTGET/LAYOUTRETURN */
@@ -1154,18 +1155,17 @@ pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo,
11541155
set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
11551156
pnfs_get_layout_hdr(lo);
11561157
if (test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) {
1157-
if (stateid != NULL) {
1158-
nfs4_stateid_copy(stateid, &lo->plh_stateid);
1159-
if (lo->plh_return_seq != 0)
1160-
stateid->seqid = cpu_to_be32(lo->plh_return_seq);
1161-
}
1158+
nfs4_stateid_copy(stateid, &lo->plh_stateid);
1159+
*cred = get_cred(lo->plh_lc_cred);
1160+
if (lo->plh_return_seq != 0)
1161+
stateid->seqid = cpu_to_be32(lo->plh_return_seq);
11621162
if (iomode != NULL)
11631163
*iomode = lo->plh_return_iomode;
11641164
pnfs_clear_layoutreturn_info(lo);
11651165
return true;
11661166
}
1167-
if (stateid != NULL)
1168-
nfs4_stateid_copy(stateid, &lo->plh_stateid);
1167+
nfs4_stateid_copy(stateid, &lo->plh_stateid);
1168+
*cred = get_cred(lo->plh_lc_cred);
11691169
if (iomode != NULL)
11701170
*iomode = IOMODE_ANY;
11711171
return true;
@@ -1189,28 +1189,34 @@ pnfs_init_layoutreturn_args(struct nfs4_layoutreturn_args *args,
11891189
}
11901190

11911191
static int
1192-
pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo, const nfs4_stateid *stateid,
1193-
enum pnfs_iomode iomode, bool sync)
1192+
pnfs_send_layoutreturn(struct pnfs_layout_hdr *lo,
1193+
const nfs4_stateid *stateid,
1194+
const struct cred **pcred,
1195+
enum pnfs_iomode iomode,
1196+
bool sync)
11941197
{
11951198
struct inode *ino = lo->plh_inode;
11961199
struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;
11971200
struct nfs4_layoutreturn *lrp;
1201+
const struct cred *cred = *pcred;
11981202
int status = 0;
11991203

1204+
*pcred = NULL;
12001205
lrp = kzalloc(sizeof(*lrp), GFP_NOFS);
12011206
if (unlikely(lrp == NULL)) {
12021207
status = -ENOMEM;
12031208
spin_lock(&ino->i_lock);
12041209
pnfs_clear_layoutreturn_waitbit(lo);
12051210
spin_unlock(&ino->i_lock);
1211+
put_cred(cred);
12061212
pnfs_put_layout_hdr(lo);
12071213
goto out;
12081214
}
12091215

12101216
pnfs_init_layoutreturn_args(&lrp->args, lo, stateid, iomode);
12111217
lrp->args.ld_private = &lrp->ld_private;
12121218
lrp->clp = NFS_SERVER(ino)->nfs_client;
1213-
lrp->cred = lo->plh_lc_cred;
1219+
lrp->cred = cred;
12141220
if (ld->prepare_layoutreturn)
12151221
ld->prepare_layoutreturn(&lrp->args);
12161222

@@ -1255,15 +1261,16 @@ static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo)
12551261
return;
12561262
spin_lock(&inode->i_lock);
12571263
if (pnfs_layout_need_return(lo)) {
1264+
const struct cred *cred;
12581265
nfs4_stateid stateid;
12591266
enum pnfs_iomode iomode;
12601267
bool send;
12611268

1262-
send = pnfs_prepare_layoutreturn(lo, &stateid, &iomode);
1269+
send = pnfs_prepare_layoutreturn(lo, &stateid, &cred, &iomode);
12631270
spin_unlock(&inode->i_lock);
12641271
if (send) {
12651272
/* Send an async layoutreturn so we dont deadlock */
1266-
pnfs_send_layoutreturn(lo, &stateid, iomode, false);
1273+
pnfs_send_layoutreturn(lo, &stateid, &cred, iomode, false);
12671274
}
12681275
} else
12691276
spin_unlock(&inode->i_lock);
@@ -1283,6 +1290,7 @@ _pnfs_return_layout(struct inode *ino)
12831290
struct pnfs_layout_hdr *lo = NULL;
12841291
struct nfs_inode *nfsi = NFS_I(ino);
12851292
LIST_HEAD(tmp_list);
1293+
const struct cred *cred;
12861294
nfs4_stateid stateid;
12871295
int status = 0;
12881296
bool send, valid_layout;
@@ -1327,10 +1335,10 @@ _pnfs_return_layout(struct inode *ino)
13271335
goto out_put_layout_hdr;
13281336
}
13291337

1330-
send = pnfs_prepare_layoutreturn(lo, &stateid, NULL);
1338+
send = pnfs_prepare_layoutreturn(lo, &stateid, &cred, NULL);
13311339
spin_unlock(&ino->i_lock);
13321340
if (send)
1333-
status = pnfs_send_layoutreturn(lo, &stateid, IOMODE_ANY, true);
1341+
status = pnfs_send_layoutreturn(lo, &stateid, &cred, IOMODE_ANY, true);
13341342
out_put_layout_hdr:
13351343
pnfs_free_lseg_list(&tmp_list);
13361344
pnfs_put_layout_hdr(lo);
@@ -1376,6 +1384,7 @@ bool pnfs_roc(struct inode *ino,
13761384
struct nfs4_state *state;
13771385
struct pnfs_layout_hdr *lo;
13781386
struct pnfs_layout_segment *lseg, *next;
1387+
const struct cred *lc_cred;
13791388
nfs4_stateid stateid;
13801389
enum pnfs_iomode iomode = 0;
13811390
bool layoutreturn = false, roc = false;
@@ -1445,16 +1454,20 @@ bool pnfs_roc(struct inode *ino,
14451454
* 2. we don't send layoutreturn
14461455
*/
14471456
/* lo ref dropped in pnfs_roc_release() */
1448-
layoutreturn = pnfs_prepare_layoutreturn(lo, &stateid, &iomode);
1457+
layoutreturn = pnfs_prepare_layoutreturn(lo, &stateid, &lc_cred, &iomode);
14491458
/* If the creds don't match, we can't compound the layoutreturn */
1450-
if (!layoutreturn || cred_fscmp(cred, lo->plh_lc_cred) != 0)
1459+
if (!layoutreturn)
14511460
goto out_noroc;
1461+
if (cred_fscmp(cred, lc_cred) != 0)
1462+
goto out_noroc_put_cred;
14521463

14531464
roc = layoutreturn;
14541465
pnfs_init_layoutreturn_args(args, lo, &stateid, iomode);
14551466
res->lrs_present = 0;
14561467
layoutreturn = false;
14571468

1469+
out_noroc_put_cred:
1470+
put_cred(lc_cred);
14581471
out_noroc:
14591472
spin_unlock(&ino->i_lock);
14601473
rcu_read_unlock();
@@ -1467,7 +1480,7 @@ bool pnfs_roc(struct inode *ino,
14671480
return true;
14681481
}
14691482
if (layoutreturn)
1470-
pnfs_send_layoutreturn(lo, &stateid, iomode, true);
1483+
pnfs_send_layoutreturn(lo, &stateid, &lc_cred, iomode, true);
14711484
pnfs_put_layout_hdr(lo);
14721485
return false;
14731486
}
@@ -2464,13 +2477,14 @@ pnfs_mark_layout_for_return(struct inode *inode,
24642477
* for how it works.
24652478
*/
24662479
if (pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, range, 0) != -EBUSY) {
2480+
const struct cred *cred;
24672481
nfs4_stateid stateid;
24682482
enum pnfs_iomode iomode;
24692483

2470-
return_now = pnfs_prepare_layoutreturn(lo, &stateid, &iomode);
2484+
return_now = pnfs_prepare_layoutreturn(lo, &stateid, &cred, &iomode);
24712485
spin_unlock(&inode->i_lock);
24722486
if (return_now)
2473-
pnfs_send_layoutreturn(lo, &stateid, iomode, false);
2487+
pnfs_send_layoutreturn(lo, &stateid, &cred, iomode, false);
24742488
} else {
24752489
spin_unlock(&inode->i_lock);
24762490
nfs_commit_inode(inode, 0);

0 commit comments

Comments
 (0)