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] 85560117d0
This commit is contained in:
parent
78001b7af3
commit
d53346ed08
|
@ -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"));
|
||||
|
|
|
@ -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"),
|
||||
|
|
Loading…
Reference in New Issue