From a60cc5c2eeaad7ea5ea0c4a74cc4af5e2dc3f6c2 Mon Sep 17 00:00:00 2001
From: Ruediger Meier <ruediger.meier@ga-group.nl>
Date: Tue, 4 Apr 2017 16:29:58 +0200
Subject: [PATCH] 
 util-linux-losetup-Add-support-for-setting-logical-blocksize.patch

Signed-off-by: Ruediger Meier <ruediger.meier@ga-group.nl>
---
 include/loopdev.h   |  5 ++++-
 lib/loopdev.c       | 20 ++++++++++++++++++++
 sys-utils/losetup.c | 19 +++++++++++++++----
 3 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/include/loopdev.h b/include/loopdev.h
index 953d2db..7c783bf 100644
--- a/include/loopdev.h
+++ b/include/loopdev.h
@@ -41,6 +41,7 @@ enum {
 	LO_FLAGS_AUTOCLEAR  = 4,	/* kernel >= 2.6.25 */
 	LO_FLAGS_PARTSCAN   = 8,	/* kernel >= 3.2 */
 	LO_FLAGS_DIRECT_IO  = 16,	/* kernel >= 4.2 */
+	LO_FLAGS_BLOCKSIZE  = 32,       /* Tentative */
 };
 
 #define LO_NAME_SIZE	64
@@ -120,7 +121,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)
 };
 
 /*
@@ -173,6 +175,7 @@ int loopcxt_set_offset(struct loopdev_cxt *lc, uint64_t offset);
 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);
diff --git a/lib/loopdev.c b/lib/loopdev.c
index fd4f166..b85e2ce 100644
--- a/lib/loopdev.c
+++ b/lib/loopdev.c
@@ -1115,6 +1115,26 @@ int loopcxt_set_backing_file(struct loopdev_cxt *lc, const char *filename)
 }
 
 /*
+ * @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(CXT, ul_debugobj(lc, "set blocksize=%llu", (long long unsigned int)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
diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c
index 2218d3b..d8f1bfa 100644
--- a/sys-utils/losetup.c
+++ b/sys-utils/losetup.c
@@ -399,6 +399,7 @@ static void usage(FILE *out)
 	fputs(USAGE_SEPARATOR, 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(_("     --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(_("     --direct-io[=<on|off>]    open backing file with O_DIRECT\n"), out);
@@ -448,7 +449,8 @@ static void warn_size(const char *filename, uint64_t size)
 
 static int create_loop(struct loopdev_cxt *lc,
 		       int nooverlap, int lo_flags, int flags,
-		       const char *file, uint64_t offset, uint64_t sizelimit)
+		       const char *file, uint64_t offset, uint64_t sizelimit,
+		       uint64_t blocksize)
 {
 	int hasdev = loopcxt_has_device(lc);
 	int rc = 0;
@@ -534,6 +536,8 @@ static int create_loop(struct loopdev_cxt *lc,
 			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 ((rc = loopcxt_set_backing_file(lc, file))) {
@@ -562,7 +566,7 @@ int main(int argc, char **argv)
 	struct loopdev_cxt lc;
 	int act = 0, flags = 0, no_overlap = 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;
@@ -572,7 +576,8 @@ int main(int argc, char **argv)
 		OPT_SIZELIMIT = CHAR_MAX + 1,
 		OPT_SHOW,
 		OPT_RAW,
-		OPT_DIO
+		OPT_DIO,
+		OPT_BLOCKSIZE,
 	};
 	static const struct option longopts[] = {
 		{ "all",          no_argument,       NULL, 'a'           },
@@ -585,6 +590,7 @@ int main(int argc, char **argv)
 		{ "associated",   required_argument, NULL, 'j'           },
 		{ "json",         no_argument,       NULL, 'J'           },
 		{ "list",         no_argument,       NULL, 'l'           },
+		{ "logical-blocksize", required_argument, NULL, OPT_BLOCKSIZE },
 		{ "noheadings",   no_argument,       NULL, 'n'           },
 		{ "offset",       required_argument, NULL, 'o'           },
 		{ "output",       required_argument, NULL, 'O'           },
@@ -658,6 +664,10 @@ int main(int argc, char **argv)
 			act = A_SHOW;
 			file = optarg;
 			break;
+		case OPT_BLOCKSIZE:
+			blocksize = strtosize_or_err(optarg, _("failed to parse logical block size"));
+			flags |= LOOPDEV_FL_BLOCKSIZE;
+			break;
 		case 'l':
 			list = 1;
 			break;
@@ -790,7 +800,8 @@ int main(int argc, char **argv)
 
 	switch (act) {
 	case A_CREATE:
-		res = create_loop(&lc, no_overlap, lo_flags, flags, file, offset, sizelimit);
+		res = create_loop(&lc, no_overlap, lo_flags, flags, file, offset,
+				  sizelimit, blocksize);
 		if (res == 0) {
 			if (showdev)
 				printf("%s\n", loopcxt_get_device(&lc));
-- 
1.8.5.6