libmount: fix "already mounted" detection on systems with mtab

For systems with regular mtab the fs->root should be ignored in
"already mounted" heuristic.

Reported-by: Matt Burgess <matthew@linuxfromscratch.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2012-03-09 13:11:24 +01:00
parent 5791238768
commit 7293e97a42
2 changed files with 53 additions and 17 deletions

View File

@ -166,6 +166,10 @@ _INLINE_ void list_splice(struct list_head *list, struct list_head *head)
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
#define list_first_entry(head, type, member) \
((head) && (head)->next != (head) ? list_entry((head)->next, type, member) : NULL)
/**
* list_for_each - iterate over elements in a list
* @pos: the &struct list_head to use as a loop counter.

View File

@ -704,16 +704,18 @@ struct libmnt_fs *mnt_table_find_pair(struct libmnt_table *tb, const char *sourc
}
/*
* @tb: /proc/self/mountinfo
* @fs: filesystem
* @mountflags: MS_BIND or 0
* @fsroot: fs-root that will be probably used in the mountinfo file
* tb: /proc/self/mountinfo
* fs: filesystem
* mountflags: MS_BIND or 0
* fsroot: fs-root that will be probably used in the mountinfo file
* for @fs after mount(2)
*
* For btrfs subvolumes this function returns NULL, but @fsroot properly set.
*
* Returns: entry from @tb that will be used as a source for @fs if the @fs is
* bindmount.
*
* Don't export to library API!
*/
struct libmnt_fs *mnt_table_get_fs_root(struct libmnt_table *tb,
struct libmnt_fs *fs,
@ -816,6 +818,20 @@ err:
return NULL;
}
static int is_mountinfo(struct libmnt_table *tb)
{
struct libmnt_fs *fs;
if (!tb)
return 0;
fs = list_first_entry(&tb->ents, struct libmnt_fs, ents);
if (fs && mnt_fs_is_kernel(fs) && mnt_fs_get_root(fs))
return 1;
return 0;
}
/**
* mnt_table_is_mounted:
* @tb: /proc/self/mountinfo file
@ -831,10 +847,9 @@ err:
int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
{
char *root = NULL;
struct libmnt_fs *src_fs;
const char *src;
const char *src = NULL;
char *xsrc = NULL, *tgt;
int flags = 0, rc = 0;
int rc = 0;
assert(tb);
assert(fstab_fs);
@ -842,12 +857,21 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
if (mnt_fs_is_swaparea(fstab_fs))
return 0;
if (mnt_fs_get_option(fstab_fs, "bind", NULL, NULL) == 0)
flags = MS_BIND;
if (is_mountinfo(tb)) {
/* @tb is mountinfo, so we can try to use fs-roots */
struct libmnt_fs *fs;
int flags = 0;
src_fs = mnt_table_get_fs_root(tb, fstab_fs, flags, &root);
if (src_fs)
src = mnt_fs_get_srcpath(src_fs);
if (mnt_fs_get_option(fstab_fs, "bind", NULL, NULL) == 0)
flags = MS_BIND;
fs = mnt_table_get_fs_root(tb, fstab_fs, flags, &root);
if (fs)
src = mnt_fs_get_srcpath(fs);
}
if (src)
src = xsrc = mnt_resolve_spec(src, tb->cache);
else if (mnt_fs_is_pseudofs(fstab_fs))
src = mnt_fs_get_source(fstab_fs);
else
@ -856,18 +880,26 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
tgt = mnt_resolve_path(mnt_fs_get_target(fstab_fs), tb->cache);
if (tgt && src && root) {
if (tgt && src) {
struct libmnt_iter itr;
struct libmnt_fs *fs;
mnt_reset_iter(&itr, MNT_ITER_FORWARD);
while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
const char *r = mnt_fs_get_root(fs);
if (r && strcmp(r, root) == 0
&& mnt_fs_streq_srcpath(fs, src)
&& mnt_fs_streq_target(fs, tgt))
if (root) {
/* mountinfo: compare root, source and target */
const char *r = mnt_fs_get_root(fs);
if (r && strcmp(r, root) == 0 &&
mnt_fs_streq_srcpath(fs, src) &&
mnt_fs_streq_target(fs, tgt))
break;
}
/* mtab: compare source and target */
else if (mnt_fs_streq_srcpath(fs, src) &&
mnt_fs_streq_target(fs, tgt))
break;
}
if (fs)