[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