summaryrefslogtreecommitdiffstats
path: root/src/shared/loop-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/loop-util.c')
-rw-r--r--src/shared/loop-util.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c
index 2da101b748..49afa4dac6 100644
--- a/src/shared/loop-util.c
+++ b/src/shared/loop-util.c
@@ -442,11 +442,16 @@ static int loop_device_make_internal(
_cleanup_close_ int copy = -1;
uint64_t diskseq = 0;
- /* If this is already a block device, store a copy of the fd as it is */
-
- copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+ /* If this is already a block device and we are supposed to cover the whole of it
+ * then store an fd to the original open device node — and do not actually create an
+ * unnecessary loopback device for it. Note that we reopen the inode here, instead of
+ * keeping just a dup() clone of it around, since we want to ensure that the O_DIRECT
+ * flag of the handle we keep is off, we have our own file index, and have the right
+ * read/write mode in effect. */
+
+ copy = fd_reopen(fd, open_flags|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
if (copy < 0)
- return -errno;
+ return copy;
r = loop_get_diskseq(copy, &diskseq);
if (r < 0 && r != -EOPNOTSUPP)