]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
losetup: directly set dio instead of afterwards
authorAlex Xu (Hello71) <alex_y_xu@yahoo.ca>
Thu, 9 Sep 2021 13:55:03 +0000 (09:55 -0400)
committerAlex Xu (Hello71) <alex_y_xu@yahoo.ca>
Thu, 9 Sep 2021 13:55:03 +0000 (09:55 -0400)
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
sys-utils/losetup.c

index d9ea1d4a22ef5488921f4f5fcde1f6c64a161fd6..679c8d7bcda1e49d4564aab03bf007c1644ed327 100644 (file)
@@ -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"));
index 56de4ccba1dc14a09de7e0befc9c23c67c7ce159..c400cbf12863a2c6035da31db30d15124b57bf2a 100644 (file)
@@ -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"),