libmount: avoid duplicate loopdevs
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
ce43340461
commit
8b470b20d7
|
@ -1225,7 +1225,7 @@ int loopdev_is_used(const char *device, const char *filename,
|
|||
struct stat st;
|
||||
int rc = 0;
|
||||
|
||||
if (!device)
|
||||
if (!device || !filename)
|
||||
return 0;
|
||||
|
||||
loopcxt_init(&lc, 0);
|
||||
|
@ -1243,6 +1243,9 @@ int loopdev_delete(const char *device)
|
|||
struct loopdev_cxt lc;
|
||||
int rc;
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
loopcxt_init(&lc, 0);
|
||||
rc = loopcxt_set_device(&lc, device);
|
||||
if (!rc)
|
||||
|
|
|
@ -69,6 +69,68 @@ int mnt_context_is_loopdev(struct libmnt_context *cxt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check, if there already exists a mounted loop device on the mountpoint node
|
||||
* with the same parameters.
|
||||
*/
|
||||
static int is_mounted_same_loopfile(struct libmnt_context *cxt,
|
||||
const char *target,
|
||||
const char *backing_file,
|
||||
uint64_t offset)
|
||||
{
|
||||
struct libmnt_table *tb;
|
||||
struct libmnt_iter itr;
|
||||
struct libmnt_fs *fs;
|
||||
struct libmnt_cache *cache;
|
||||
|
||||
assert(cxt);
|
||||
assert(cxt->fs);
|
||||
assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
|
||||
|
||||
if (!target || !backing_file || mnt_context_get_mtab(cxt, &tb))
|
||||
return 0;
|
||||
|
||||
DBG(CXT, mnt_debug_h(cxt, "checking if %s mounted on %d",
|
||||
backing_file, target));
|
||||
|
||||
cache = mnt_context_get_cache(cxt);
|
||||
mnt_reset_iter(&itr, MNT_ITER_BACKWARD);
|
||||
|
||||
/* Search for mountpoint node in mtab, procceed if any of these has the
|
||||
* loop option set or the device is a loop device
|
||||
*/
|
||||
while (mnt_table_next_fs(tb, &itr, &fs) == 0) {
|
||||
const char *src = mnt_fs_get_source(fs);
|
||||
const char *opts = mnt_fs_get_user_options(fs);
|
||||
char *val;
|
||||
size_t len;
|
||||
int res = 0;
|
||||
|
||||
if (!src || !mnt_fs_match_target(fs, target, cache))
|
||||
continue;
|
||||
|
||||
if (strncmp(src, "/dev/loop", 9) == 0) {
|
||||
res = loopdev_is_used((char *) src, backing_file,
|
||||
offset, LOOPDEV_FL_OFFSET);
|
||||
|
||||
} else if (opts && (cxt->user_mountflags & MNT_MS_LOOP) &&
|
||||
mnt_optstr_get_option(opts, "loop", &val, &len) == 0 && val) {
|
||||
|
||||
val = strndup(val, len);
|
||||
res = loopdev_is_used((char *) val, backing_file,
|
||||
offset, LOOPDEV_FL_OFFSET);
|
||||
free(val);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
DBG(CXT, mnt_debug_h(cxt, "%s already mounted", backing_file));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mnt_context_setup_loopdev(struct libmnt_context *cxt)
|
||||
{
|
||||
const char *backing_file, *optstr, *loopdev = NULL;
|
||||
|
@ -147,6 +209,11 @@ int mnt_context_setup_loopdev(struct libmnt_context *cxt)
|
|||
}
|
||||
}
|
||||
|
||||
if (rc == 0 && is_mounted_same_loopfile(cxt,
|
||||
mnt_context_get_target(cxt),
|
||||
backing_file, offset))
|
||||
rc = -EBUSY;
|
||||
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
|
|
|
@ -286,11 +286,15 @@ try_readonly:
|
|||
|
||||
if (!mnt_context_syscall_called(cxt)) {
|
||||
/*
|
||||
* libmount errors
|
||||
* libmount errors (extra library checks)
|
||||
*/
|
||||
if (rc == -EPERM) {
|
||||
switch (rc) {
|
||||
case -EPERM:
|
||||
warnx(_("only root can mount %s on %s"), src, tgt);
|
||||
return EX_USAGE;
|
||||
case -EBUSY:
|
||||
warnx(_("%s is already mounted"), src);
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
if (src == NULL || tgt == NULL) {
|
||||
|
|
Loading…
Reference in New Issue