From 29662fa646b41492a9c298a83399126f94847e93 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 17 Aug 2015 18:40:57 +0200 Subject: pnfs/blocklayout: calculate layoutupdate size correctly We need to include the first u32 for the number of entries. Add a helper for the calculation instead of opencoding it so that it's in one place. Signed-off-by: Christoph Hellwig Signed-off-by: Trond Myklebust --- fs/nfs/blocklayout/extent_tree.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'fs/nfs/blocklayout') diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c index 31d0b5e53dfd..7536036fb526 100644 --- a/fs/nfs/blocklayout/extent_tree.c +++ b/fs/nfs/blocklayout/extent_tree.c @@ -462,6 +462,12 @@ out: return err; } +static size_t ext_tree_layoutupdate_size(size_t count) +{ + return sizeof(__be32) /* number of entries */ + + BL_EXTENT_SIZE * count; +} + static void ext_tree_free_commitdata(struct nfs4_layoutcommit_args *arg, size_t buffer_size) { @@ -489,7 +495,7 @@ static int ext_tree_encode_commit(struct pnfs_block_layout *bl, __be32 *p, continue; (*count)++; - if (*count * BL_EXTENT_SIZE > buffer_size) { + if (ext_tree_layoutupdate_size(*count) > buffer_size) { /* keep counting.. */ ret = -ENOSPC; continue; @@ -530,7 +536,7 @@ retry: if (unlikely(ret)) { ext_tree_free_commitdata(arg, buffer_size); - buffer_size = sizeof(__be32) + BL_EXTENT_SIZE * count; + buffer_size = ext_tree_layoutupdate_size(count); count = 0; arg->layoutupdate_pages = @@ -549,7 +555,7 @@ retry: } *start_p = cpu_to_be32(count); - arg->layoutupdate_len = sizeof(__be32) + BL_EXTENT_SIZE * count; + arg->layoutupdate_len = ext_tree_layoutupdate_size(count); if (unlikely(arg->layoutupdate_pages != &arg->layoutupdate_page)) { __be32 *p = start_p; -- cgit v1.2.3 From 68596bd188e5e621c28a2f6fc0a3dd80a606d16b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 17 Aug 2015 18:40:58 +0200 Subject: pnfs/blocklayout: set up layoutupdate_pages properly We need to replace the __be32 with a void pointer to do proper arithmentics on the virtual addresses so that we can get the right page pointers. Reported-by: Dan Carpenter Signed-off-by: Christoph Hellwig Signed-off-by: Trond Myklebust --- fs/nfs/blocklayout/extent_tree.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'fs/nfs/blocklayout') diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c index 7536036fb526..a11b759d294a 100644 --- a/fs/nfs/blocklayout/extent_tree.c +++ b/fs/nfs/blocklayout/extent_tree.c @@ -558,14 +558,11 @@ retry: arg->layoutupdate_len = ext_tree_layoutupdate_size(count); if (unlikely(arg->layoutupdate_pages != &arg->layoutupdate_page)) { - __be32 *p = start_p; + void *p = start_p, *end = p + arg->layoutupdate_len; int i = 0; - for (p = start_p; - p < start_p + arg->layoutupdate_len; - p += PAGE_SIZE) { + for ( ; p < end; p += PAGE_SIZE) arg->layoutupdate_pages[i++] = vmalloc_to_page(p); - } } dprintk("%s found %zu ranges\n", __func__, count); -- cgit v1.2.3 From 2bd3c63a333c364cfde4701b51f82e1fae106a88 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 17 Aug 2015 18:40:59 +0200 Subject: pnfs/blocklayout: reject too long signatures Instead of overwriting kernel memory reject too long signatures. Signed-off-by: Christoph Hellwig Signed-off-by: Trond Myklebust --- fs/nfs/blocklayout/dev.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs/nfs/blocklayout') diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c index e535599a0719..d76993a42432 100644 --- a/fs/nfs/blocklayout/dev.c +++ b/fs/nfs/blocklayout/dev.c @@ -65,6 +65,11 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b) return -EIO; p = xdr_decode_hyper(p, &b->simple.sigs[i].offset); b->simple.sigs[i].sig_len = be32_to_cpup(p++); + if (b->simple.sigs[i].sig_len > PNFS_BLOCK_UUID_LEN) { + pr_info("signature too long: %d\n", + b->simple.sigs[i].sig_len); + return -EIO; + } p = xdr_inline_decode(xdr, b->simple.sigs[i].sig_len); if (!p) -- cgit v1.2.3 From 513d6d7a9591d7c5ebb5f05465942185db9299a4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 17 Aug 2015 18:41:00 +0200 Subject: pnfs/blocklayout: pass proper file mode to blkdev_get/put We generally want to read and write to a block device that's used by the pNFS block layout client (and even if it's read only the server has no way of telling us). Add FMODE_WRITE to the mode argument so that we don't incorrectly tell the block driver that we want a read-only open. Signed-off-by: Christoph Hellwig Signed-off-by: Trond Myklebust --- fs/nfs/blocklayout/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/nfs/blocklayout') diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c index d76993a42432..a861bbdfe577 100644 --- a/fs/nfs/blocklayout/dev.c +++ b/fs/nfs/blocklayout/dev.c @@ -22,7 +22,7 @@ bl_free_device(struct pnfs_block_dev *dev) kfree(dev->children); } else { if (dev->bdev) - blkdev_put(dev->bdev, FMODE_READ); + blkdev_put(dev->bdev, FMODE_READ | FMODE_WRITE); } } @@ -200,7 +200,7 @@ bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d, if (!dev) return -EIO; - d->bdev = blkdev_get_by_dev(dev, FMODE_READ, NULL); + d->bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_WRITE, NULL); if (IS_ERR(d->bdev)) { printk(KERN_WARNING "pNFS: failed to open device %d:%d (%ld)\n", MAJOR(dev), MINOR(dev), PTR_ERR(d->bdev)); -- cgit v1.2.3 From 8bb28975823aee062f82b99ddacc499601c0cfd1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 17 Aug 2015 18:41:01 +0200 Subject: pnfs: move common blocklayout XDR defintions to nfs4.h Signed-off-by: Christoph Hellwig Signed-off-by: Trond Myklebust --- fs/nfs/blocklayout/blocklayout.h | 19 +------------------ fs/nfs/blocklayout/extent_tree.c | 2 +- fs/nfsd/blocklayoutxdr.c | 2 +- fs/nfsd/blocklayoutxdr.h | 15 --------------- include/linux/nfs4.h | 18 ++++++++++++++++++ 5 files changed, 21 insertions(+), 35 deletions(-) (limited to 'fs/nfs/blocklayout') diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index 92dca9e90d8d..c556640dcf3b 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h @@ -46,13 +46,6 @@ struct pnfs_block_dev; -enum pnfs_block_volume_type { - PNFS_BLOCK_VOLUME_SIMPLE = 0, - PNFS_BLOCK_VOLUME_SLICE = 1, - PNFS_BLOCK_VOLUME_CONCAT = 2, - PNFS_BLOCK_VOLUME_STRIPE = 3, -}; - #define PNFS_BLOCK_MAX_UUIDS 4 #define PNFS_BLOCK_MAX_DEVICES 64 @@ -117,13 +110,6 @@ struct pnfs_block_dev { struct pnfs_block_dev_map *map); }; -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 { union { @@ -134,15 +120,12 @@ struct pnfs_block_extent { 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 */ + enum pnfs_block_extent_state be_state; /* the state of this extent */ #define EXTENT_WRITTEN 1 #define EXTENT_COMMITTING 2 unsigned int be_tag; }; -/* on the wire size of the extent */ -#define BL_EXTENT_SIZE (7 * sizeof(__be32) + NFS4_DEVICEID4_SIZE) - struct pnfs_block_layout { struct pnfs_layout_hdr bl_layout; struct rb_root bl_ext_rw; diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c index a11b759d294a..c59a59c37f3d 100644 --- a/fs/nfs/blocklayout/extent_tree.c +++ b/fs/nfs/blocklayout/extent_tree.c @@ -465,7 +465,7 @@ out: static size_t ext_tree_layoutupdate_size(size_t count) { return sizeof(__be32) /* number of entries */ + - BL_EXTENT_SIZE * count; + PNFS_BLOCK_EXTENT_SIZE * count; } static void ext_tree_free_commitdata(struct nfs4_layoutcommit_args *arg, diff --git a/fs/nfsd/blocklayoutxdr.c b/fs/nfsd/blocklayoutxdr.c index 9aa2796da90d..6d834dc9bbc8 100644 --- a/fs/nfsd/blocklayoutxdr.c +++ b/fs/nfsd/blocklayoutxdr.c @@ -101,7 +101,7 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp, } nr_iomaps = be32_to_cpup(p++); - expected = sizeof(__be32) + nr_iomaps * NFS4_BLOCK_EXTENT_SIZE; + expected = sizeof(__be32) + nr_iomaps * PNFS_BLOCK_EXTENT_SIZE; if (len != expected) { dprintk("%s: extent array size mismatch: %u/%u\n", __func__, len, expected); diff --git a/fs/nfsd/blocklayoutxdr.h b/fs/nfsd/blocklayoutxdr.h index fdc79037c0e7..6de925fe8499 100644 --- a/fs/nfsd/blocklayoutxdr.h +++ b/fs/nfsd/blocklayoutxdr.h @@ -7,13 +7,6 @@ struct iomap; struct xdr_stream; -enum pnfs_block_extent_state { - PNFS_BLOCK_READWRITE_DATA = 0, - PNFS_BLOCK_READ_DATA = 1, - PNFS_BLOCK_INVALID_DATA = 2, - PNFS_BLOCK_NONE_DATA = 3, -}; - struct pnfs_block_extent { struct nfsd4_deviceid vol_id; u64 foff; @@ -21,14 +14,6 @@ struct pnfs_block_extent { u64 soff; enum pnfs_block_extent_state es; }; -#define NFS4_BLOCK_EXTENT_SIZE 44 - -enum pnfs_block_volume_type { - PNFS_BLOCK_VOLUME_SIMPLE = 0, - PNFS_BLOCK_VOLUME_SLICE = 1, - PNFS_BLOCK_VOLUME_CONCAT = 2, - PNFS_BLOCK_VOLUME_STRIPE = 3, -}; /* * Random upper cap for the uuid length to avoid unbounded allocation. diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index b8e72aad919c..00121f298269 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h @@ -547,6 +547,24 @@ enum pnfs_notify_deviceid_type4 { NOTIFY_DEVICEID4_DELETE = 1 << 2, }; +enum pnfs_block_volume_type { + PNFS_BLOCK_VOLUME_SIMPLE = 0, + PNFS_BLOCK_VOLUME_SLICE = 1, + PNFS_BLOCK_VOLUME_CONCAT = 2, + PNFS_BLOCK_VOLUME_STRIPE = 3, +}; + +enum pnfs_block_extent_state { + PNFS_BLOCK_READWRITE_DATA = 0, + PNFS_BLOCK_READ_DATA = 1, + PNFS_BLOCK_INVALID_DATA = 2, + PNFS_BLOCK_NONE_DATA = 3, +}; + +/* on the wire size of a block layout extent */ +#define PNFS_BLOCK_EXTENT_SIZE \ + (7 * sizeof(__be32) + NFS4_DEVICEID4_SIZE) + #define NFL4_UFLG_MASK 0x0000003F #define NFL4_UFLG_DENSE 0x00000001 #define NFL4_UFLG_COMMIT_THRU_MDS 0x00000002 -- cgit v1.2.3