NFSv4.1 set RPC_TASK_SOFTCONN for filelayout DS RPC calls
[pandora-kernel.git] / fs / nfs / read.c
index 20a0293..2cfdd77 100644 (file)
@@ -35,7 +35,7 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;
 
 static struct kmem_cache *nfs_rdata_cachep;
 
-struct nfs_read_header *nfs_readhdr_alloc()
+struct nfs_read_header *nfs_readhdr_alloc(void)
 {
        struct nfs_read_header *rhdr;
 
@@ -179,34 +179,26 @@ static void nfs_read_completion(struct nfs_pgio_header *hdr)
 
        if (test_bit(NFS_IOHDR_REDO, &hdr->flags))
                goto out;
-       if (!test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
-               while (!list_empty(&hdr->pages)) {
-                       struct nfs_page *req = nfs_list_entry(hdr->pages.next);
-                       struct page *page = req->wb_page;
-
-                       if (test_bit(NFS_IOHDR_EOF, &hdr->flags)) {
-                               if (bytes > hdr->good_bytes)
-                                       zero_user(page, 0, PAGE_SIZE);
-                               else if (hdr->good_bytes - bytes < PAGE_SIZE)
-                                       zero_user_segment(page,
-                                               hdr->good_bytes & ~PAGE_MASK,
-                                               PAGE_SIZE);
-                       }
-                       SetPageUptodate(page);
-                       nfs_list_remove_request(req);
-                       nfs_readpage_release(req);
-                       bytes += PAGE_SIZE;
+       while (!list_empty(&hdr->pages)) {
+               struct nfs_page *req = nfs_list_entry(hdr->pages.next);
+               struct page *page = req->wb_page;
+
+               if (test_bit(NFS_IOHDR_EOF, &hdr->flags)) {
+                       if (bytes > hdr->good_bytes)
+                               zero_user(page, 0, PAGE_SIZE);
+                       else if (hdr->good_bytes - bytes < PAGE_SIZE)
+                               zero_user_segment(page,
+                                       hdr->good_bytes & ~PAGE_MASK,
+                                       PAGE_SIZE);
                }
-       } else {
-               while (!list_empty(&hdr->pages)) {
-                       struct nfs_page *req = nfs_list_entry(hdr->pages.next);
-
-                       bytes += req->wb_bytes;
+               bytes += req->wb_bytes;
+               if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
                        if (bytes <= hdr->good_bytes)
-                               SetPageUptodate(req->wb_page);
-                       nfs_list_remove_request(req);
-                       nfs_readpage_release(req);
-               }
+                               SetPageUptodate(page);
+               } else
+                       SetPageUptodate(page);
+               nfs_list_remove_request(req);
+               nfs_readpage_release(req);
        }
 out:
        hdr->release(hdr);
@@ -214,7 +206,7 @@ out:
 
 int nfs_initiate_read(struct rpc_clnt *clnt,
                      struct nfs_read_data *data,
-                     const struct rpc_call_ops *call_ops)
+                     const struct rpc_call_ops *call_ops, int flags)
 {
        struct inode *inode = data->header->inode;
        int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0;
@@ -231,7 +223,7 @@ int nfs_initiate_read(struct rpc_clnt *clnt,
                .callback_ops = call_ops,
                .callback_data = data,
                .workqueue = nfsiod_workqueue,
-               .flags = RPC_TASK_ASYNC | swap_flags,
+               .flags = RPC_TASK_ASYNC | swap_flags | flags,
        };
 
        /* Set up the initial task struct. */
@@ -280,7 +272,7 @@ static int nfs_do_read(struct nfs_read_data *data,
 {
        struct inode *inode = data->header->inode;
 
-       return nfs_initiate_read(NFS_CLIENT(inode), data, call_ops);
+       return nfs_initiate_read(NFS_CLIENT(inode), data, call_ops, 0);
 }
 
 static int
@@ -320,6 +312,19 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = {
        .completion = nfs_read_completion,
 };
 
+static void nfs_pagein_error(struct nfs_pageio_descriptor *desc,
+               struct nfs_pgio_header *hdr)
+{
+       set_bit(NFS_IOHDR_REDO, &hdr->flags);
+       while (!list_empty(&hdr->rpc_list)) {
+               struct nfs_read_data *data = list_first_entry(&hdr->rpc_list,
+                               struct nfs_read_data, list);
+               list_del(&data->list);
+               nfs_readdata_release(data);
+       }
+       desc->pg_completion_ops->error_cleanup(&desc->pg_list);
+}
+
 /*
  * Generate multiple requests to fill a single page.
  *
@@ -342,33 +347,27 @@ static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc,
        size_t rsize = desc->pg_bsize, nbytes;
        unsigned int offset;
 
-       nfs_list_remove_request(req);
-       nfs_list_add_request(req, &hdr->pages);
-
        offset = 0;
        nbytes = desc->pg_count;
        do {
                size_t len = min(nbytes,rsize);
 
                data = nfs_readdata_alloc(hdr, 1);
-               if (!data)
-                       goto out_bad;
+               if (!data) {
+                       nfs_pagein_error(desc, hdr);
+                       return -ENOMEM;
+               }
                data->pages.pagevec[0] = page;
                nfs_read_rpcsetup(data, len, offset);
                list_add(&data->list, &hdr->rpc_list);
                nbytes -= len;
                offset += len;
        } while (nbytes != 0);
+
+       nfs_list_remove_request(req);
+       nfs_list_add_request(req, &hdr->pages);
        desc->pg_rpc_callops = &nfs_read_common_ops;
        return 0;
-out_bad:
-       while (!list_empty(&hdr->rpc_list)) {
-               data = list_first_entry(&hdr->rpc_list, struct nfs_read_data, list);
-               list_del(&data->list);
-               nfs_readdata_release(data);
-       }
-       desc->pg_completion_ops->error_cleanup(&hdr->pages);
-       return -ENOMEM;
 }
 
 static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,
@@ -378,12 +377,11 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,
        struct page             **pages;
        struct nfs_read_data    *data;
        struct list_head *head = &desc->pg_list;
-       int ret = 0;
 
        data = nfs_readdata_alloc(hdr, nfs_page_array_len(desc->pg_base,
                                                          desc->pg_count));
        if (!data) {
-               desc->pg_completion_ops->error_cleanup(head);
+               nfs_pagein_error(desc, hdr);
                return -ENOMEM;
        }
 
@@ -427,8 +425,6 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
        if (ret == 0)
                ret = nfs_do_multiple_reads(&hdr->rpc_list,
                                            desc->pg_rpc_callops);
-       else
-               set_bit(NFS_IOHDR_REDO, &hdr->flags);
        if (atomic_dec_and_test(&hdr->refcnt))
                hdr->completion_ops->completion(hdr);
        return ret;