summaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2018-03-07 14:49:06 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2018-03-08 12:56:31 -0500
commit9c6376ebddad585da4238532dd6d90ae23ffee67 (patch)
treea69494f605f82c0cb19dc8dc63fc65832c6b60dd /fs/nfs/pnfs.c
parentd9ee65539d3eabd9ade46cca1780e3309ad0f907 (diff)
pNFS: Prevent the layout header refcount going to zero in pnfs_roc()
Ensure that we hold a reference to the layout header when processing the pNFS return-on-close so that the refcount value does not inadvertently go to zero. Reported-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Cc: stable@vger.kernel.org # v4.10+ Tested-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index c13e826614b5..ee723aa153a3 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -292,8 +292,11 @@ pnfs_detach_layout_hdr(struct pnfs_layout_hdr *lo)
292void 292void
293pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) 293pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
294{ 294{
295 struct inode *inode = lo->plh_inode; 295 struct inode *inode;
296 296
297 if (!lo)
298 return;
299 inode = lo->plh_inode;
297 pnfs_layoutreturn_before_put_layout_hdr(lo); 300 pnfs_layoutreturn_before_put_layout_hdr(lo);
298 301
299 if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) { 302 if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
@@ -1241,10 +1244,12 @@ retry:
1241 spin_lock(&ino->i_lock); 1244 spin_lock(&ino->i_lock);
1242 lo = nfsi->layout; 1245 lo = nfsi->layout;
1243 if (!lo || !pnfs_layout_is_valid(lo) || 1246 if (!lo || !pnfs_layout_is_valid(lo) ||
1244 test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) 1247 test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
1248 lo = NULL;
1245 goto out_noroc; 1249 goto out_noroc;
1250 }
1251 pnfs_get_layout_hdr(lo);
1246 if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) { 1252 if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
1247 pnfs_get_layout_hdr(lo);
1248 spin_unlock(&ino->i_lock); 1253 spin_unlock(&ino->i_lock);
1249 wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN, 1254 wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN,
1250 TASK_UNINTERRUPTIBLE); 1255 TASK_UNINTERRUPTIBLE);
@@ -1312,10 +1317,12 @@ out_noroc:
1312 struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld; 1317 struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;
1313 if (ld->prepare_layoutreturn) 1318 if (ld->prepare_layoutreturn)
1314 ld->prepare_layoutreturn(args); 1319 ld->prepare_layoutreturn(args);
1320 pnfs_put_layout_hdr(lo);
1315 return true; 1321 return true;
1316 } 1322 }
1317 if (layoutreturn) 1323 if (layoutreturn)
1318 pnfs_send_layoutreturn(lo, &stateid, iomode, true); 1324 pnfs_send_layoutreturn(lo, &stateid, iomode, true);
1325 pnfs_put_layout_hdr(lo);
1319 return false; 1326 return false;
1320} 1327}
1321 1328