NFS: ask for layouttypes during v4 fsinfo call
authorAndy Adamson <andros@netapp.com>
Wed, 20 Oct 2010 04:17:57 +0000 (00:17 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Sun, 24 Oct 2010 22:07:09 +0000 (18:07 -0400)
This information will be used to determine which layout driver,
if any, to use for subsequent IO on this filesystem.  Each driver
is assigned an integer id, with 0 reserved to indicate no driver.

The server can in theory return multiple ids.  However, our current
client implementation only notes the first entry and ignores the
rest.

Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Fred Isaman <iisaman@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/nfs_xdr.h

index e87fe612ca184426d13118377c5f2f1f440e6af4..a5f1edb45b47068a60bb0ce08a243a5ed8a694c1 100644 (file)
@@ -130,6 +130,7 @@ const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE
                        | FATTR4_WORD0_MAXWRITE
                        | FATTR4_WORD0_LEASE_TIME,
                        FATTR4_WORD1_TIME_DELTA
+                       | FATTR4_WORD1_FS_LAYOUT_TYPES
 };
 
 const u32 nfs4_fs_locations_bitmap[2] = {
index bd2101d918c80cda6d6f21b03f696e5312803676..8b4dfa393f0f0cd27e3a39b59ceb58e885600549 100644 (file)
@@ -3978,6 +3978,61 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
        return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep);
 }
 
+/*
+ * Decode potentially multiple layout types. Currently we only support
+ * one layout driver per file system.
+ */
+static int decode_first_pnfs_layout_type(struct xdr_stream *xdr,
+                                        uint32_t *layouttype)
+{
+       uint32_t *p;
+       int num;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       num = be32_to_cpup(p);
+
+       /* pNFS is not supported by the underlying file system */
+       if (num == 0) {
+               *layouttype = 0;
+               return 0;
+       }
+       if (num > 1)
+               printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers "
+                       "per filesystem not supported\n", __func__);
+
+       /* Decode and set first layout type, move xdr->p past unused types */
+       p = xdr_inline_decode(xdr, num * 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       *layouttype = be32_to_cpup(p);
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
+/*
+ * The type of file system exported.
+ * Note we must ensure that layouttype is set in any non-error case.
+ */
+static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap,
+                               uint32_t *layouttype)
+{
+       int status = 0;
+
+       dprintk("%s: bitmap is %x\n", __func__, bitmap[1]);
+       if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U)))
+               return -EIO;
+       if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) {
+               status = decode_first_pnfs_layout_type(xdr, layouttype);
+               bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES;
+       } else
+               *layouttype = 0;
+       return status;
+}
+
 static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
 {
        __be32 *savep;
@@ -4004,6 +4059,9 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
                goto xdr_error;
        fsinfo->wtpref = fsinfo->wtmax;
        status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta);
+       if (status != 0)
+               goto xdr_error;
+       status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype);
        if (status != 0)
                goto xdr_error;
 
index da7a1300dc60bb01423cafd64cb8028b7de5dcb2..065f9d105d05bd5bac2d6ded8e3462b7eedce89c 100644 (file)
@@ -114,6 +114,7 @@ struct nfs_fsinfo {
        __u64                   maxfilesize;
        struct timespec         time_delta; /* server time granularity */
        __u32                   lease_time; /* in seconds */
+       __u32                   layouttype; /* supported pnfs layout driver */
 };
 
 struct nfs_fsstat {