Modified on 2016-08-24 by sbrabec to use -b instead of -L.
-L is now used by the upstream with a different meaning.

From: Hannes Reinecke <hare@suse.de>
Date: Wed, 10 Jun 2015 16:42:22 +0200
Subject: losetup: Add support for setting logical blocksize
References: bsc#931634, FATE#319010

Add a new option '-b/--logical-blocksize' for setting the logical
blocksize on a loop device.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 include/loopdev.h   |  5 ++++-
 lib/loopdev.c       | 20 ++++++++++++++++++++
 sys-utils/losetup.c | 11 +++++++++--
 3 files changed, 33 insertions(+), 3 deletions(-)

Index: util-linux-2.25/include/loopdev.h
===================================================================
--- util-linux-2.25.orig/include/loopdev.h
+++ util-linux-2.25/include/loopdev.h
@@ -39,6 +39,7 @@ enum {
 	LO_FLAGS_USE_AOPS   = 2,
 	LO_FLAGS_AUTOCLEAR  = 4,	/* kernel >= 2.6.25 */
 	LO_FLAGS_PARTSCAN   = 8,	/* kernel >= 3.2 */
+	LO_FLAGS_BLOCKSIZE  = 16,	/* Tentative */
 };
 
 #define LO_NAME_SIZE	64
@@ -119,7 +120,8 @@ enum {
 	LOOPDEV_FL_NOIOCTL	= (1 << 6),
 	LOOPDEV_FL_DEVSUBDIR	= (1 << 7),
 	LOOPDEV_FL_CONTROL	= (1 << 8),	/* system with /dev/loop-control */
-	LOOPDEV_FL_SIZELIMIT	= (1 << 9)
+	LOOPDEV_FL_SIZELIMIT	= (1 << 9),
+	LOOPDEV_FL_BLOCKSIZE	= (1 << 10)
 };
 
 /*
@@ -171,6 +173,7 @@ int loopcxt_set_offset(struct loopdev_cx
 int loopcxt_set_sizelimit(struct loopdev_cxt *lc, uint64_t sizelimit);
 int loopcxt_set_flags(struct loopdev_cxt *lc, uint32_t flags);
 int loopcxt_set_backing_file(struct loopdev_cxt *lc, const char *filename);
+int loopcxt_set_blocksize(struct loopdev_cxt *lc, uint64_t blocksize);
 
 extern char *loopcxt_get_backing_file(struct loopdev_cxt *lc);
 extern int loopcxt_get_backing_devno(struct loopdev_cxt *lc, dev_t *devno);
Index: util-linux-2.25/lib/loopdev.c
===================================================================
--- util-linux-2.25.orig/lib/loopdev.c
+++ util-linux-2.25/lib/loopdev.c
@@ -1094,6 +1094,26 @@ int loopcxt_set_backing_file(struct loop
 }
 
 /*
+ * @lc: context
+ * @blocksize: logical blocksize for the device
+ *
+ * The setting is removed by loopcxt_set_device() loopcxt_next()!
+ *
+ * Returns: 0 on success, <0 on error.
+ */
+int loopcxt_set_blocksize(struct loopdev_cxt *lc, uint64_t blocksize)
+{
+	if (!lc)
+		return -EINVAL;
+
+	lc->info.lo_init[0] = blocksize;
+	lc->info.lo_flags |= LO_FLAGS_BLOCKSIZE;
+
+	DBG(lc, loopdev_debug("set blocksize=%llu", lc->info.lo_init[0]));
+	return 0;
+}
+
+/*
  * In kernels prior to v3.9, if the offset or sizelimit options
  * are used, the block device's size won't be synced automatically.
  * blockdev --getsize64 and filesystems will use the backing
Index: util-linux-2.25/sys-utils/losetup.c
===================================================================
--- util-linux-2.25.orig/sys-utils/losetup.c
+++ util-linux-2.25/sys-utils/losetup.c
@@ -380,6 +380,7 @@ static void usage(FILE *out)
 
 	fputs(_(" -o, --offset <num>            start at offset <num> into file\n"), out);
 	fputs(_("     --sizelimit <num>         device is limited to <num> bytes of the file\n"), out);
+	fputs(_(" -L, --logical-blocksize <size> set the logical block size to <size>\n"), out);
 	fputs(_(" -P, --partscan                create a partitioned loop device\n"), out);
 	fputs(_(" -r, --read-only               set up a read-only loop device\n"), out);
 	fputs(_("     --show                    print device name after setup (with -f)\n"), out);
@@ -430,7 +431,7 @@ int main(int argc, char **argv)
 	struct loopdev_cxt lc;
 	int act = 0, flags = 0, c;
 	char *file = NULL;
-	uint64_t offset = 0, sizelimit = 0;
+	uint64_t offset = 0, sizelimit = 0, blocksize = 0;
 	int res = 0, showdev = 0, lo_flags = 0;
 	char *outarg = NULL;
 	int list = 0;
@@ -449,6 +450,7 @@ int main(int argc, char **argv)
 		{ "help", 0, 0, 'h' },
 		{ "associated", 1, 0, 'j' },
 		{ "list", 0, 0, 'l' },
+		{ "logical-blocksize", 1, 0, 'L' },
 		{ "noheadings", 0, 0, 'n' },
 		{ "offset", 1, 0, 'o' },
 		{ "output", 1, 0, 'O' },
@@ -478,7 +480,7 @@ int main(int argc, char **argv)
 	if (loopcxt_init(&lc, 0))
 		err(EXIT_FAILURE, _("failed to initialize loopcxt"));
 
-	while ((c = getopt_long(argc, argv, "ac:d:Dfhj:lno:O:PrvV",
+	while ((c = getopt_long(argc, argv, "ac:d:Dfhj:L:lno:O:PrvV",
 				longopts, NULL)) != -1) {
 
 		err_exclusive_options(c, longopts, excl, excl_st);
@@ -517,6 +519,10 @@ int main(int argc, char **argv)
 			act = A_SHOW;
 			file = optarg;
 			break;
+		case 'L':
+			blocksize = strtosize_or_err(optarg, _("failed to parse logical block size"));
+			flags |= LOOPDEV_FL_BLOCKSIZE;
+			break;
 		case 'l':
 			list = 1;
 			break;
@@ -649,6 +655,8 @@ int main(int argc, char **argv)
 				loopcxt_set_offset(&lc, offset);
 			if (flags & LOOPDEV_FL_SIZELIMIT)
 				loopcxt_set_sizelimit(&lc, sizelimit);
+			if (flags & LOOPDEV_FL_BLOCKSIZE)
+				loopcxt_set_blocksize(&lc, blocksize);
 			if (lo_flags)
 				loopcxt_set_flags(&lc, lo_flags);
 			if ((res = loopcxt_set_backing_file(&lc, file))) {
