mount: loop device race condition

Fix race in mount -o loop

Retry acquiring a loop device if the setup failed with EBUSY.

Signed-Off-By: Matthias Koenig <mkoenig@suse.de>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Matthias Koenig 2007-06-20 15:17:45 +02:00 committed by Karel Zak
parent 653872612c
commit 95ba33f7a4
2 changed files with 46 additions and 13 deletions

View File

@ -341,8 +341,16 @@ set_loop(const char *device, const char *file, unsigned long long offset,
}
if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
perror("ioctl: LOOP_SET_FD");
return 1;
close(fd);
close(ffd);
if (errno == EBUSY) {
if (verbose)
printf(_("ioctl LOOP_SET_FD failed: %s\n"), strerror(errno));
return 2;
} else {
perror("ioctl: LOOP_SET_FD");
return 1;
}
}
close (ffd);

View File

@ -846,20 +846,45 @@ loop_check(const char **spec, const char **type, int *flags,
printf(_("mount: skipping the setup of a loop device\n"));
} else {
int loopro = (*flags & MS_RDONLY);
int res;
if (!*loopdev || !**loopdev)
*loopdev = find_unused_loop_device();
if (!*loopdev)
return EX_SYSERR; /* no more loop devices */
if (verbose)
printf(_("mount: going to use the loop device %s\n"), *loopdev);
offset = opt_offset ? strtoull(opt_offset, NULL, 0) : 0;
if (set_loop(*loopdev, *loopfile, offset,
opt_encryption, pfd, &loopro)) {
do {
if (!*loopdev || !**loopdev)
*loopdev = find_unused_loop_device();
if (!*loopdev)
return EX_SYSERR; /* no more loop devices */
if (verbose)
printf(_("mount: failed setting up loop device\n"));
return EX_FAIL;
}
printf(_("mount: going to use the loop device %s\n"), *loopdev);
if ((res = set_loop(*loopdev, *loopfile, offset,
opt_encryption, pfd, &loopro))) {
if (res == 2) {
/* loop dev has been grabbed by some other process,
try again, if not given explicitly */
if (!opt_loopdev) {
if (verbose)
printf(_("mount: stolen loop=%s ...trying again\n"), *loopdev);
my_free(*loopdev);
*loopdev = NULL;
continue;
}
error(_("mount: stolen loop=%s"), *loopdev);
return EX_FAIL;
} else {
if (verbose)
printf(_("mount: failed setting up loop device\n"));
if (!opt_loopdev) {
my_free(*loopdev);
*loopdev = NULL;
}
return EX_FAIL;
}
}
} while (!*loopdev);
if (verbose > 1)
printf(_("mount: setup loop device successfully\n"));
*spec = *loopdev;