Skip to content

Commit 1ebf980

Browse files
trondmypdamschuma-ntap
authored andcommitted
NFS/filelayout: Fix racy setting of fl->dsaddr in filelayout_check_deviceid()
We must set fl->dsaddr once, and once only, even if there are multiple processes calling filelayout_check_deviceid() for the same layout segment. Reported-by: Olga Kornievskaia <[email protected]> Signed-off-by: Trond Myklebust <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent ecbb903 commit 1ebf980

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

fs/nfs/filelayout/filelayout.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,10 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
542542
struct nfs4_file_layout_dsaddr *dsaddr;
543543
int status = -EINVAL;
544544

545+
/* Is the deviceid already set? If so, we're good. */
546+
if (fl->dsaddr != NULL)
547+
return 0;
548+
545549
/* find and reference the deviceid */
546550
d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
547551
lo->plh_lc_cred, gfp_flags);
@@ -553,8 +557,6 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
553557
if (filelayout_test_devid_unavailable(&dsaddr->id_node))
554558
goto out_put;
555559

556-
fl->dsaddr = dsaddr;
557-
558560
if (fl->first_stripe_index >= dsaddr->stripe_count) {
559561
dprintk("%s Bad first_stripe_index %u\n",
560562
__func__, fl->first_stripe_index);
@@ -570,6 +572,13 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
570572
goto out_put;
571573
}
572574
status = 0;
575+
576+
/*
577+
* Atomic compare and xchange to ensure we don't scribble
578+
* over a non-NULL pointer.
579+
*/
580+
if (cmpxchg(&fl->dsaddr, NULL, dsaddr) != NULL)
581+
goto out_put;
573582
out:
574583
return status;
575584
out_put:

0 commit comments

Comments
 (0)