NFSv4.1: filelayout i/o helpers
authorFred Isaman <iisaman@netapp.com>
Tue, 1 Mar 2011 01:34:18 +0000 (01:34 +0000)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 11 Mar 2011 20:38:42 +0000 (15:38 -0500)
Prepare for filelayout_read_pagelist with helper functions that find the correct
data server, filehandle, and offset.

Signed-off-by: Andy Adamson <andros@citi.umich.edu>
Signed-off-by: Dean Hildebrand <dhildeb@us.ibm.com>
Signed-off-by: Fred Isaman <iisaman@netapp.com>
Signed-off-by: Marc Eshel <eshel@almaden.ibm.com>
Signed-off-by: Mike Sager <sager@netapp.com>
Signed-off-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Tao Guo <guotao@nrchpc.ac.cn>
Signed-off-by: Tigran Mkrtchyan <tigran@anahit.desy.de>
Signed-off-by: Tigran Mkrtchyan <tigran.mkrtchyan@desy.de>
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c

index 0efe8cbd9e3cdda4b8cb70802380336e14a10f02..ed833705dcee57e56a05054fdce10c5fde8e71bc 100644 (file)
@@ -66,6 +66,40 @@ filelayout_clear_layoutdriver(struct nfs_server *nfss)
        return 0;
 }
 
+static loff_t
+filelayout_get_dense_offset(struct nfs4_filelayout_segment *flseg,
+                           loff_t offset)
+{
+       u32 stripe_width = flseg->stripe_unit * flseg->dsaddr->stripe_count;
+       u64 tmp;
+
+       offset -= flseg->pattern_offset;
+       tmp = offset;
+       do_div(tmp, stripe_width);
+
+       return tmp * flseg->stripe_unit + do_div(offset, flseg->stripe_unit);
+}
+
+/* This function is used by the layout driver to calculate the
+ * offset of the file on the dserver based on whether the
+ * layout type is STRIPE_DENSE or STRIPE_SPARSE
+ */
+static loff_t
+filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset)
+{
+       struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
+
+       switch (flseg->stripe_type) {
+       case STRIPE_SPARSE:
+               return offset;
+
+       case STRIPE_DENSE:
+               return filelayout_get_dense_offset(flseg, offset);
+       }
+
+       BUG();
+}
+
 /*
  * filelayout_check_layout()
  *
index bbf60dd2ab9d1f4653d7ad54f0e4a79a0c63aca3..9fef76e04936fa318a643a03675725316c7a1550 100644 (file)
@@ -83,9 +83,16 @@ FILELAYOUT_LSEG(struct pnfs_layout_segment *lseg)
                            generic_hdr);
 }
 
+extern struct nfs_fh *
+nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
+
 extern void nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *);
 extern void print_ds(struct nfs4_pnfs_ds *ds);
 extern void print_deviceid(struct nfs4_deviceid *dev_id);
+u32 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset);
+u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j);
+struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg,
+                                       u32 ds_idx);
 extern struct nfs4_file_layout_dsaddr *
 nfs4_fl_find_get_deviceid(struct nfs_client *, struct nfs4_deviceid *dev_id);
 struct nfs4_file_layout_dsaddr *
index 8bc91fb8b6fa7751c3dd0d097e5a4f1d4f449935..f466fed2f46652cfb96c178b037fb10fdc819b97 100644 (file)
@@ -516,3 +516,70 @@ nfs4_fl_find_get_deviceid(struct nfs_client *clp, struct nfs4_deviceid *id)
        return (d == NULL) ? NULL :
                container_of(d, struct nfs4_file_layout_dsaddr, deviceid);
 }
+
+/*
+ * Want res = (offset - layout->pattern_offset)/ layout->stripe_unit
+ * Then: ((res + fsi) % dsaddr->stripe_count)
+ */
+u32
+nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset)
+{
+       struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
+       u64 tmp;
+
+       tmp = offset - flseg->pattern_offset;
+       do_div(tmp, flseg->stripe_unit);
+       tmp += flseg->first_stripe_index;
+       return do_div(tmp, flseg->dsaddr->stripe_count);
+}
+
+u32
+nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j)
+{
+       return FILELAYOUT_LSEG(lseg)->dsaddr->stripe_indices[j];
+}
+
+struct nfs_fh *
+nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j)
+{
+       struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
+       u32 i;
+
+       if (flseg->stripe_type == STRIPE_SPARSE) {
+               if (flseg->num_fh == 1)
+                       i = 0;
+               else if (flseg->num_fh == 0)
+                       /* Use the MDS OPEN fh set in nfs_read_rpcsetup */
+                       return NULL;
+               else
+                       i = nfs4_fl_calc_ds_index(lseg, j);
+       } else
+               i = j;
+       return flseg->fh_array[i];
+}
+
+struct nfs4_pnfs_ds *
+nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
+{
+       struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr;
+       struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
+
+       if (ds == NULL) {
+               printk(KERN_ERR "%s: No data server for offset index %d\n",
+                       __func__, ds_idx);
+               return NULL;
+       }
+
+       if (!ds->ds_clp) {
+               int err;
+
+               err = nfs4_ds_connect(NFS_SERVER(lseg->pls_layout->plh_inode),
+                                         dsaddr->ds_list[ds_idx]);
+               if (err) {
+                       printk(KERN_ERR "%s nfs4_ds_connect error %d\n",
+                              __func__, err);
+                       return NULL;
+               }
+       }
+       return ds;
+}