summaryrefslogtreecommitdiff
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-11-30 18:19:09 +0300
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-12-02 01:21:49 +0300
commit24408f5282df58210cfecaa6851b2be52f5c661f (patch)
tree846785c469295d127b3d5184277540c2bb035efa /fs/nfs/pnfs.c
parentfe1cf9469d7bcb6af27e42eb555a41b0135bce4a (diff)
downloadlinux-24408f5282df58210cfecaa6851b2be52f5c661f.tar.xz
pNFS: Fix bugs in _pnfs_return_layout
We need to honour the NFS_LAYOUT_RETURN_REQUESTED bit regardless of whether or not there are layout segments pending. Furthermore, we should ensure that we leave the plh_return_segs list empty. This patch fixes a memory leak of the layout segments on plh_return_segs. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
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 76b18518881e..a3a51860563c 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1145,7 +1145,7 @@ _pnfs_return_layout(struct inode *ino)
struct nfs_inode *nfsi = NFS_I(ino);
LIST_HEAD(tmp_list);
nfs4_stateid stateid;
- int status = 0, empty;
+ int status = 0;
bool send;
dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);
@@ -1159,7 +1159,14 @@ _pnfs_return_layout(struct inode *ino)
}
/* Reference matched in nfs4_layoutreturn_release */
pnfs_get_layout_hdr(lo);
- empty = list_empty(&lo->plh_segs);
+ /* Is there an outstanding layoutreturn ? */
+ if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
+ spin_unlock(&ino->i_lock);
+ if (wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN,
+ TASK_UNINTERRUPTIBLE))
+ goto out_put_layout_hdr;
+ spin_lock(&ino->i_lock);
+ }
pnfs_clear_layoutcommit(ino, &tmp_list);
pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL, 0);
@@ -1173,7 +1180,7 @@ _pnfs_return_layout(struct inode *ino)
}
/* Don't send a LAYOUTRETURN if list was initially empty */
- if (empty) {
+ if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) {
spin_unlock(&ino->i_lock);
dprintk("NFS: %s no layout segments to return\n", __func__);
goto out_put_layout_hdr;