summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2012-08-24 18:13:06 +0200
committerKarel Zak2012-08-24 18:29:51 +0200
commit975e14bd4abaf5635ce0783f3ecddb87449cc05a (patch)
treea4add5810c4fd13171144eaad0f61b9ac98a58ff
parentbuild-sys: release++ (v2.22-rc2) (diff)
downloadkernel-qcow2-util-linux-975e14bd4abaf5635ce0783f3ecddb87449cc05a.tar.gz
kernel-qcow2-util-linux-975e14bd4abaf5635ce0783f3ecddb87449cc05a.tar.xz
kernel-qcow2-util-linux-975e14bd4abaf5635ce0783f3ecddb87449cc05a.zip
libmount: rewrite mnt_table_is_fs_mounted() to be less aggressive
The old implementation always canonicalizes target (mountpoint) path. It's better to postpone this operation until the path is really necessary (usually it's unnecessary), because readlink() on mountpoint may trigger automounts. Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--libmount/src/context.c2
-rw-r--r--libmount/src/tab.c74
2 files changed, 52 insertions, 24 deletions
diff --git a/libmount/src/context.c b/libmount/src/context.c
index bfc418cd8..d6f905039 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -1963,6 +1963,8 @@ int mnt_context_helper_setopt(struct libmnt_context *cxt, int c, char *arg)
* @fs: filesystem
* @mounted: returns 1 for mounted and 0 for non-mounted filesystems
*
+ * Please, read mnt_table_is_fs_mounted() description!
+ *
* Returns: 0 on success and negative number in case of error.
*/
int mnt_context_is_fs_mounted(struct libmnt_context *cxt,
diff --git a/libmount/src/tab.c b/libmount/src/tab.c
index 927e0f8da..1c159b56f 100644
--- a/libmount/src/tab.c
+++ b/libmount/src/tab.c
@@ -876,8 +876,18 @@ static int is_mountinfo(struct libmnt_table *tb)
* @tb: /proc/self/mountinfo file
* @fstab_fs: /etc/fstab entry
*
- * Checks if the @fstab_fs entry is already in the @tb table. The "swap"
- * is ignored.
+ * Checks if the @fstab_fs entry is already in the @tb table. The "swap" is
+ * ignored. This function explicitly compares source, target and root of the
+ * filesystems.
+ *
+ * Note that source and target are canonicalized only if a cache for @tb is
+ * defined (see mnt_table_set_cache()). The target canonicalization may
+ * triggers automount on autofs mountpoints!
+ *
+ * Don't use it if you want to know if a device is mounted, just use
+ * mnt_table_find_source() for the device.
+ *
+ * This function is designed mostly for "mount -a".
*
* TODO: check for loopdev (see mount/mount.c is_fstab_entry_mounted().
*
@@ -886,8 +896,8 @@ static int is_mountinfo(struct libmnt_table *tb)
int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
{
char *root = NULL;
- const char *src = NULL;
- char *xsrc = NULL, *tgt;
+ const char *src = NULL, *tgt = NULL;
+ char *xtgt = NULL;
int rc = 0;
assert(tb);
@@ -909,15 +919,13 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_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))
+ if (!src)
src = mnt_fs_get_source(fstab_fs);
- else
- src = xsrc = mnt_resolve_spec(mnt_fs_get_source(fstab_fs),
- tb->cache);
- tgt = mnt_resolve_path(mnt_fs_get_target(fstab_fs), tb->cache);
+ if (src && tb->cache && !mnt_fs_is_pseudofs(fstab_fs))
+ src = mnt_resolve_spec(src, tb->cache);
+
+ tgt = mnt_fs_get_target(fstab_fs);
if (tgt && src) {
struct libmnt_iter itr;
@@ -925,31 +933,36 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
mnt_reset_iter(&itr, MNT_ITER_FORWARD);
- while(mnt_table_next_fs(tb, &itr, &fs) == 0) {
+ while (mnt_table_next_fs(tb, &itr, &fs) == 0) {
+
+ if (!mnt_fs_streq_srcpath(fs, src))
+ continue;
if (root) {
- /* mountinfo: compare root, source and target */
const char *r = mnt_fs_get_root(fs);
+ if (!r || strcmp(r, root) != 0)
+ continue;
+ }
- if (r && strcmp(r, root) == 0 &&
- mnt_fs_streq_srcpath(fs, src) &&
- mnt_fs_streq_target(fs, tgt))
+ /*
+ * Compare target, try to minimize number of situations
+ * when we need to canonicalize the path to avoid
+ * readlink() on mountpoints.
+ */
+ if (!xtgt) {
+ if (mnt_fs_streq_target(fs, tgt))
break;
+ if (tb->cache)
+ xtgt = mnt_resolve_path(tgt, tb->cache);
}
- /* mtab: compare source and target */
- else if (mnt_fs_streq_srcpath(fs, src) &&
- mnt_fs_streq_target(fs, tgt))
+ if (xtgt && mnt_fs_streq_target(fs, xtgt))
break;
+
}
if (fs)
rc = 1; /* success */
}
- if (xsrc && !tb->cache)
- free(xsrc);
- if (!tb->cache)
- free(tgt);
-
free(root);
return rc;
}
@@ -1094,11 +1107,16 @@ int test_find_pair(struct libmnt_test *ts, int argc, char *argv[])
{
struct libmnt_table *tb;
struct libmnt_fs *fs;
+ struct libmnt_cache *mpc = NULL;
int rc = -1;
tb = create_table(argv[1]);
if (!tb)
return -1;
+ mpc = mnt_new_cache();
+ if (!mpc)
+ goto done;
+ mnt_table_set_cache(tb, mpc);
fs = mnt_table_find_pair(tb, argv[2], argv[3], MNT_ITER_FORWARD);
if (!fs)
@@ -1108,6 +1126,7 @@ int test_find_pair(struct libmnt_test *ts, int argc, char *argv[])
rc = 0;
done:
mnt_free_table(tb);
+ mnt_free_cache(mpc);
return rc;
}
@@ -1116,6 +1135,7 @@ static int test_is_mounted(struct libmnt_test *ts, int argc, char *argv[])
struct libmnt_table *tb = NULL, *fstab = NULL;
struct libmnt_fs *fs;
struct libmnt_iter *itr = NULL;
+ struct libmnt_cache *mpc = NULL;
int rc;
tb = mnt_new_table_from_file("/proc/self/mountinfo");
@@ -1132,6 +1152,11 @@ static int test_is_mounted(struct libmnt_test *ts, int argc, char *argv[])
if (!itr)
goto done;
+ mpc = mnt_new_cache();
+ if (!mpc)
+ goto done;
+ mnt_table_set_cache(tb, mpc);
+
while(mnt_table_next_fs(fstab, itr, &fs) == 0) {
if (mnt_table_is_fs_mounted(tb, fs))
printf("%s already mounted on %s\n",
@@ -1147,6 +1172,7 @@ static int test_is_mounted(struct libmnt_test *ts, int argc, char *argv[])
done:
mnt_free_table(tb);
mnt_free_table(fstab);
+ mnt_free_cache(mpc);
mnt_free_iter(itr);
return rc;
}