Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / fs / nfs / pnfs.c
index a2478bc..3ad6595 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
+#include <linux/module.h>
 #include "internal.h"
 #include "pnfs.h"
 #include "iostat.h"
@@ -574,9 +575,6 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        struct nfs_server *server = NFS_SERVER(ino);
        struct nfs4_layoutget *lgp;
        struct pnfs_layout_segment *lseg = NULL;
-       struct page **pages = NULL;
-       int i;
-       u32 max_resp_sz, max_pages;
 
        dprintk("--> %s\n", __func__);
 
@@ -585,20 +583,6 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        if (lgp == NULL)
                return NULL;
 
-       /* allocate pages for xdr post processing */
-       max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
-       max_pages = max_resp_sz >> PAGE_SHIFT;
-
-       pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags);
-       if (!pages)
-               goto out_err_free;
-
-       for (i = 0; i < max_pages; i++) {
-               pages[i] = alloc_page(gfp_flags);
-               if (!pages[i])
-                       goto out_err_free;
-       }
-
        lgp->args.minlength = PAGE_CACHE_SIZE;
        if (lgp->args.minlength > range->length)
                lgp->args.minlength = range->length;
@@ -607,39 +591,19 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        lgp->args.type = server->pnfs_curr_ld->id;
        lgp->args.inode = ino;
        lgp->args.ctx = get_nfs_open_context(ctx);
-       lgp->args.layout.pages = pages;
-       lgp->args.layout.pglen = max_pages * PAGE_SIZE;
        lgp->lsegpp = &lseg;
        lgp->gfp_flags = gfp_flags;
 
        /* Synchronously retrieve layout information from server and
         * store in lseg.
         */
-       nfs4_proc_layoutget(lgp);
+       nfs4_proc_layoutget(lgp, gfp_flags);
        if (!lseg) {
                /* remember that LAYOUTGET failed and suspend trying */
                set_bit(lo_fail_bit(range->iomode), &lo->plh_flags);
        }
 
-       /* free xdr pages */
-       for (i = 0; i < max_pages; i++)
-               __free_page(pages[i]);
-       kfree(pages);
-
        return lseg;
-
-out_err_free:
-       /* free any allocated xdr pages, lgp as it's not used */
-       if (pages) {
-               for (i = 0; i < max_pages; i++) {
-                       if (!pages[i])
-                               break;
-                       __free_page(pages[i]);
-               }
-               kfree(pages);
-       }
-       kfree(lgp);
-       return NULL;
 }
 
 /* Initiates a LAYOUTRETURN(FILE) */
@@ -1177,6 +1141,15 @@ void pnfs_ld_write_done(struct nfs_write_data *data)
                put_lseg(data->lseg);
                data->lseg = NULL;
                dprintk("pnfs write error = %d\n", data->pnfs_error);
+               if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags &
+                                               PNFS_LAYOUTRET_ON_ERROR) {
+                       /* Don't lo_commit on error, Server will needs to
+                        * preform a file recovery.
+                        */
+                       clear_bit(NFS_INO_LAYOUTCOMMIT,
+                                 &NFS_I(data->inode)->flags);
+                       pnfs_return_layout(data->inode);
+               }
        }
        data->mds_ops->rpc_release(data);
 }
@@ -1259,6 +1232,28 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
 
+static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
+{
+       struct nfs_pageio_descriptor pgio;
+
+       put_lseg(data->lseg);
+       data->lseg = NULL;
+       dprintk("pnfs write error = %d\n", data->pnfs_error);
+       if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags &
+                                               PNFS_LAYOUTRET_ON_ERROR)
+               pnfs_return_layout(data->inode);
+
+       nfs_pageio_init_read_mds(&pgio, data->inode);
+
+       while (!list_empty(&data->pages)) {
+               struct nfs_page *req = nfs_list_entry(data->pages.next);
+
+               nfs_list_remove_request(req);
+               nfs_pageio_add_request(&pgio, req);
+       }
+       nfs_pageio_complete(&pgio);
+}
+
 /*
  * Called by non rpc-based layout drivers
  */
@@ -1267,11 +1262,8 @@ void pnfs_ld_read_done(struct nfs_read_data *data)
        if (likely(!data->pnfs_error)) {
                __nfs4_read_done_cb(data);
                data->mds_ops->rpc_call_done(&data->task, data);
-       } else {
-               put_lseg(data->lseg);
-               data->lseg = NULL;
-               dprintk("pnfs write error = %d\n", data->pnfs_error);
-       }
+       } else
+               pnfs_ld_handle_read_error(data);
        data->mds_ops->rpc_release(data);
 }
 EXPORT_SYMBOL_GPL(pnfs_ld_read_done);