mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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;
 | 
						struct nfs4_file_layout_dsaddr *dsaddr;
 | 
				
			||||||
	int status = -EINVAL;
 | 
						int status = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Is the deviceid already set? If so, we're good. */
 | 
				
			||||||
 | 
						if (fl->dsaddr != NULL)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* find and reference the deviceid */
 | 
						/* find and reference the deviceid */
 | 
				
			||||||
	d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
 | 
						d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid,
 | 
				
			||||||
			lo->plh_lc_cred, gfp_flags);
 | 
								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))
 | 
						if (filelayout_test_devid_unavailable(&dsaddr->id_node))
 | 
				
			||||||
		goto out_put;
 | 
							goto out_put;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fl->dsaddr = dsaddr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (fl->first_stripe_index >= dsaddr->stripe_count) {
 | 
						if (fl->first_stripe_index >= dsaddr->stripe_count) {
 | 
				
			||||||
		dprintk("%s Bad first_stripe_index %u\n",
 | 
							dprintk("%s Bad first_stripe_index %u\n",
 | 
				
			||||||
				__func__, fl->first_stripe_index);
 | 
									__func__, fl->first_stripe_index);
 | 
				
			||||||
| 
						 | 
					@ -570,6 +572,13 @@ filelayout_check_deviceid(struct pnfs_layout_hdr *lo,
 | 
				
			||||||
		goto out_put;
 | 
							goto out_put;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	status = 0;
 | 
						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:
 | 
					out:
 | 
				
			||||||
	return status;
 | 
						return status;
 | 
				
			||||||
out_put:
 | 
					out_put:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue