diff options
author | Stanislav Brabec | 2017-09-26 16:14:51 +0200 |
---|---|---|
committer | Karel Zak | 2017-09-27 14:30:02 +0200 |
commit | a1a41597bfd55e709024bd91aaf024159362679c (patch) | |
tree | ee740d8df1db5485c5886ff3f753927707752f1a /sys-utils | |
parent | docs: add exec() exit codes to TODO (diff) | |
download | kernel-qcow2-util-linux-a1a41597bfd55e709024bd91aaf024159362679c.tar.gz kernel-qcow2-util-linux-a1a41597bfd55e709024bd91aaf024159362679c.tar.xz kernel-qcow2-util-linux-a1a41597bfd55e709024bd91aaf024159362679c.zip |
losetup: Add support for logical block size
Kernel since 4.14 supports setting of logical block size[1]. It allows to
create loop devices that report logical block size different from 512.
Add support for this feature to losetup.
References:
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/block/loop.c?id=89e4fdecb51cf5535867026274bc97de9480ade5
[kzak@redhat.com: - fix loopcxt_get_blocksize()
- remove lo_blocksize from loop_info64]
Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Omar Sandoval <osandov@fb.com>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils')
-rw-r--r-- | sys-utils/losetup.8 | 3 | ||||
-rw-r--r-- | sys-utils/losetup.c | 51 |
2 files changed, 41 insertions, 13 deletions
diff --git a/sys-utils/losetup.8 b/sys-utils/losetup.8 index 98a8e70d6..570704d72 100644 --- a/sys-utils/losetup.8 +++ b/sys-utils/losetup.8 @@ -116,6 +116,9 @@ The data start is moved \fIoffset\fP bytes into the specified file or device. .IP "\fB\-\-sizelimit \fIsize\fP" The data end is set to no more than \fIsize\fP bytes after the data start. .TP +.BR \-b , " \-\-logical-blocksize " \fIsize +Set the logical block size of the loop device in bytes (since Linux 4.14). +.TP .BR \-c , " \-\-set\-capacity " \fIloopdev Force the loop driver to reread the size of the file associated with the specified loop device. diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c index bbff98389..368a0b90a 100644 --- a/sys-utils/losetup.c +++ b/sys-utils/losetup.c @@ -36,6 +36,7 @@ enum { A_FIND_FREE, /* find first unused */ A_SET_CAPACITY, /* set device capacity */ A_SET_DIRECT_IO, /* set accessing backing file by direct io */ + A_SET_BLOCKSIZE, /* set logical block size of the loop device */ }; enum { @@ -50,6 +51,7 @@ enum { COL_RO, COL_SIZELIMIT, COL_DIO, + COL_BLOCKSIZE, }; /* basic output flags */ @@ -76,6 +78,7 @@ static struct colinfo infos[] = { [COL_SIZELIMIT] = { "SIZELIMIT", 5, SCOLS_FL_RIGHT, N_("size limit of the file in bytes")}, [COL_MAJMIN] = { "MAJ:MIN", 3, 0, N_("loop device major:minor number")}, [COL_DIO] = { "DIO", 1, SCOLS_FL_RIGHT, N_("access backing file with direct-io")}, + [COL_BLOCKSIZE] = { "BLOCKSIZE", 4, SCOLS_FL_RIGHT, N_("logical block size in bytes")}, }; static int columns[ARRAY_SIZE(infos) * 2] = {-1}; @@ -280,6 +283,10 @@ static int set_scols_data(struct loopdev_cxt *lc, struct libscols_line *ln) case COL_PARTSCAN: p = loopcxt_is_partscan(lc) ? "1" : "0"; break; + case COL_BLOCKSIZE: + if (loopcxt_get_blocksize(lc, &x) == 0) + xasprintf(&np, "%jd", x); + break; default: return -EINVAL; } @@ -404,6 +411,7 @@ static void __attribute__((__noreturn__)) usage(void) 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(_(" -b --logical-blocksize <num> set the logical block size to <num>\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); @@ -566,11 +574,11 @@ 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; - unsigned long use_dio = 0, set_dio = 0; + unsigned long use_dio = 0, set_dio = 0, set_blocksize = 0; enum { OPT_SIZELIMIT = CHAR_MAX + 1, @@ -589,6 +597,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, 'b' }, { "noheadings", no_argument, NULL, 'n' }, { "offset", required_argument, NULL, 'o' }, { "output", required_argument, NULL, 'O' }, @@ -620,7 +629,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:JlLno:O:PrvV", + while ((c = getopt_long(argc, argv, "ab:c:d:Dfhj:JlLno:O:PrvV", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); @@ -629,6 +638,10 @@ int main(int argc, char **argv) case 'a': act = A_SHOW; break; + case 'b': + set_blocksize = 1; + blocksize = strtosize_or_err(optarg, _("failed to parse logical block size")); + break; case 'c': act = A_SET_CAPACITY; if (!is_loopdev(optarg) || @@ -727,6 +740,7 @@ int main(int argc, char **argv) columns[ncolumns++] = COL_RO; columns[ncolumns++] = COL_BACK_FILE; columns[ncolumns++] = COL_DIO; + columns[ncolumns++] = COL_BLOCKSIZE; } if (act == A_FIND_FREE && optind < argc) { @@ -747,12 +761,14 @@ int main(int argc, char **argv) /* * losetup [--list] <device> * OR - * losetup --direct-io[=off] <device> + * losetup {--direct-io[=off]|--logical-blocksize=size}... <device> */ - if (!set_dio) + if (!(set_dio || set_blocksize)) act = A_SHOW_ONE; - else + if (set_dio) act = A_SET_DIRECT_IO; + if (set_blocksize) + act = A_SET_BLOCKSIZE; if (!is_loopdev(argv[optind]) || loopcxt_set_device(&lc, argv[optind])) err(EXIT_FAILURE, _("%s: failed to use device"), @@ -799,8 +815,8 @@ int main(int argc, char **argv) if (showdev) printf("%s\n", loopcxt_get_device(&lc)); warn_size(file, sizelimit); - if (set_dio) - goto lo_set_dio; + if (set_dio || set_blocksize) + goto lo_set_post; } break; case A_DELETE: @@ -853,11 +869,20 @@ int main(int argc, char **argv) loopcxt_get_device(&lc)); break; case A_SET_DIRECT_IO: - lo_set_dio: - res = loopcxt_set_dio(&lc, use_dio); - if (res) - warn(_("%s: set direct io failed"), - loopcxt_get_device(&lc)); + case A_SET_BLOCKSIZE: + lo_set_post: + if (set_dio) { + res = loopcxt_set_dio(&lc, use_dio); + if (res) + warn(_("%s: set direct io failed"), + loopcxt_get_device(&lc)); + } + if (set_blocksize) { + res = loopcxt_set_blocksize(&lc, blocksize); + if (res) + warn(_("%s: set logical block size failed"), + loopcxt_get_device(&lc)); + } break; default: warnx(_("bad usage")); |