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 /lib/loopdev.c | |
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 'lib/loopdev.c')
-rw-r--r-- | lib/loopdev.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/loopdev.c b/lib/loopdev.c index 8c653a361..66fa4f669 100644 --- a/lib/loopdev.c +++ b/lib/loopdev.c @@ -737,6 +737,38 @@ int loopcxt_get_offset(struct loopdev_cxt *lc, uint64_t *offset) /* * @lc: context + * @blocksize: returns logical blocksize for the given device + * + * Returns: <0 on error, 0 on success + */ +int loopcxt_get_blocksize(struct loopdev_cxt *lc, uint64_t *blocksize) +{ + struct sysfs_cxt *sysfs = loopcxt_get_sysfs(lc); + int rc = -EINVAL; + + if (sysfs) + rc = sysfs_read_u64(sysfs, "queue/logical_block_size", blocksize); + + /* Fallback based on BLKSSZGET ioctl */ + if (rc) { + int fd = loopcxt_get_fd(lc); + int sz = 0; + + if (fd < 0) + return -EINVAL; + rc = blkdev_get_sector_size(fd, &sz); + if (rc) + return rc; + + *blocksize = sz; + } + + DBG(CXT, ul_debugobj(lc, "get_blocksize [rc=%d]", rc)); + return rc; +} + +/* + * @lc: context * @sizelimit: returns size limit for the given device * * Returns: <0 on error, 0 on success @@ -1398,6 +1430,24 @@ int loopcxt_set_dio(struct loopdev_cxt *lc, unsigned long use_dio) return 0; } +int loopcxt_set_blocksize(struct loopdev_cxt *lc, unsigned long blocksize) +{ + int fd = loopcxt_get_fd(lc); + + if (fd < 0) + return -EINVAL; + + /* Kernels prior to v4.14 don't support this ioctl */ + if (ioctl(fd, LOOP_SET_BLOCK_SIZE, blocksize) < 0) { + int rc = -errno; + DBG(CXT, ul_debugobj(lc, "LOOP_SET_BLOCK_SIZE failed: %m")); + return rc; + } + + DBG(CXT, ul_debugobj(lc, "logical block size set")); + return 0; +} + int loopcxt_delete_device(struct loopdev_cxt *lc) { int fd = loopcxt_get_fd(lc); |