FS: Use stable writes when not doing a bulk flush
[deliverable/linux.git] / fs / nfs / pagelist.c
index b68536cc9046ec937b9b4ccddb98b2acf468f1db..fd85618149a1fe6754d1cdfe4d2c1e2b2829ca04 100644 (file)
 #include <linux/nfs_mount.h>
 
 #include "internal.h"
+#include "pnfs.h"
 
 static struct kmem_cache *nfs_page_cachep;
 
 static inline struct nfs_page *
 nfs_page_alloc(void)
 {
-       struct nfs_page *p;
-       p = kmem_cache_alloc(nfs_page_cachep, GFP_KERNEL);
-       if (p) {
-               memset(p, 0, sizeof(*p));
+       struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_KERNEL);
+       if (p)
                INIT_LIST_HEAD(&p->wb_list);
-       }
        return p;
 }
 
@@ -216,7 +214,7 @@ nfs_wait_on_request(struct nfs_page *req)
  */
 void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
                     struct inode *inode,
-                    int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
+                    int (*doio)(struct nfs_pageio_descriptor *),
                     size_t bsize,
                     int io_flags)
 {
@@ -225,10 +223,12 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
        desc->pg_count = 0;
        desc->pg_bsize = bsize;
        desc->pg_base = 0;
+       desc->pg_moreio = 0;
        desc->pg_inode = inode;
        desc->pg_doio = doio;
        desc->pg_ioflags = io_flags;
        desc->pg_error = 0;
+       desc->pg_lseg = NULL;
 }
 
 /**
@@ -243,7 +243,8 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
  * Return 'true' if this is the case, else return 'false'.
  */
 static int nfs_can_coalesce_requests(struct nfs_page *prev,
-                                    struct nfs_page *req)
+                                    struct nfs_page *req,
+                                    struct nfs_pageio_descriptor *pgio)
 {
        if (req->wb_context->cred != prev->wb_context->cred)
                return 0;
@@ -257,6 +258,12 @@ static int nfs_can_coalesce_requests(struct nfs_page *prev,
                return 0;
        if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
                return 0;
+       /*
+        * Non-whole file layouts need to check that req is inside of
+        * pgio->pg_lseg.
+        */
+       if (pgio->pg_test && !pgio->pg_test(pgio, prev, req))
+               return 0;
        return 1;
 }
 
@@ -289,7 +296,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
                if (newlen > desc->pg_bsize)
                        return 0;
                prev = nfs_list_entry(desc->pg_list.prev);
-               if (!nfs_can_coalesce_requests(prev, req))
+               if (!nfs_can_coalesce_requests(prev, req, desc))
                        return 0;
        } else
                desc->pg_base = req->wb_pgbase;
@@ -305,12 +312,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
 static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
 {
        if (!list_empty(&desc->pg_list)) {
-               int error = desc->pg_doio(desc->pg_inode,
-                                         &desc->pg_list,
-                                         nfs_page_array_len(desc->pg_base,
-                                                            desc->pg_count),
-                                         desc->pg_count,
-                                         desc->pg_ioflags);
+               int error = desc->pg_doio(desc);
                if (error < 0)
                        desc->pg_error = error;
                else
@@ -334,9 +336,11 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
                           struct nfs_page *req)
 {
        while (!nfs_pageio_do_add_request(desc, req)) {
+               desc->pg_moreio = 1;
                nfs_pageio_doio(desc);
                if (desc->pg_error < 0)
                        return 0;
+               desc->pg_moreio = 0;
        }
        return 1;
 }
This page took 0.028959 seconds and 5 git commands to generate.