pNFS: Fix bugs in _pnfs_return_layout
authorTrond Myklebust <trond.myklebust@primarydata.com>
Wed, 30 Nov 2016 15:19:09 +0000 (10:19 -0500)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Thu, 1 Dec 2016 22:21:49 +0000 (17:21 -0500)
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>
fs/nfs/pnfs.c

index 76b18518881e0d40b16e76021de056aa1704ff38..a3a51860563c7211e119ef6791b52b08d178aa4a 100644 (file)
@@ -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;