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 <kolga@netapp.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
ecbb903c56
commit
1ebf980127
1 changed files with 11 additions and 2 deletions
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue