[pnfs] [PATCH 10/21] pnfsblock: xdr decode pnfs_block_layout4
Fred Isaman
iisaman at citi.umich.edu
Thu Apr 10 10:07:26 EDT 2008
XDR decodes the block layout payload sent in LAYOUTGET result.
Signed-off-by: Fred Isaman <iisaman at citi.umich.edu>
Signed-off-by: Benny Halevy <bhalevy at panasas.com>
pnfsblock: fix pnfs_deviceid references
the pnfs_deviceid typedef was changed to struct pnfs_deviceid
Signed-off-by: Fred Isaman <iisaman at citi.umich.edu>
Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
fs/nfs/blocklayout/blocklayout.c | 64 +++++++++++++++++++++++++++-
fs/nfs/blocklayout/blocklayout.h | 29 +++++++++++++
fs/nfs/blocklayout/blocklayoutdev.c | 80 +++++++++++++++++++++++++++++++++++
3 files changed, 172 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index 295256f..7a39638 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -43,6 +43,26 @@ MODULE_DESCRIPTION("The NFSv4.1 pNFS Block layout driver");
/* Callback operations to the pNFS client */
struct pnfs_client_operations *pnfs_callback_ops;
+static void
+destroy_extent(struct kref *kref)
+{
+ struct pnfs_block_extent *be;
+
+ be = container_of(kref, struct pnfs_block_extent, be_refcnt);
+ dprintk("%s be=%p\n", __func__, be);
+ kfree(be);
+}
+
+static void
+put_extent(struct pnfs_block_extent *be)
+{
+ if (be) {
+ dprintk("%s enter %p (%i)\n", __func__, be,
+ atomic_read(&be->be_refcnt.refcount));
+ kref_put(&be->be_refcnt, destroy_extent);
+ }
+}
+
static int
bl_commit(struct pnfs_layout_type *layoutid,
int sync,
@@ -89,6 +109,22 @@ bl_write_pagelist(struct pnfs_layout_type *layoutid,
}
static void
+release_extents(struct pnfs_block_layout *bl)
+{
+ struct pnfs_block_extent *be;
+
+ spin_lock(&bl->bl_ext_lock);
+ while (!list_empty(&bl->bl_extents)) {
+ be = list_first_entry(&bl->bl_extents, struct pnfs_block_extent,
+ be_node);
+ list_del(&be->be_node);
+ put_extent(be);
+ }
+ bl->bl_n_ext = 0;
+ spin_unlock(&bl->bl_ext_lock);
+}
+
+static void
bl_free_layout(struct pnfs_layout_type *lt)
{
dprintk("%s enter\n", __func__);
@@ -110,7 +146,14 @@ bl_alloc_layout(struct pnfs_mount_type *mtype, struct inode *inode)
static void
bl_free_lseg(struct pnfs_layout_segment *lseg)
{
+ struct pnfs_block_layout *bl;
+
dprintk("%s enter\n", __func__);
+ if (lseg) {
+ bl = (struct pnfs_block_layout *)lseg->ld_data;
+ release_extents(bl);
+ kfree(lseg);
+ }
return;
}
@@ -118,8 +161,27 @@ static struct pnfs_layout_segment *
bl_alloc_lseg(struct pnfs_layout_type *layoutid,
struct nfs4_pnfs_layoutget_res *lgr)
{
+ struct pnfs_layout_segment *lseg;
+ struct pnfs_block_layout *bl;
+ int status;
+
dprintk("%s enter\n", __func__);
- return NULL;
+ lseg = kzalloc(sizeof(*lseg) + sizeof(*bl), GFP_KERNEL);
+ if (!lseg)
+ return NULL;
+ bl = (struct pnfs_block_layout *) lseg->ld_data;
+ /* This is needed to get layoutid->ld_data (metadevice list) from bl */
+ lseg->layout = layoutid;
+
+ spin_lock_init(&bl->bl_ext_lock);
+ INIT_LIST_HEAD(&bl->bl_extents);
+
+ status = nfs4_blk_process_layoutget(bl, lgr);
+ if (status) {
+ bl_free_lseg(lseg);
+ return ERR_PTR(status);
+ }
+ return lseg;
}
static int
diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
index 942b0cc..b9241d8 100644
--- a/fs/nfs/blocklayout/blocklayout.h
+++ b/fs/nfs/blocklayout/blocklayout.h
@@ -98,6 +98,33 @@ struct pnfs_blk_sig {
struct pnfs_blk_sig_comp si_comps[PNFS_BLOCK_MAX_SIG_COMP];
};
+enum exstate4 {
+ PNFS_BLOCK_READWRITE_DATA = 0,
+ PNFS_BLOCK_READ_DATA = 1,
+ PNFS_BLOCK_INVALID_DATA = 2, /* mapped, but data is invalid */
+ PNFS_BLOCK_NONE_DATA = 3 /* unmapped, it's a hole */
+};
+
+/* sector_t fields are all in 512-byte sectors */
+struct pnfs_block_extent {
+ struct list_head be_node;
+ struct pnfs_deviceid be_devid;
+ struct block_device *be_mdev;
+ sector_t be_f_offset; /* the starting offset in the file */
+ sector_t be_length; /* the size of the extent */
+ sector_t be_v_offset; /* the starting offset in the volume */
+ enum exstate4 be_state; /* the state of this extent */
+ struct kref be_refcnt;
+};
+
+struct pnfs_block_layout {
+ spinlock_t bl_ext_lock; /* protects list manipulation */
+ uint32_t bl_n_ext;
+ struct list_head bl_extents;
+};
+
+#define BLK_ID(lt) ((struct block_mount_id *)(PNFS_MOUNTID(lt)->mountid))
+
uint32_t *blk_overflow(uint32_t *p, uint32_t *end, size_t nbytes);
#define BLK_READBUF(p, e, nbytes) do { \
@@ -136,6 +163,8 @@ int nfs4_blkdev_put(struct block_device *bdev);
struct pnfs_block_dev *nfs4_blk_decode_device(struct super_block *sb,
struct pnfs_device *dev,
struct list_head *sdlist);
+int nfs4_blk_process_layoutget(struct pnfs_block_layout *bl,
+ struct nfs4_pnfs_layoutget_res *lgr);
int nfs4_blk_create_scsi_disk_list(struct list_head *);
void nfs4_blk_destroy_disk_list(struct list_head *);
struct pnfs_block_dev *nfs4_blk_init_metadev(struct super_block *sb,
diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c
index a35c42a..3bb385e 100644
--- a/fs/nfs/blocklayout/blocklayoutdev.c
+++ b/fs/nfs/blocklayout/blocklayoutdev.c
@@ -504,3 +504,83 @@ nfs4_blk_decode_device(struct super_block *sb,
kfree(vols);
return rv;
}
+
+static struct block_device *translate_devid(struct pnfs_block_layout *bl,
+ struct pnfs_deviceid *id)
+{
+ struct pnfs_layout_segment *lseg;
+ struct block_device *rv = NULL;
+ struct block_mount_id *mid;
+ struct pnfs_block_dev *dev;
+
+ dprintk("%s enter, bl=%p, id=%p\n", __func__, bl, id);
+ lseg = container_of((void *)bl, struct pnfs_layout_segment, ld_data);
+ mid = BLK_ID(lseg->layout);
+ spin_lock(&mid->bm_lock);
+ list_for_each_entry(dev, &mid->bm_devlist, bm_node) {
+ if (memcmp(id->data, dev->bm_mdevid.data,
+ NFS4_PNFS_DEVICEID4_SIZE) == 0) {
+ rv = dev->bm_mdev;
+ goto out;
+ }
+ }
+ out:
+ spin_unlock(&mid->bm_lock);
+ dprintk("%s returning %p\n", __func__, rv);
+ return rv;
+}
+
+/* XDR decode pnfs_block_layout4 structure */
+int
+nfs4_blk_process_layoutget(struct pnfs_block_layout *bl,
+ struct nfs4_pnfs_layoutget_res *lgr)
+{
+ uint32_t *p = (uint32_t *)lgr->layout.buf;
+ uint32_t *end = (uint32_t *)((char *)lgr->layout.buf + lgr->layout.len);
+ int i, status = -EIO;
+ uint32_t count;
+
+ BLK_READBUF(p, end, 4);
+ READ32(count);
+
+ dprintk("%s enter, number of extents %i\n", __func__, count);
+ BLK_READBUF(p, end, (28 + NFS4_PNFS_DEVICEID4_SIZE) * count);
+
+ for (i = 0; i < count; i++) {
+ struct pnfs_block_extent *be;
+ uint64_t tmp; /* Used by READSECTOR */
+
+ be = kmalloc(sizeof(struct pnfs_block_extent), GFP_KERNEL);
+ if (!be) {
+ status = -ENOMEM;
+ goto out_err;
+ }
+ INIT_LIST_HEAD(&be->be_node);
+ kref_init(&be->be_refcnt);
+ READ_DEVID(&be->be_devid);
+ be->be_mdev = translate_devid(bl, &be->be_devid);
+ if (!be->be_mdev)
+ goto out_err;
+ /* The next three values are read in as bytes,
+ * but stored as 512-byte sector lengths
+ */
+ READ_SECTOR(be->be_f_offset);
+ READ_SECTOR(be->be_length);
+ READ_SECTOR(be->be_v_offset);
+ READ32(be->be_state);
+
+ spin_lock(&bl->bl_ext_lock);
+ list_add_tail(&be->be_node, &bl->bl_extents);
+ bl->bl_n_ext++;
+ spin_unlock(&bl->bl_ext_lock);
+ }
+ if (p != end) {
+ dprintk("%s Undecoded cruft at end of opaque\n", __func__);
+ status = -EIO;
+ goto out_err;
+ }
+ status = 0;
+ out_err:
+ dprintk("%s returns %i\n", __func__, status);
+ return status;
+}
--
1.5.3.3
More information about the pNFS
mailing list