]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - libmount/src/context.c
libmount: do not call umount helper on --fake
[thirdparty/util-linux.git] / libmount / src / context.c
index 2d9795e239a7a6d21b3e6ec9800009aaa3b97177..ec04191fccb20f56f36b382ebe4ef0d525a9da46 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include "mountP.h"
+#include "fileutils.h"
 
 #include <sys/wait.h>
 
@@ -64,11 +65,6 @@ struct libmnt_context *mnt_new_context(void)
        DBG(CXT, ul_debugobj(cxt, "----> allocate %s",
                                cxt->restricted ? "[RESTRICTED]" : ""));
 
-       mnt_has_regular_mtab(&cxt->mtab_path, &cxt->mtab_writable);
-
-       if (!cxt->mtab_writable)
-               /* use /run/mount/utab if /etc/mtab is useless */
-               mnt_has_regular_utab(&cxt->utab_path, &cxt->utab_writable);
 
        return cxt;
 }
@@ -177,6 +173,7 @@ int mnt_reset_context(struct libmnt_context *cxt)
        cxt->flags |= (fl & MNT_FL_NOCANONICALIZE);
        cxt->flags |= (fl & MNT_FL_RDONLY_UMOUNT);
        cxt->flags |= (fl & MNT_FL_NOSWAPMATCH);
+       cxt->flags |= (fl & MNT_FL_TABPATHS_CHECKED);
        return 0;
 }
 
@@ -194,7 +191,6 @@ int mnt_reset_context(struct libmnt_context *cxt)
  */
 int mnt_context_reset_status(struct libmnt_context *cxt)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
 
@@ -204,6 +200,63 @@ int mnt_context_reset_status(struct libmnt_context *cxt)
        return 0;
 }
 
