From d53346ed082db8717df7a76d2df9fd657d3e23e9 Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Thu, 9 Sep 2021 09:55:03 -0400 Subject: [PATCH] losetup: directly set dio instead of afterwards This avoids an extra syscall, and allows the kernel to automatically set block size [0], avoiding unnecessary failure with 4096-byte devices. This changes the observable behavior of losetup --direct-io in the case where DIO is not supported to fully fail, instead of creating a non-direct-io device. If the user explicitly specifies --direct-io, then they should get either a DIO loopdev or no loopdev, not a non-DIO loopdev and a misleading error. Additionally, loopcxt_setup_device now uses O_CLOEXEC in the read-only fallback. [0] https://github.com/torvalds/linux/commit/85560117d00f5d528e928918b8f61cadcefff98b --- lib/loopdev.c | 10 +++++++--- sys-utils/losetup.c | 5 ++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/loopdev.c b/lib/loopdev.c index d9ea1d4a22..679c8d7bcd 100644 --- a/lib/loopdev.c +++ b/lib/loopdev.c @@ -1290,7 +1290,8 @@ static int loopcxt_check_size(struct loopdev_cxt *lc, int file_fd) */ int loopcxt_setup_device(struct loopdev_cxt *lc) { - int file_fd, dev_fd, mode = O_RDWR, rc = -1, cnt = 0, err, again; + int file_fd, dev_fd, mode = O_RDWR, flags = O_CLOEXEC; + int rc = -1, cnt = 0, err, again; int errsv = 0; int fallback = 0; @@ -1305,9 +1306,12 @@ int loopcxt_setup_device(struct loopdev_cxt *lc) if (lc->config.info.lo_flags & LO_FLAGS_READ_ONLY) mode = O_RDONLY; - if ((file_fd = open(lc->filename, mode | O_CLOEXEC)) < 0) { + if (lc->config.info.lo_flags & LO_FLAGS_DIRECT_IO) + flags |= O_DIRECT; + + if ((file_fd = open(lc->filename, mode | flags)) < 0) { if (mode != O_RDONLY && (errno == EROFS || errno == EACCES)) - file_fd = open(lc->filename, mode = O_RDONLY); + file_fd = open(lc->filename, (mode = O_RDONLY) | flags); if (file_fd < 0) { DBG(SETUP, ul_debugobj(lc, "open backing file failed: %m")); diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c index 56de4ccba1..c400cbf128 100644 --- a/sys-utils/losetup.c +++ b/sys-utils/losetup.c @@ -728,6 +728,8 @@ int main(int argc, char **argv) use_dio = set_dio = 1; if (optarg) use_dio = parse_switch(optarg, _("argument error"), "on", "off", NULL); + if (use_dio) + lo_flags |= LO_FLAGS_DIRECT_IO; break; case 'v': break; @@ -847,8 +849,6 @@ int main(int argc, char **argv) if (showdev) printf("%s\n", loopcxt_get_device(&lc)); warn_size(file, sizelimit, offset, flags); - if (set_dio) - goto lo_set_dio; } break; case A_DELETE: @@ -901,7 +901,6 @@ int main(int argc, char **argv) loopcxt_get_device(&lc)); break; case A_SET_DIRECT_IO: -lo_set_dio: res = loopcxt_ioctl_dio(&lc, use_dio); if (res) warn(_("%s: set direct io failed"), -- 2.47.2