[PATCH 2/2] loop: Add module parameter 'lbs' to set logical blocksize

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The loop device already knows about the physical blocksize
(= blocksize of the underlying file). This patch adds a
module option 'lbs' to specify the blocksize directly
or '0' for using the blocksize from the underlying file.

Signed-off-by: Hannes Reinecke <hare@xxxxxxx>
---
 drivers/block/loop.c | 55 +++++++++++++++++++++++++++++++++++++++-------------
 drivers/block/loop.h |  1 +
 2 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 6965e5a..6019373 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -84,6 +84,7 @@ static DEFINE_MUTEX(loop_index_mutex);
 
 static int max_part;
 static int part_shift;
+static int lbs = 512;
 
 /*
  * Transfer functions
@@ -160,9 +161,14 @@ static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
 	&xor_funcs
 };
 
-static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
+/*
+ * Returns the number of sectors
+ */
+static loff_t get_size(loff_t offset, loff_t sizelimit, int blocksize,
+		       struct file *file)
 {
 	loff_t loopsize;
+	int lo_bits = blksize_bits(blocksize);
 
 	/* Compute loopsize in bytes */
 	loopsize = i_size_read(file->f_mapping->host);
@@ -176,20 +182,22 @@ static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
 		loopsize = sizelimit;
 	/*
 	 * Unfortunately, if we want to do I/O on the device,
-	 * the number of 512-byte sectors has to fit into a sector_t.
+	 * the number of sectors has to fit into a sector_t.
 	 */
-	return loopsize >> 9;
+	return loopsize >> lo_bits;
 }
 
 static loff_t get_loop_size(struct loop_device *lo, struct file *file)
 {
-	return get_size(lo->lo_offset, lo->lo_sizelimit, file);
+	return get_size(lo->lo_offset, lo->lo_sizelimit,
+			lo->lo_logical_blocksize, file);
 }
 
 static int
 figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
 {
-	loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
+	loff_t size = get_size(offset, sizelimit, lo->lo_logical_blocksize,
+			       lo->lo_backing_file);
 	sector_t x = (sector_t)size;
 	struct block_device *bdev = lo->lo_device;
 
@@ -200,8 +208,9 @@ figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
 	if (lo->lo_sizelimit != sizelimit)
 		lo->lo_sizelimit = sizelimit;
 	blk_queue_physical_block_size(lo->lo_queue, lo->lo_blocksize);
+	blk_queue_logical_block_size(lo->lo_queue, lo->lo_logical_blocksize);
 	set_capacity(lo->lo_disk, x);
-	bd_set_size(bdev, (loff_t)get_capacity(bdev->bd_disk) << 9);
+	bd_set_size(bdev, size << blksize_bits(lo->lo_logical_blocksize));
 	/* let user-space know about the new size */
 	kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
 	return 0;
@@ -272,8 +281,9 @@ static int do_lo_send_direct_write(struct loop_device *lo,
 static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
 		loff_t pos, struct page *page)
 {
+	sector_t sec = (pos >> blksize_bits(lo->lo_logical_blocksize));
 	int ret = lo_do_transfer(lo, WRITE, page, 0, bvec->bv_page,
-			bvec->bv_offset, bvec->bv_len, pos >> 9);
+			bvec->bv_offset, bvec->bv_len, sec);
 	if (likely(!ret))
 		return __do_lo_send_write(lo->lo_backing_file,
 				page_address(page), bvec->bv_len,
@@ -337,10 +347,11 @@ lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 	struct loop_device *lo = p->lo;
 	struct page *page = buf->page;
 	sector_t IV;
+	int lo_bits = blksize_bits(lo->lo_logical_blocksize);
 	int size;
 
-	IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
-							(buf->offset >> 9);
+	IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - lo_bits)) +
+		(buf->offset >> lo_bits);
 	size = sd->len;
 	if (size > p->bsize)
 		size = p->bsize;