+static int context_init_paths(struct libmnt_context *cxt, int writable)
+{
+       assert(cxt);
+
+       if (!cxt->mtab_path)
+               cxt->mtab_path = mnt_get_mtab_path();
+       if (!cxt->utab_path)
+               cxt->utab_path = mnt_get_utab_path();
+
+       if (!writable)
+               return 0;               /* only paths wanted */
+       if (mnt_context_is_nomtab(cxt))
+               return 0;               /* write mode overrided by mount -n */
+       if (cxt->flags & MNT_FL_TABPATHS_CHECKED)
+               return 0;
+
+       DBG(CXT, ul_debugobj(cxt, "checking for writable tab files"));
+
+#ifdef USE_LIBMOUNT_FORCE_MOUNTINFO
+       cxt->mtab_writable = 0;
+#else
+       mnt_has_regular_mtab(&cxt->mtab_path, &cxt->mtab_writable);
+#endif
+
+       if (!cxt->mtab_writable)
+               /* use /run/mount/utab if /etc/mtab is useless */
+               mnt_has_regular_utab(&cxt->utab_path, &cxt->utab_writable);
+
+       cxt->flags |= MNT_FL_TABPATHS_CHECKED;
+       return 0;
+}
+
+int mnt_context_mtab_writable(struct libmnt_context *cxt)
+{
+       assert(cxt);
+
+       context_init_paths(cxt, 1);
+       return cxt->mtab_writable == 1;
+}
+
+int mnt_context_utab_writable(struct libmnt_context *cxt)
+{
+       assert(cxt);
+
+       context_init_paths(cxt, 1);
+       return cxt->utab_writable == 1;
+}
+
+const char *mnt_context_get_writable_tabpath(struct libmnt_context *cxt)
+{
+       assert(cxt);
+
+       context_init_paths(cxt, 1);
+       return cxt->mtab_writable ? cxt->mtab_path : cxt->utab_path;
+}
+
+
 static int set_flag(struct libmnt_context *cxt, int flag, int enable)
 {
        assert(cxt);
@@ -269,7 +322,6 @@ int mnt_context_is_restricted(struct libmnt_context *cxt)
  */
 int mnt_context_set_optsmode(struct libmnt_context *cxt, int mode)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
        cxt->optsmode = mode;
@@ -285,7 +337,6 @@ int mnt_context_set_optsmode(struct libmnt_context *cxt, int mode)
 
 int mnt_context_get_optsmode(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return cxt->optsmode;
 }
 
@@ -667,7 +718,6 @@ int mnt_context_set_fs(struct libmnt_context *cxt, struct libmnt_fs *fs)
  */
 struct libmnt_fs *mnt_context_get_fs(struct libmnt_context *cxt)
 {
-       assert(cxt);
        if (!cxt)
                return NULL;
        if (!cxt->fs)
@@ -683,7 +733,6 @@ struct libmnt_fs *mnt_context_get_fs(struct libmnt_context *cxt)
  */
 void *mnt_context_get_fs_userdata(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return cxt->fs ? mnt_fs_get_userdata(cxt->fs) : NULL;
 }
 
@@ -695,7 +744,6 @@ void *mnt_context_get_fs_userdata(struct libmnt_context *cxt)
  */
 void *mnt_context_get_fstab_userdata(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return cxt->fstab ? mnt_table_get_userdata(cxt->fstab) : NULL;
 }
 
@@ -707,7 +755,6 @@ void *mnt_context_get_fstab_userdata(struct libmnt_context *cxt)
  */
 void *mnt_context_get_mtab_userdata(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return cxt->mtab ? mnt_table_get_userdata(cxt->mtab) : NULL;
 }
 
@@ -716,11 +763,15 @@ void *mnt_context_get_mtab_userdata(struct libmnt_context *cxt)
  * @cxt: mount context
  * @source: mount source (device, directory, UUID, LABEL, ...)
  *
+ * Note that libmount does not interpret "nofail" (MNT_MS_NOFAIL)
+ * mount option. The real return code is always returned, when
+ * the device does not exist then it's usually MNT_ERR_NOSOURCE
+ * from libmount or ENOENT, ENOTDIR, ENOTBLK, ENXIO from moun(2).
+ *
  * Returns: 0 on success, negative number in case of error.
  */
 int mnt_context_set_source(struct libmnt_context *cxt, const char *source)
 {
-       assert(cxt);
        return mnt_fs_set_source(mnt_context_get_fs(cxt), source);
 }
 
@@ -732,7 +783,6 @@ int mnt_context_set_source(struct libmnt_context *cxt, const char *source)
  */
 const char *mnt_context_get_source(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return mnt_fs_get_source(mnt_context_get_fs(cxt));
 }
 
@@ -745,7 +795,6 @@ const char *mnt_context_get_source(struct libmnt_context *cxt)
  */
 int mnt_context_set_target(struct libmnt_context *cxt, const char *target)
 {
-       assert(cxt);
        return mnt_fs_set_target(mnt_context_get_fs(cxt), target);
 }
 
@@ -757,7 +806,6 @@ int mnt_context_set_target(struct libmnt_context *cxt, const char *target)
  */
 const char *mnt_context_get_target(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return mnt_fs_get_target(mnt_context_get_fs(cxt));
 }
 
@@ -774,7 +822,6 @@ const char *mnt_context_get_target(struct libmnt_context *cxt)
  */
 int mnt_context_set_fstype(struct libmnt_context *cxt, const char *fstype)
 {
-       assert(cxt);
        return mnt_fs_set_fstype(mnt_context_get_fs(cxt), fstype);
 }
 
@@ -786,7 +833,6 @@ int mnt_context_set_fstype(struct libmnt_context *cxt, const char *fstype)
  */
 const char *mnt_context_get_fstype(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return mnt_fs_get_fstype(mnt_context_get_fs(cxt));
 }
 
@@ -799,7 +845,6 @@ const char *mnt_context_get_fstype(struct libmnt_context *cxt)
  */
 int mnt_context_set_options(struct libmnt_context *cxt, const char *optstr)
 {
-       assert(cxt);
        return mnt_fs_set_options(mnt_context_get_fs(cxt), optstr);
 }
 
@@ -812,7 +857,6 @@ int mnt_context_set_options(struct libmnt_context *cxt, const char *optstr)
  */
 int mnt_context_append_options(struct libmnt_context *cxt, const char *optstr)
 {
-       assert(cxt);
        return mnt_fs_append_options(mnt_context_get_fs(cxt), optstr);
 }
 
@@ -831,7 +875,6 @@ int mnt_context_append_options(struct libmnt_context *cxt, const char *optstr)
  */
 const char *mnt_context_get_options(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return mnt_fs_get_options(mnt_context_get_fs(cxt));
 }
 
@@ -848,7 +891,6 @@ int mnt_context_set_fstype_pattern(struct libmnt_context *cxt, const char *patte
 {
        char *p = NULL;
 
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
        if (pattern) {
@@ -874,7 +916,6 @@ int mnt_context_set_options_pattern(struct libmnt_context *cxt, const char *patt
 {
        char *p = NULL;
 
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
        if (pattern) {
@@ -910,7 +951,6 @@ int mnt_context_set_options_pattern(struct libmnt_context *cxt, const char *patt
  */
 int mnt_context_set_fstab(struct libmnt_context *cxt, struct libmnt_table *tb)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
 
@@ -932,7 +972,6 @@ int mnt_context_set_fstab(struct libmnt_context *cxt, struct libmnt_table *tb)
  */
 int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
        if (!cxt->fstab) {
@@ -966,12 +1005,13 @@ int mnt_context_get_fstab(struct libmnt_context *cxt, struct libmnt_table **tb)
  */
 int mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
        if (!cxt->mtab) {
                int rc;
 
+               context_init_paths(cxt, 0);
+
                cxt->mtab = mnt_new_table();
                if (!cxt->mtab)
                        return -ENOMEM;
@@ -1002,6 +1042,52 @@ int mnt_context_get_mtab(struct libmnt_context *cxt, struct libmnt_table **tb)
        return 0;
 }
 
+/*
+ * Called by mtab parser to filter out entries, non-zero means that
+ * an entry has to be filtered out.
+ */
+static int mtab_filter(struct libmnt_fs *fs, void *data)
+{
+       if (!fs || !data)
+               return 0;
+       if (mnt_fs_streq_target(fs, data))
+               return 0;
+       if (mnt_fs_streq_srcpath(fs, data))
+               return 0;
+       return 1;
+}
+
+/*
+ * The same like mnt_context_get_mtab(), but does not read all mountinfo/mtab
+ * file, but only entries relevant for @tgt.
+ */
+int mnt_context_get_mtab_for_target(struct libmnt_context *cxt,
+                                   struct libmnt_table **mtab,
+                                   const char *tgt)
+{
+       struct stat st;
+       struct libmnt_cache *cache = NULL;
+       char *cn_tgt = NULL;
+       int rc;
+
+       if (stat(tgt, &st) == 0 && S_ISDIR(st.st_mode)) {
+               cache = mnt_context_get_cache(cxt);
+               cn_tgt = mnt_resolve_path(tgt, cache);
+               if (cn_tgt)
+                       mnt_context_set_tabfilter(cxt, mtab_filter, cn_tgt);
+       }
+
+       rc = mnt_context_get_mtab(cxt, mtab);
+
+       if (cn_tgt) {
+               mnt_context_set_tabfilter(cxt, NULL, NULL);
+               if (!cache)
+                       free(cn_tgt);
+       }
+
+       return rc;
+}
+
 /*
  * Allows to specify a filter for tab file entries. The filter is called by
  * the table parser. Currently used for mtab and utab only.
@@ -1010,7 +1096,6 @@ int mnt_context_set_tabfilter(struct libmnt_context *cxt,
                              int (*fltr)(struct libmnt_fs *, void *),
                              void *data)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
 
@@ -1050,8 +1135,6 @@ int mnt_context_get_table(struct libmnt_context *cxt,
 {
        int rc;
 
-       assert(cxt);
-       assert(tb);
        if (!cxt || !tb)
                return -EINVAL;
 
@@ -1089,7 +1172,6 @@ int mnt_context_get_table(struct libmnt_context *cxt,
 int mnt_context_set_tables_errcb(struct libmnt_context *cxt,
        int (*cb)(struct libmnt_table *tb, const char *filename, int line))
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
 
@@ -1147,7 +1229,6 @@ int mnt_context_set_cache(struct libmnt_context *cxt, struct libmnt_cache *cache
  */
 struct libmnt_cache *mnt_context_get_cache(struct libmnt_context *cxt)
 {
-       assert(cxt);
        if (!cxt || mnt_context_is_nocanonicalize(cxt))
                return NULL;
 
@@ -1174,7 +1255,6 @@ int mnt_context_set_passwd_cb(struct libmnt_context *cxt,
                              char *(*get)(struct libmnt_context *),
                              void (*release)(struct libmnt_context *, char *))
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
        cxt->pwd_get_cb = get;
@@ -1204,7 +1284,6 @@ int mnt_context_set_passwd_cb(struct libmnt_context *cxt,
  */
 struct libmnt_lock *mnt_context_get_lock(struct libmnt_context *cxt)
 {
-       assert(cxt);
        /*
         * DON'T call this function within libmount, it will always allocate
         * the lock. The mnt_update_* functions are able to allocate the lock
@@ -1214,8 +1293,8 @@ struct libmnt_lock *mnt_context_get_lock(struct libmnt_context *cxt)
                return NULL;
 
        if (!cxt->lock) {
-               cxt->lock = mnt_new_lock(cxt->mtab_writable ?
-                               cxt->mtab_path : cxt->utab_path, 0);
+               cxt->lock = mnt_new_lock(
+                               mnt_context_get_writable_tabpath(cxt), 0);
                if (cxt->lock)
                        mnt_lock_block_signals(cxt->lock, TRUE);
        }
@@ -1244,7 +1323,6 @@ struct libmnt_lock *mnt_context_get_lock(struct libmnt_context *cxt)
  */
 int mnt_context_set_mflags(struct libmnt_context *cxt, unsigned long flags)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
 
@@ -1277,8 +1355,6 @@ int mnt_context_get_mflags(struct libmnt_context *cxt, unsigned long *flags)
        int rc = 0;
        struct list_head *p;
 
-       assert(cxt);
-       assert(flags);
        if (!cxt || !flags)
                return -EINVAL;
 
@@ -1336,8 +1412,6 @@ int mnt_context_get_user_mflags(struct libmnt_context *cxt, unsigned long *flags
 {
        int rc = 0;
 
-       assert(cxt);
-       assert(flags);
        if (!cxt || !flags)
                return -EINVAL;
 
@@ -1369,7 +1443,6 @@ int mnt_context_get_user_mflags(struct libmnt_context *cxt, unsigned long *flags
  */
 int mnt_context_set_mountdata(struct libmnt_context *cxt, void *data)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
        cxt->mountdata = data;
@@ -1544,6 +1617,41 @@ int mnt_context_prepare_target(struct libmnt_context *cxt)
        return 0;
 }
 
+/* Guess type, but not set to cxt->fs, always use free() for the result. It's
+ * no error when we're not able to guess a filesystem type. Note that error
+ * does not mean that result in @type is NULL.
+ */
+int mnt_context_guess_srcpath_fstype(struct libmnt_context *cxt, char **type)
+{
+       int rc = 0;
+       const char *dev = mnt_fs_get_srcpath(cxt->fs);
+
+       *type = NULL;
+
+       if (!dev)
+               goto done;
+
+       if (access(dev, F_OK) == 0) {
+               struct libmnt_cache *cache = mnt_context_get_cache(cxt);
+               int ambi = 0;
+
+               *type = mnt_get_fstype(dev, &ambi, cache);
+               if (cache && *type)
+                       *type = strdup(*type);
+               if (ambi)
+                       rc = -MNT_ERR_AMBIFS;
+       } else {
+               DBG(CXT, ul_debugobj(cxt, "access(%s) failed [%m]", dev));
+               if (strchr(dev, ':') != NULL)
+                       *type = strdup("nfs");
+               else if (!strncmp(dev, "//", 2))
+                       *type = strdup("cifs");
+       }
+
+done:
+       return rc;
+}
+
 /*
  * It's usually no error when we're not able to detect the filesystem type -- we
  * will try to use the types from /{etc,proc}/filesystems.
@@ -1551,13 +1659,14 @@ int mnt_context_prepare_target(struct libmnt_context *cxt)
 int mnt_context_guess_fstype(struct libmnt_context *cxt)
 {
        char *type;
-       const char *dev;
        int rc = 0;
 
        assert(cxt);
        assert(cxt->fs);
        assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
 
+       DBG(CXT, ul_debugobj(cxt, "preparing fstype"));
+
        if (!cxt || !cxt->fs)
                return -EINVAL;
 
@@ -1573,35 +1682,16 @@ int mnt_context_guess_fstype(struct libmnt_context *cxt)
 
        if (type)
                goto done;
-       if (cxt->flags & MS_REMOUNT)
+       if (cxt->mountflags & MS_REMOUNT)
                goto none;
        if (cxt->fstype_pattern)
                goto done;
 
-       dev = mnt_fs_get_srcpath(cxt->fs);
-       if (!dev)
-               goto done;
-
-       if (access(dev, F_OK) == 0) {
-               struct libmnt_cache *cache = mnt_context_get_cache(cxt);
-               int ambi = 0;
-
-               type = mnt_get_fstype(dev, &ambi, cache);
-               if (type) {
-                       rc = mnt_fs_set_fstype(cxt->fs, type);
-                       if (!cache)
-                               free(type);     /* type is not cached */
-               }
-               if (ambi)
-                       rc = -MNT_ERR_AMBIFS;
-       } else {
-               DBG(CXT, ul_debugobj(cxt, "access(%s) failed [%m]", dev));
-               if (strchr(dev, ':') != NULL)
-                       rc = mnt_fs_set_fstype(cxt->fs, "nfs");
-               else if (!strncmp(dev, "//", 2))
-                       rc = mnt_fs_set_fstype(cxt->fs, "cifs");
-       }
-
+       rc = mnt_context_guess_srcpath_fstype(cxt, &type);
+       if (rc == 0 && type)
+               __mnt_fs_set_fstype_ptr(cxt->fs, type);
+       else
+               free(type);
 done:
        DBG(CXT, ul_debugobj(cxt, "FS type: %s [rc=%d]",
                                mnt_fs_get_fstype(cxt->fs), rc));
@@ -1726,15 +1816,15 @@ int mnt_context_prepare_update(struct libmnt_context *cxt)
 
        target = mnt_fs_get_target(cxt->fs);
 
-       if (cxt->action == MNT_ACT_UMOUNT && target && !strcmp(target, "/"))
-               /* Don't try to touch mtab if umounting root FS */
+       if (cxt->action == MNT_ACT_UMOUNT && target && !strcmp(target, "/")) {
+               DBG(CXT, ul_debugobj(cxt, "root umount: setting NOMTAB"));
                mnt_context_disable_mtab(cxt, TRUE);
-
+       }
        if (mnt_context_is_nomtab(cxt)) {
                DBG(CXT, ul_debugobj(cxt, "skip update: NOMTAB flag"));
                return 0;
        }
-       if (!cxt->mtab_writable && !cxt->utab_writable) {
+       if (!mnt_context_get_writable_tabpath(cxt)) {
                DBG(CXT, ul_debugobj(cxt, "skip update: no writable destination"));
                return 0;
        }
@@ -1747,7 +1837,7 @@ int mnt_context_prepare_update(struct libmnt_context *cxt)
        }
 
        if (!cxt->update) {
-               const char *name = cxt->mtab_writable ? cxt->mtab_path : cxt->utab_path;
+               const char *name = mnt_context_get_writable_tabpath(cxt);
 
                if (cxt->action == MNT_ACT_UMOUNT && is_file_empty(name)) {
                        DBG(CXT, ul_debugobj(cxt,
@@ -1759,7 +1849,8 @@ int mnt_context_prepare_update(struct libmnt_context *cxt)
                if (!cxt->update)
                        return -ENOMEM;
 
-               mnt_update_set_filename(cxt->update, name, !cxt->mtab_writable);
+               mnt_update_set_filename(cxt->update, name,
+                               !mnt_context_mtab_writable(cxt));
        }
 
        if (cxt->action == MNT_ACT_UMOUNT)
@@ -1790,7 +1881,7 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
        /* check utab update when external helper executed */
        if (mnt_context_helper_executed(cxt)
            && mnt_context_get_helper_status(cxt) == 0
-           && cxt->utab_writable) {
+           && mnt_context_utab_writable(cxt)) {
 
                if (mnt_update_already_done(cxt->update, cxt->lock)) {
                        DBG(CXT, ul_debugobj(cxt, "don't update: error evaluate or already updated"));
@@ -1875,6 +1966,9 @@ static int apply_table(struct libmnt_context *cxt, struct libmnt_table *tb,
        if (!rc && !mnt_fs_get_fstype(cxt->fs))
                rc = mnt_fs_set_fstype(cxt->fs, mnt_fs_get_fstype(fs));
 
+       if (!rc && !mnt_fs_get_root(cxt->fs) && mnt_fs_get_root(fs))
+               rc = mnt_fs_set_root(cxt->fs, mnt_fs_get_root(fs));
+
        if (rc)
                return rc;
 
@@ -1904,14 +1998,12 @@ static int apply_table(struct libmnt_context *cxt, struct libmnt_table *tb,
  */
 int mnt_context_apply_fstab(struct libmnt_context *cxt)
 {
-       int rc = -1;
+       int rc = -1, isremount = 0;
        struct libmnt_table *tab = NULL;
        const char *src = NULL, *tgt = NULL;
+       unsigned long mflags = 0;
 
-       assert(cxt);
-       assert(cxt->fs);
-
-       if (!cxt)
+       if (!cxt || !cxt->fs)
                return -EINVAL;
 
        if (mnt_context_tab_applied(cxt))       /* already applied */
@@ -1929,6 +2021,9 @@ int mnt_context_apply_fstab(struct libmnt_context *cxt)
                cxt->optsmode &= ~MNT_OMODE_FORCE;
        }
 
+       if (mnt_context_get_mflags(cxt, &mflags) == 0 && mflags & MS_REMOUNT)
+               isremount = 1;
+
        if (cxt->fs) {
                src = mnt_fs_get_source(cxt->fs);
                tgt = mnt_fs_get_target(cxt->fs);
@@ -1958,28 +2053,43 @@ int mnt_context_apply_fstab(struct libmnt_context *cxt)
                return 0;
        }
 
-       DBG(CXT, ul_debugobj(cxt,
-               "trying to apply fstab (src=%s, target=%s)", src, tgt));
-
        /* let's initialize cxt->fs */
        ignore_result( mnt_context_get_fs(cxt) );
 
        /* try fstab */
        if (cxt->optsmode & MNT_OMODE_FSTAB) {
+               DBG(CXT, ul_debugobj(cxt, "trying to apply fstab (src=%s, target=%s)", src, tgt));
                rc = mnt_context_get_fstab(cxt, &tab);
                if (!rc)
                        rc = apply_table(cxt, tab, MNT_ITER_FORWARD);
        }
 
        /* try mtab */
-       if (rc < 0 && (cxt->optsmode & MNT_OMODE_MTAB)) {
-               DBG(CXT, ul_debugobj(cxt, "trying to apply from mtab"));
-               rc = mnt_context_get_mtab(cxt, &tab);
+       if (rc < 0 && (cxt->optsmode & MNT_OMODE_MTAB)
+           && (isremount || cxt->action == MNT_ACT_UMOUNT)) {
+               DBG(CXT, ul_debugobj(cxt, "trying to apply mtab (src=%s, target=%s)", src, tgt));
+               if (tgt)
+                       rc = mnt_context_get_mtab_for_target(cxt, &tab, tgt);
+               else
+                       rc = mnt_context_get_mtab(cxt, &tab);
                if (!rc)
                        rc = apply_table(cxt, tab, MNT_ITER_BACKWARD);
        }
-       if (rc)
-               DBG(CXT, ul_debugobj(cxt, "failed to find entry in fstab/mtab"));
+       if (rc) {
+               if (!mnt_context_is_restricted(cxt)
+                   && tgt && !src
+                   && isremount) {
+                       DBG(CXT, ul_debugobj(cxt, "only target; ignore missing mtab entry on remount"));
+                       return 0;
+               }
+
+               DBG(CXT, ul_debugobj(cxt, "failed to find entry in fstab/mtab [rc=%d]: %m", rc));
+
+               /* force to "not found in fstab/mtab" error, the details why
+                * not found are not so important and may be misinterpreted by
+                * applications... */
+               rc = -MNT_ERR_NOFSTAB;
+       }
        return rc;
 }
 
@@ -1991,7 +2101,6 @@ int mnt_context_apply_fstab(struct libmnt_context *cxt)
  */
 int mnt_context_tab_applied(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return cxt->flags & MNT_FL_TAB_APPLIED;
 }
 
@@ -2002,9 +2111,6 @@ int mnt_context_tab_applied(struct libmnt_context *cxt)
  */
 int mnt_context_propagation_only(struct libmnt_context *cxt)
 {
-       assert(cxt);
-       assert(cxt->fs);
-
        if (cxt->action != MNT_ACT_MOUNT)
                return 0;
 
@@ -2033,7 +2139,6 @@ int mnt_context_propagation_only(struct libmnt_context *cxt)
  */
 int mnt_context_get_status(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return !cxt->syscall_status || !cxt->helper_exec_status;
 }
 
@@ -2045,7 +2150,6 @@ int mnt_context_get_status(struct libmnt_context *cxt)
  */
 int mnt_context_helper_executed(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return cxt->helper_exec_status != 1;
 }
 
@@ -2058,7 +2162,6 @@ int mnt_context_helper_executed(struct libmnt_context *cxt)
  */
 int mnt_context_get_helper_status(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return cxt->helper_status;
 }
 
@@ -2070,7 +2173,6 @@ int mnt_context_get_helper_status(struct libmnt_context *cxt)
  */
 int mnt_context_syscall_called(struct libmnt_context *cxt)
 {
-       assert(cxt);
        return cxt->syscall_status != 1;
 }
 
@@ -2085,7 +2187,6 @@ int mnt_context_syscall_called(struct libmnt_context *cxt)
  */
 int mnt_context_get_syscall_errno(struct libmnt_context *cxt)
 {
-       assert(cxt);
        if (cxt->syscall_status < 0)
                return -cxt->syscall_status;
        return 0;
@@ -2105,7 +2206,6 @@ int mnt_context_get_syscall_errno(struct libmnt_context *cxt)
  */
 int mnt_context_set_syscall_status(struct libmnt_context *cxt, int status)
 {
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
 
@@ -2154,7 +2254,8 @@ int mnt_context_init_helper(struct libmnt_context *cxt, int action,
 {
        int rc;
 
-       assert(cxt);
+       if (!cxt)
+               return -EINVAL;
 
        rc = mnt_context_disable_helpers(cxt, TRUE);
        if (!rc)
@@ -2207,7 +2308,6 @@ int mnt_context_is_fs_mounted(struct libmnt_context *cxt,
        struct libmnt_table *mtab;
        int rc;
 
-       assert(cxt);
        if (!cxt || !fs || !mounted)
                return -EINVAL;
 
@@ -2223,7 +2323,6 @@ static int mnt_context_add_child(struct libmnt_context *cxt, pid_t pid)
 {
        pid_t *pids;
 
-       assert(cxt);
        if (!cxt)
                return -EINVAL;
 
@@ -2277,7 +2376,6 @@ int mnt_context_wait_for_children(struct libmnt_context *cxt,
 {
        int i;
 
-       assert(cxt);
        if (!cxt)
                return -EINVAL;