From cbdb5025a3127d20a1e18a14bbcb0cc17be84710 Mon Sep 17 00:00:00 2001 From: Manuel Bentele Date: Wed, 2 Dec 2020 07:07:44 +0100 Subject: Setup xloop device with XLOOP_CONFIGURE ioctl call This feature allows the userspace tool xlosetup to completely setup a loop device with a single ioctl call, removing the in-between state where the device can be partially configured, eg. the loop device has a backing file associated with it, but is reading from the wrong offset. Besides removing the intermediate state, another big benefit of this ioctl is that XLOOP_SET_STATUS can be slow. The main reason for this slowness is that XLOOP_SET_STATUS(64) calls blk_mq_freeze_queue() to freeze the associated queue. This requires waiting for RCU. --- src/utils/sys-utils/xlosetup.8 | 7 +++++++ src/utils/sys-utils/xlosetup.c | 10 +++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src/utils/sys-utils') diff --git a/src/utils/sys-utils/xlosetup.8 b/src/utils/sys-utils/xlosetup.8 index 4e063e6..c948899 100644 --- a/src/utils/sys-utils/xlosetup.8 +++ b/src/utils/sys-utils/xlosetup.8 @@ -68,6 +68,13 @@ It's possible to create more independent xloop devices for the same backing file. .B This setup may be dangerous, can cause data loss, corruption and overwrites. Use \fB\-\-nooverlap\fR with \fB\-\-find\fR during setup to avoid this problem. +.sp +The xloop device setup is not an atomic operation when used with \fB\-\-find\fP, and +.B xlosetup +does not protect this operation by any lock. The number of attempts is +internally restricted to a maximum of 64. It is recommended to use for example +.BR flock (1) +to avoid a collision in heavily parallel use cases. .SH OPTIONS The \fIsize\fR and \fIoffset\fR diff --git a/src/utils/sys-utils/xlosetup.c b/src/utils/sys-utils/xlosetup.c index 60fa0ba..cbc2e69 100644 --- a/src/utils/sys-utils/xlosetup.c +++ b/src/utils/sys-utils/xlosetup.c @@ -469,7 +469,7 @@ static int create_loop(struct loopdev_cxt *lc, uint64_t blocksize, uint32_t file_fmt_type) { int hasdev = loopcxt_has_device(lc); - int rc = 0; + int rc = 0, ntries = 0; /* xlosetup --find --noverlap file.img */ if (!hasdev && nooverlap) { @@ -501,7 +501,7 @@ static int create_loop(struct loopdev_cxt *lc, errx(EXIT_FAILURE, _("%s: overlapping encrypted xloop device exists"), file); } - lc->info.lo_flags &= ~LO_FLAGS_AUTOCLEAR; + lc->config.info.lo_flags &= ~LO_FLAGS_AUTOCLEAR; if (loopcxt_ioctl_status(lc)) { loopcxt_deinit(lc); errx(EXIT_FAILURE, _("%s: failed to re-use xloop device"), file); @@ -571,8 +571,12 @@ static int create_loop(struct loopdev_cxt *lc, rc = loopcxt_setup_device(lc); if (rc == 0) break; /* success */ - if (errno == EBUSY && !hasdev) + + if (errno == EBUSY && !hasdev && ntries < 64) { + xusleep(200000); + ntries++; continue; + } /* errors */ errpre = hasdev && loopcxt_get_fd(lc) < 0 ? -- cgit v1.2.3-55-g7522