@@ -377,7 +388,7 @@ do_lo_receive(struct loop_device *lo,
 	cookie.lo = lo;
 	cookie.page = bvec->bv_page;
 	cookie.offset = bvec->bv_offset;
-	cookie.bsize = lo->lo_blocksize;
+	cookie.bsize = lo->lo_logical_blocksize;
 
 	sd.len = 0;
 	sd.total_len = bvec->bv_len;
@@ -415,9 +426,10 @@ lo_receive(struct loop_device *lo, struct bio *bio, loff_t pos)
 static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
 {
 	loff_t pos;
+	int lo_bits = blksize_bits(lo->lo_logical_blocksize);
 	int ret;
 
-	pos = ((loff_t) bio->bi_iter.bi_sector << 9) + lo->lo_offset;
+	pos = ((loff_t) bio->bi_iter.bi_sector << lo_bits) + lo->lo_offset;
 
 	if (bio_rw(bio) == WRITE) {
 		struct file *file = lo->lo_backing_file;
@@ -797,6 +809,7 @@ static void loop_config_discard(struct loop_device *lo)
 	struct file *file = lo->lo_backing_file;
 	struct inode *inode = file->f_mapping->host;
 	struct request_queue *q = lo->lo_queue;
+	int lo_bits = blksize_bits(lo->lo_logical_blocksize);
 
 	/*
 	 * We use punch hole to reclaim the free space used by the
@@ -816,7 +829,7 @@ static void loop_config_discard(struct loop_device *lo)
 
 	q->limits.discard_granularity = inode->i_sb->s_blocksize;
 	q->limits.discard_alignment = 0;
-	q->limits.max_discard_sectors = UINT_MAX >> 9;
+	q->limits.max_discard_sectors = UINT_MAX >> lo_bits;
 	q->limits.discard_zeroes_data = 1;
 	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
 }
@@ -884,6 +897,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 	set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);
 
 	lo->lo_blocksize = lo_blocksize;
+	lo->lo_logical_blocksize = lbs ? lbs : lo_blocksize;
 	lo->lo_device = bdev;
 	lo->lo_flags = lo_flags;
 	lo->lo_backing_file = file;
@@ -900,8 +914,9 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		blk_queue_flush(lo->lo_queue, REQ_FLUSH);
 
 	blk_queue_physical_block_size(lo->lo_queue, lo->lo_blocksize);
+	blk_queue_logical_block_size(lo->lo_queue, lo->lo_logical_blocksize);
 	set_capacity(lo->lo_disk, size);
-	bd_set_size(bdev, size << 9);
+	bd_set_size(bdev, size << blksize_bits(lo->lo_logical_blocksize));
 	loop_sysfs_init(lo);
 	/* let user-space know about the new size */
 	kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
@@ -1562,6 +1577,8 @@ module_param(max_loop, int, S_IRUGO);
 MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
 module_param(max_part, int, S_IRUGO);
 MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
+module_param(lbs, int, S_IRUGO);
+MODULE_PARM_DESC(lbs, "logical blocksize (0: native, default: 512)");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
 
@@ -1856,6 +1873,18 @@ static int __init loop_init(void)
 		goto misc_out;
 	}
 
+	switch (lbs) {
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+	case 0:
+		break;
+	default:
+		err = -EINVAL;
+		goto misc_out;
+	}
+
 	/*
 	 * If max_loop is specified, create that many devices upfront.
 	 * This also becomes a hard limit. If max_loop is not specified,
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
index 90df5d6..fefe3dc 100644
--- a/drivers/block/loop.h
+++ b/drivers/block/loop.h
@@ -47,6 +47,7 @@ struct loop_device {
 	struct file *	lo_backing_file;
 	struct block_device *lo_device;
 	unsigned	lo_blocksize;
+	unsigned	lo_logical_blocksize;
 	void		*key_data; 
 
 	gfp_t		old_gfp_mask;
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux