Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[pandora-kernel.git] / fs / nfs / nfs4filelayout.c
index be79dc9..0bafcc9 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include <linux/nfs_fs.h>
+#include <linux/nfs_page.h>
 
 #include "internal.h"
 #include "nfs4filelayout.h"
@@ -421,6 +422,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
                        struct nfs4_deviceid *id,
                        gfp_t gfp_flags)
 {
+       struct nfs4_deviceid_node *d;
        struct nfs4_file_layout_dsaddr *dsaddr;
        int status = -EINVAL;
        struct nfs_server *nfss = NFS_SERVER(lo->plh_inode);
@@ -428,7 +430,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
        dprintk("--> %s\n", __func__);
 
        if (fl->pattern_offset > lgr->range.offset) {
-               dprintk("%s pattern_offset %lld to large\n",
+               dprintk("%s pattern_offset %lld too large\n",
                                __func__, fl->pattern_offset);
                goto out;
        }
@@ -440,12 +442,14 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
        }
 
        /* find and reference the deviceid */
-       dsaddr = nfs4_fl_find_get_deviceid(id);
-       if (dsaddr == NULL) {
+       d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode)->pnfs_curr_ld,
+                                  NFS_SERVER(lo->plh_inode)->nfs_client, id);
+       if (d == NULL) {
                dsaddr = get_device_info(lo->plh_inode, id, gfp_flags);
                if (dsaddr == NULL)
                        goto out;
-       }
+       } else
+               dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
        fl->dsaddr = dsaddr;
 
        if (fl->first_stripe_index < 0 ||
@@ -507,12 +511,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                         gfp_t gfp_flags)
 {
        struct xdr_stream stream;
-       struct xdr_buf buf = {
-               .pages =  lgr->layoutp->pages,
-               .page_len =  lgr->layoutp->len,
-               .buflen =  lgr->layoutp->len,
-               .len = lgr->layoutp->len,
-       };
+       struct xdr_buf buf;
        struct page *scratch;
        __be32 *p;
        uint32_t nfl_util;
@@ -524,7 +523,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
        if (!scratch)
                return -ENOMEM;
 
-       xdr_init_decode(&stream, &buf, NULL);
+       xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len);
        xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
 
        /* 20 = ufl_util (4), first_stripe_index (4), pattern_offset (8),
@@ -535,7 +534,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
 
        memcpy(id, p, sizeof(*id));
        p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
-       print_deviceid(id);
+       nfs4_print_deviceid(id);
 
        nfl_util = be32_to_cpup(p++);
        if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS)
@@ -554,13 +553,18 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                __func__, nfl_util, fl->num_fh, fl->first_stripe_index,
                fl->pattern_offset);
 
-       if (!fl->num_fh)
+       /* Note that a zero value for num_fh is legal for STRIPE_SPARSE.
+        * Futher checking is done in filelayout_check_layout */
+       if (fl->num_fh < 0 || fl->num_fh >
+           max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT))
                goto out_err;
 
-       fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
-                              gfp_flags);
-       if (!fl->fh_array)
-               goto out_err;
+       if (fl->num_fh > 0) {
+               fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+                                      gfp_flags);
+               if (!fl->fh_array)
+                       goto out_err;
+       }
 
        for (i = 0; i < fl->num_fh; i++) {
                /* Do we want to use a mempool here? */
@@ -653,16 +657,20 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
 /*
  * filelayout_pg_test(). Called by nfs_can_coalesce_requests()
  *
- * return 1 :  coalesce page
- * return 0 :  don't coalesce page
+ * return true  : coalesce page
+ * return false : don't coalesce page
  */
-int
+bool
 filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
                   struct nfs_page *req)
 {
        u64 p_stripe, r_stripe;
        u32 stripe_unit;
 
+       if (!pnfs_generic_pg_test(pgio, prev, req) ||
+           !nfs_generic_pg_test(pgio, prev, req))
+               return false;
+
        if (!pgio->pg_lseg)
                return 1;
        p_stripe = (u64)prev->wb_index << PAGE_CACHE_SHIFT;
@@ -860,6 +868,12 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
        return -ENOMEM;
 }
 
+static void
+filelayout_free_deveiceid_node(struct nfs4_deviceid_node *d)
+{
+       nfs4_fl_free_deviceid(container_of(d, struct nfs4_file_layout_dsaddr, id_node));
+}
+
 static struct pnfs_layoutdriver_type filelayout_type = {
        .id                     = LAYOUT_NFSV4_1_FILES,
        .name                   = "LAYOUT_NFSV4_1_FILES",
@@ -872,6 +886,7 @@ static struct pnfs_layoutdriver_type filelayout_type = {
        .commit_pagelist        = filelayout_commit_pagelist,
        .read_pagelist          = filelayout_read_pagelist,
        .write_pagelist         = filelayout_write_pagelist,
+       .free_deviceid_node     = filelayout_free_deveiceid_node,
 };
 
 static int __init nfs4filelayout_init(void)