Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ebf9801 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

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: default avatarOlga Kornievskaia <kolga@netapp.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent ecbb903c
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -542,6 +542,10 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
	struct nfs4_file_layout_dsaddr *dsaddr;
	int status = -EINVAL;

	/* Is the deviceid already set? If so, we're good. */
	if (fl->dsaddr != NULL)
		return 0;

	/* find and reference the deviceid */
	d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
			lo->plh_lc_cred, gfp_flags);
@@ -553,8 +557,6 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
	if (filelayout_test_devid_unavailable(&dsaddr->id_node))
		goto out_put;

	fl->dsaddr = dsaddr;

	if (fl->first_stripe_index >= dsaddr->stripe_count) {
		dprintk("%s Bad first_stripe_index %u\n",
				__func__, fl->first_stripe_index);
@@ -570,6 +572,13 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
		goto out_put;
	}
	status = 0;

	/*
	 * Atomic compare and xchange to ensure we don't scribble
	 * over a non-NULL pointer.
	 */
	if (cmpxchg(&fl->dsaddr, NULL, dsaddr) != NULL)
		goto out_put;
out:
	return status;
out_put: