}
 
        fsinfo.fattr = fattr;
+       fsinfo.nlayouttypes = 0;
        memset(fsinfo.layouttype, 0, sizeof(fsinfo.layouttype));
        error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
        if (error < 0)
 
        if (error == 0) {
                /* block layout checks this! */
                server->pnfs_blksize = fsinfo->blksize;
-               set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype);
+               set_pnfs_layoutdriver(server, fhandle, fsinfo);
        }
 
        return error;
 
  * Decode potentially multiple layout types.
  */
 static int decode_pnfs_layout_types(struct xdr_stream *xdr,
-                                        uint32_t *layouttype)
+                                   struct nfs_fsinfo *fsinfo)
 {
        __be32 *p;
-       uint32_t num, i;
+       uint32_t i;
 
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                goto out_overflow;
-       num = be32_to_cpup(p);
+       fsinfo->nlayouttypes = be32_to_cpup(p);
 
        /* pNFS is not supported by the underlying file system */
-       if (num == 0) {
+       if (fsinfo->nlayouttypes == 0)
                return 0;
-       }
-       if (num > NFS_MAX_LAYOUT_TYPES)
-               printk(KERN_INFO "NFS: %s: Warning: Too many (%d) pNFS layout types\n", __func__, num);
 
        /* Decode and set first layout type, move xdr->p past unused types */
-       p = xdr_inline_decode(xdr, num * 4);
+       p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4);
        if (unlikely(!p))
                goto out_overflow;
-       for(i = 0; i < num && i < NFS_MAX_LAYOUT_TYPES; i++)
-               layouttype[i] = be32_to_cpup(p++);
+
+       /* If we get too many, then just cap it at the max */
+       if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) {
+               printk(KERN_INFO "NFS: %s: Warning: Too many (%u) pNFS layout types\n",
+                       __func__, fsinfo->nlayouttypes);
+               fsinfo->nlayouttypes = NFS_MAX_LAYOUT_TYPES;
+       }
+
+       for(i = 0; i < fsinfo->nlayouttypes; ++i)
+               fsinfo->layouttype[i] = be32_to_cpup(p++);
        return 0;
 out_overflow:
        print_overflow_msg(__func__, xdr);
  * 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)
+                               struct nfs_fsinfo *fsinfo)
 {
        int status = 0;
 
        if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U)))
                return -EIO;
        if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) {
-               status = decode_pnfs_layout_types(xdr, layouttype);
+               status = decode_pnfs_layout_types(xdr, fsinfo);
                bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES;
        }
        return status;
        status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta);
        if (status != 0)
                goto xdr_error;
-       status = decode_attr_pnfstype(xdr, bitmap, fsinfo->layouttype);
+       status = decode_attr_pnfstype(xdr, bitmap, fsinfo);
        if (status != 0)
                goto xdr_error;
 
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
 #include <linux/module.h>
+#include <linux/sort.h>
 #include "internal.h"
 #include "pnfs.h"
 #include "iostat.h"
        nfss->pnfs_curr_ld = NULL;
 }
 
+/*
+ * When the server sends a list of layout types, we choose one in the order
+ * given in the list below.
+ *
+ * FIXME: should this list be configurable in some fashion? module param?
+ *       mount option? something else?
+ */
+static const u32 ld_prefs[] = {
+       LAYOUT_SCSI,
+       LAYOUT_BLOCK_VOLUME,
+       LAYOUT_OSD2_OBJECTS,
+       LAYOUT_FLEX_FILES,
+       LAYOUT_NFSV4_1_FILES,
+       0
+};
+
+static int
+ld_cmp(const void *e1, const void *e2)
+{
+       u32 ld1 = *((u32 *)e1);
+       u32 ld2 = *((u32 *)e2);
+       int i;
+
+       for (i = 0; ld_prefs[i] != 0; i++) {
+               if (ld1 == ld_prefs[i])
+                       return -1;
+
+               if (ld2 == ld_prefs[i])
+                       return 1;
+       }
+       return 0;
+}
+
 /*
  * Try to set the server's pnfs module to the pnfs layout type specified by id.
  * Currently only one pNFS layout driver per filesystem is supported.
  */
 void
 set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh,
-                     u32 *ids)
+                     struct nfs_fsinfo *fsinfo)
 {
        struct pnfs_layoutdriver_type *ld_type = NULL;
        u32 id;
+       int i;
 
        if (!(server->nfs_client->cl_exchange_flags &
                 (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) {
                goto out_no_driver;
        }
 
-       id = ids[0];
-       if (!id)
-               goto out_no_driver;
+       sort(fsinfo->layouttype, fsinfo->nlayouttypes,
+               sizeof(*fsinfo->layouttype), ld_cmp, NULL);
 
-       ld_type = find_pnfs_driver(id);
-       if (!ld_type) {
-               request_module("%s-%u", LAYOUT_NFSV4_1_MODULE_PREFIX, id);
+       for (i = 0; i < fsinfo->nlayouttypes; i++) {
+               id = fsinfo->layouttype[i];
                ld_type = find_pnfs_driver(id);
+               if (!ld_type) {
+                       request_module("%s-%u", LAYOUT_NFSV4_1_MODULE_PREFIX,
+                                       id);
+                       ld_type = find_pnfs_driver(id);
+               }
+               if (ld_type)
+                       break;
        }
 
        if (!ld_type) {
-               dprintk("%s: No pNFS module found for %u.\n", __func__, id);
+               dprintk("%s: No pNFS module found!\n", __func__);
                goto out_no_driver;
        }
 
 
 void pnfs_put_lseg(struct pnfs_layout_segment *lseg);
 void pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg);
 
-void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32 *);
+void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, struct nfs_fsinfo *);
 void unset_pnfs_layoutdriver(struct nfs_server *);
 void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
 int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
 }
 
 static inline void set_pnfs_layoutdriver(struct nfs_server *s,
-                                        const struct nfs_fh *mntfh, u32 *ids)
+                                        const struct nfs_fh *mntfh,
+                                        struct nfs_fsinfo *fsinfo)
 {
 }
 
 
        __u64                   maxfilesize;
        struct timespec         time_delta; /* server time granularity */
        __u32                   lease_time; /* in seconds */
+       __u32                   nlayouttypes; /* number of layouttypes */
        __u32                   layouttype[NFS_MAX_LAYOUT_TYPES]; /* supported pnfs layout driver */
        __u32                   blksize; /* preferred pnfs io block size */
        __u32                   clone_blksize; /* granularity of a CLONE operation */