]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
NFSv4.1 mark layout when already returned
authorAndy Adamson <andros@netapp.com>
Wed, 20 Jun 2012 19:03:33 +0000 (15:03 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Mon, 16 Jul 2012 18:37:25 +0000 (14:37 -0400)
When the file layout driver is fencing a DS, _pnfs_return_layout can be
called mulitple times per inode due to in-flight i/o referencing lsegs on it's
plh_segs list.

Remember that LAYOUTRETURN has been called, and do not call it again.
Allow LAYOUTRETURNs after a subsequent LAYOUTGET.

Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/pnfs.c
fs/nfs/pnfs.h

index 2617831afd392879bf2ce117cd82166cde28b064..3ad768f2cef4064d6728b72fdf0c4aef09164bb0 100644 (file)
@@ -662,11 +662,11 @@ _pnfs_return_layout(struct inode *ino)
        nfs4_stateid stateid;
        int status = 0;
 
-       dprintk("--> %s\n", __func__);
+       dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);
 
        spin_lock(&ino->i_lock);
        lo = nfsi->layout;
-       if (!lo) {
+       if (!lo || pnfs_test_layout_returned(lo)) {
                spin_unlock(&ino->i_lock);
                dprintk("%s: no layout to return\n", __func__);
                return status;
@@ -676,6 +676,7 @@ _pnfs_return_layout(struct inode *ino)
        get_layout_hdr(lo);
        mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
        lo->plh_block_lgets++;
+       pnfs_mark_layout_returned(lo);
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&tmp_list);
 
@@ -686,6 +687,7 @@ _pnfs_return_layout(struct inode *ino)
                status = -ENOMEM;
                set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags);
                set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags);
+               pnfs_clear_layout_returned(lo);
                put_layout_hdr(lo);
                goto out;
        }
@@ -1075,6 +1077,10 @@ pnfs_update_layout(struct inode *ino,
        get_layout_hdr(lo);
        if (list_empty(&lo->plh_segs))
                first = true;
+
+       /* Enable LAYOUTRETURNs */
+       pnfs_clear_layout_returned(lo);
+
        spin_unlock(&ino->i_lock);
        if (first) {
                /* The lo must be on the clp list if there is any
index 592beb02c955d6102f5f92405b3dd395e3d9bb8b..2c6c80503ba4851ed1e69c253293684c540b2c32 100644 (file)
@@ -64,6 +64,7 @@ enum {
        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
        NFS_LAYOUT_DESTROYED,           /* no new use of layout allowed */
        NFS_LAYOUT_INVALID,             /* layout is being destroyed */
+       NFS_LAYOUT_RETURNED,            /* layout has already been returned */
 };
 
 enum layoutdriver_policy_flags {
@@ -255,6 +256,24 @@ struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *
 bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *);
 void nfs4_deviceid_purge_client(const struct nfs_client *);
 
+static inline void
+pnfs_mark_layout_returned(struct pnfs_layout_hdr *lo)
+{
+       set_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
+}
+
+static inline void
+pnfs_clear_layout_returned(struct pnfs_layout_hdr *lo)
+{
+       clear_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
+}
+
+static inline bool
+pnfs_test_layout_returned(struct pnfs_layout_hdr *lo)
+{
+       return test_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
+}
+
 static inline int lo_fail_bit(u32 iomode)
 {
        return iomode == IOMODE_RW ?