Merge branch 'for-1209' of git://gitorious.org/smack-next/kernel into next
[deliverable/linux.git] / fs / nfs / pnfs.c
index bbc49caa7a82810ac497e7475997262f4da14be4..76875bfcf19ceda4a54cb0dde14466a304191cf9 100644 (file)
@@ -651,7 +651,14 @@ out_err_free:
        return NULL;
 }
 
-/* Initiates a LAYOUTRETURN(FILE) */
+/*
+ * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
+ * when the layout segment list is empty.
+ *
+ * Note that a pnfs_layout_hdr can exist with an empty layout segment
+ * list when LAYOUTGET has failed, or when LAYOUTGET succeeded, but the
+ * deviceid is marked invalid.
+ */
 int
 _pnfs_return_layout(struct inode *ino)
 {
@@ -660,22 +667,31 @@ _pnfs_return_layout(struct inode *ino)
        LIST_HEAD(tmp_list);
        struct nfs4_layoutreturn *lrp;
        nfs4_stateid stateid;
-       int status = 0;
+       int status = 0, empty;
 
-       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;
+               dprintk("NFS: %s no layout to return\n", __func__);
+               goto out;
        }
        stateid = nfsi->layout->plh_stateid;
        /* Reference matched in nfs4_layoutreturn_release */
        get_layout_hdr(lo);
+       empty = list_empty(&lo->plh_segs);
        mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
+       /* Don't send a LAYOUTRETURN if list was initially empty */
+       if (empty) {
+               spin_unlock(&ino->i_lock);
+               put_layout_hdr(lo);
+               dprintk("NFS: %s no layout segments to return\n", __func__);
+               goto out;
+       }
        lo->plh_block_lgets++;
+       pnfs_mark_layout_returned(lo);
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&tmp_list);
 
@@ -686,6 +702,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 +1092,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
@@ -1209,7 +1230,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write);
 
-bool
+void
 pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
                      const struct nfs_pgio_completion_ops *compl_ops)
 {
@@ -1217,13 +1238,12 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
        struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
 
        if (ld == NULL)
-               return false;
-       nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops,
-                       server->rsize, 0);
-       return true;
+               nfs_pageio_init_read(pgio, inode, compl_ops);
+       else
+               nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, server->rsize, 0);
 }
 
-bool
+void
 pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,
                       int ioflags,
                       const struct nfs_pgio_completion_ops *compl_ops)
@@ -1232,10 +1252,9 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,
        struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
 
        if (ld == NULL)
-               return false;
-       nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops,
-                       server->wsize, ioflags);
-       return true;
+               nfs_pageio_init_write(pgio, inode, ioflags, compl_ops);
+       else
+               nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops, server->wsize, ioflags);
 }
 
 bool
@@ -1272,7 +1291,7 @@ int pnfs_write_done_resend_to_mds(struct inode *inode,
        LIST_HEAD(failed);
 
        /* Resend all requests through the MDS */
-       nfs_pageio_init_write_mds(&pgio, inode, FLUSH_STABLE, compl_ops);
+       nfs_pageio_init_write(&pgio, inode, FLUSH_STABLE, compl_ops);
        while (!list_empty(head)) {
                struct nfs_page *req = nfs_list_entry(head->next);
 
@@ -1388,6 +1407,7 @@ static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
        put_lseg(hdr->lseg);
        nfs_writehdr_free(hdr);
 }
+EXPORT_SYMBOL_GPL(pnfs_writehdr_free);
 
 int
 pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
@@ -1427,7 +1447,7 @@ int pnfs_read_done_resend_to_mds(struct inode *inode,
        LIST_HEAD(failed);
 
        /* Resend all requests through the MDS */
-       nfs_pageio_init_read_mds(&pgio, inode, compl_ops);
+       nfs_pageio_init_read(&pgio, inode, compl_ops);
        while (!list_empty(head)) {
                struct nfs_page *req = nfs_list_entry(head->next);
 
@@ -1542,6 +1562,7 @@ static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)
        put_lseg(hdr->lseg);
        nfs_readhdr_free(hdr);
 }
+EXPORT_SYMBOL_GPL(pnfs_readhdr_free);
 
 int
 pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
This page took 0.028531 seconds and 5 git commands to generate.