]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: add support for MS_REMOUNT on --all
authorKarel Zak <kzak@redhat.com>
Wed, 16 Jan 2019 14:00:07 +0000 (15:00 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 16 Jan 2019 14:00:07 +0000 (15:00 +0100)
This patch add to support for remount-all operation to
libmount and mount(8).

For example:
mount --all -o remount,ro -t vfat

to remount read-only all VFAT filesystems.

Addresses: https://github.com/karelzak/util-linux/issues/589
Signed-off-by: Karel Zak <kzak@redhat.com>
Documentation/TODO
libmount/docs/libmount-sections.txt
libmount/src/context.c
libmount/src/context_mount.c
libmount/src/libmount.h.in
libmount/src/libmount.sym
libmount/src/mountP.h
sys-utils/mount.8
sys-utils/mount.c

index 03e0a75cb66274e12668b7f9ab6473d2b0a9e9f4..bbb53a0c0e59212bd4db21c78fd4196035f2b278 100644 (file)
@@ -65,11 +65,6 @@ bash completion
 libmount (mount/umount)
 -----------------------
 
- - remount all filesystems given their type, for example:
-        mount -a -t tmpfs -o remount
-   It should be probably enough to add remount_all() to mount(8) in way we
-   already have mount_all().  https://github.com/karelzak/util-linux/issues/589
-
  - add --onlyonce to force mount(8) to check if mountpoint is already used. Now
    "already mounted" detection is used for --all only. The problem is if you
    call "mount <mountpoint>" more than once for in fstab defined tmpfs (or network
index a046fb38752bfdb0a7a59cdaa6b46a856f122764..3df4a9b0bd2e4590eb3b567d0b22f6027faba4aa 100644 (file)
@@ -135,6 +135,7 @@ mnt_context_do_mount
 mnt_context_finalize_mount
 mnt_context_mount
 mnt_context_next_mount
+mnt_context_next_remount
 mnt_context_prepare_mount
 <SUBSECTION>
 MNT_MS_COMMENT
index b9c18d94f7240ee5fad7c42f73e04b49a9d48287..af9b9ca50c1b516e6b31d188808180ccee28c497 100644 (file)
@@ -193,6 +193,49 @@ int mnt_reset_context(struct libmnt_context *cxt)
        return 0;
 }
 
+struct libmnt_context *mnt_copy_context(struct libmnt_context *o)
+{
+       struct libmnt_context *n;
+
+       n = mnt_new_context();
+       if (!n)
+               return NULL;
+
+       DBG(CXT, ul_debugobj(n, "<---- clone ---->"));
+
+       n->flags = o->flags;
+
+       if (o->fs) {
+               n->fs = mnt_copy_fs(NULL, o->fs);
+               if (!n->fs)
+                       goto failed;
+       }
+
+       n->mtab = o->mtab;
+       mnt_ref_table(n->mtab);
+
+       n->mtab = o->utab;
+       mnt_ref_table(n->utab);
+
+       if (o->helper)
+               n->helper = strdup(o->helper);
+       if (o->orig_user)
+               n->orig_user = strdup(o->orig_user);
+
+       n->mountflags = o->mountflags;
+       n->mountdata = o->mountdata;
+
+       mnt_context_reset_status(n);
+
+       n->table_fltrcb = o->table_fltrcb;
+       n->table_fltrcb_data = o->table_fltrcb_data;
+
+       return n;
+failed:
+       mnt_free_context(n);
+       return NULL;
+}
+
 /**
  * mnt_context_reset_status:
  * @cxt: context
index f914c9b1bf51df1f620232c92242bd9f947ec24d..307da3c5ca53334dc193296b9ba68d067203ac72 100644 (file)
@@ -1382,6 +1382,112 @@ int mnt_context_next_mount(struct libmnt_context *cxt,
        return 0;
 }
 
+
+/**
+ * mnt_context_next_remount:
+ * @cxt: context
+ * @itr: iterator
+ * @fs: returns the current filesystem
+ * @mntrc: returns the return code from mnt_context_mount()
+ * @ignored: returns 1 for non-matching
+ *
+ * This function tries to remount the next mounted filesystem (as returned by
+ * mnt_context_get_mtab()).
+ *
+ * You can filter out filesystems by:
+ *     mnt_context_set_options_pattern() to simulate mount -a -O pattern
+ *     mnt_context_set_fstype_pattern()  to simulate mount -a -t pattern
+ *
+ * If the filesystem does not match defined criteria, then the
+ * mnt_context_next_remount() function returns zero, but the @ignored is
+ * non-zero.
+ *
+ * If mount(2) syscall or mount.type helper failed, then the
+ * mnt_context_renext_mount() function returns zero, but the @mntrc is non-zero.
+ * Use also mnt_context_get_status() to check if the filesystem was
+ * successfully mounted.
+ *
+ * See mnt_context_mount() for more details about errors and warnings.
+ *
+ * Returns: 0 on success,
+ *         <0 in case of error (!= mount(2) errors)
+ *          1 at the end of the list.
+ */
+int mnt_context_next_remount(struct libmnt_context *cxt,
+                          struct libmnt_iter *itr,
+                          struct libmnt_fs **fs,
+                          int *mntrc,
+                          int *ignored)
+{
+       struct libmnt_context *remount_cxt = NULL;
+       struct libmnt_table *mtab;
+       const char *tgt;
+       int rc;
+
+       if (ignored)
+               *ignored = 0;
+       if (mntrc)
+               *mntrc = 0;
+
+       if (!cxt || !fs || !itr)
+               return -EINVAL;
+
+       rc = mnt_context_get_mtab(cxt, &mtab);
+       if (rc)
+               return rc;
+
+       rc = mnt_table_next_fs(mtab, itr, fs);
+       if (rc != 0)
+               return rc;      /* more filesystems (or error) */
+
+       tgt = mnt_fs_get_target(*fs);
+
+       DBG(CXT, ul_debugobj(cxt, "next-remount: trying %s", tgt));
+
+       /* ignore filesystems which don't match options patterns */
+       if ((cxt->fstype_pattern && !mnt_fs_match_fstype(*fs,
+                                       cxt->fstype_pattern)) ||
+
+       /* ignore filesystems which don't match type patterns */
+          (cxt->optstr_pattern && !mnt_fs_match_options(*fs,
+                                       cxt->optstr_pattern))) {
+               if (ignored)
+                       *ignored = 1;
+               DBG(CXT, ul_debugobj(cxt, "next-remount: not-match "
+                               "[fstype: %s, t-pattern: %s, options: %s, O-pattern: %s]",
+                               mnt_fs_get_fstype(*fs),
+                               cxt->fstype_pattern,
+                               mnt_fs_get_options(*fs),
+                               cxt->optstr_pattern));
+               return 0;
+       }
+
+       /* make sure fstab is already read to avoid fstab parsing in cloned context */
+       mnt_context_get_fstab(cxt, NULL);
+
+       /* clone context */
+       remount_cxt = mnt_copy_context(cxt);
+       if (!remount_cxt)
+               return -ENOMEM;
+
+       rc = mnt_context_set_target(remount_cxt, tgt);
+       if (!rc) {
+               /*
+                * "-t <pattern>" is used to filter out fstab entries, but for ordinary
+                * mount operation -t means "-t <type>". We have to zeroize the pattern
+                * to avoid misinterpretation.
+                */
+               remount_cxt->fstype_pattern = NULL;
+               rc = mnt_context_mount(remount_cxt);
+
+               if (mntrc)
+                       *mntrc = rc;
+       }
+
+       mnt_free_context(remount_cxt);
+       return 0;
+}
+
 /*
  * Returns 1 if @dir parent is shared
  */
index 1ce9995ecd677b5a991f9a699abd87cdfa2de5e7..a14bb6f3d13c8aa1ffaa57e5832003f8f59b0973 100644 (file)
@@ -849,6 +849,12 @@ extern int mnt_context_next_mount(struct libmnt_context *cxt,
                                struct libmnt_fs **fs,
                                int *mntrc, int *ignored);
 
+extern int mnt_context_next_remount(struct libmnt_context *cxt,
+                           struct libmnt_iter *itr,
+                           struct libmnt_fs **fs,
+                           int *mntrc,
+                           int *ignored);
+
 extern int mnt_context_prepare_mount(struct libmnt_context *cxt)
                        __ul_attribute__((warn_unused_result));
 extern int mnt_context_do_mount(struct libmnt_context *cxt);
index 5145c876dd156bc1ddb3aeb0f2872c577a1e1679..0087a3d23b42f08376c92c11f2a926b37b68c9ea 100644 (file)
@@ -344,4 +344,5 @@ MOUNT_2.33 {
 
 MOUNT_2.34 {
        mnt_guess_system_root;
+       mnt_context_next_remount;
 } MOUNT_2.33;
index 795ea69dc4a8be95c0ea17ea7b52b3fef51c5d0d..7887c0a55dead592941aa18439b1a0a7e7354776 100644 (file)
@@ -403,6 +403,7 @@ extern int __mnt_fs_set_fstype_ptr(struct libmnt_fs *fs, char *fstype)
                        __attribute__((nonnull(1)));
 
 /* context.c */
+extern struct libmnt_context *mnt_copy_context(struct libmnt_context *o);
 extern int mnt_context_mtab_writable(struct libmnt_context *cxt);
 extern int mnt_context_utab_writable(struct libmnt_context *cxt);
 extern const char *mnt_context_get_writable_tabpath(struct libmnt_context *cxt);
index da0ac5b8b0ce315a0fd09acfdf3b754a09afca32..6ef58905058ddcbd81bacd136e19e9b4e369d9c9 100644 (file)
@@ -580,6 +580,10 @@ mount or btrfs) to detect already mounted filesystems. The kernel table with
 already mounted filesystems is cached during \fBmount \-\-all\fR. It means
 that all duplicated fstab entries will be mounted.
 .sp
+The option \fB\-\-all\fR is possible to use for remount operation too. In this
+case all filters (\fB\-t\fR and \fB\-O\fR) are applied to the table of already
+mounted filesystems.
+.sp
 Note that it is a bad practice to use \fBmount \-a\fR for
 .I fstab
 checking. The recommended solution is \fBfindmnt \-\-verify\fR.
index 5e139e896948e02da6dcc05996953591e1e30ddc..f4a387b8a21af7a66c517a5dd3f70c230c1b1fe9 100644 (file)
@@ -231,6 +231,57 @@ static int mount_all(struct libmnt_context *cxt)
        return rc;
 }
 
+
+/*
+ * mount -a -o remount
+ */
+static int remount_all(struct libmnt_context *cxt)
+{
+       struct libmnt_iter *itr;
+       struct libmnt_fs *fs;
+       int mntrc, ignored, rc = MNT_EX_SUCCESS;
+
+       int nsucc = 0, nerrs = 0;
+
+       itr = mnt_new_iter(MNT_ITER_FORWARD);
+       if (!itr) {
+               warn(_("failed to initialize libmount iterator"));
+               return MNT_EX_SYSERR;
+       }
+
+       while (mnt_context_next_remount(cxt, itr, &fs, &mntrc, &ignored) == 0) {
+
+               const char *tgt = mnt_fs_get_target(fs);
+
+               if (ignored) {
+                       if (mnt_context_is_verbose(cxt))
+                               printf(_("%-25s: ignored\n"), tgt);
+               } else {
+                       if (mk_exit_code(cxt, mntrc) == MNT_EX_SUCCESS) {
+                               nsucc++;
+
+                               /* Note that MNT_EX_SUCCESS return code does
+                                * not mean that FS has been really mounted
+                                * (e.g. nofail option) */
+                               if (mnt_context_get_status(cxt)
+                                   && mnt_context_is_verbose(cxt))
+                                       printf("%-25s: successfully remounted\n", tgt);
+                       } else
+                               nerrs++;
+               }
+       }
+
+       if (nerrs == 0)
+               rc = MNT_EX_SUCCESS;            /* all success */
+       else if (nsucc == 0)
+               rc = MNT_EX_FAIL;               /* all failed */
+       else
+               rc = MNT_EX_SOMEOK;             /* some success, some failed */
+
+       mnt_free_iter(itr);
+       return rc;
+}
+
 static void success_message(struct libmnt_context *cxt)
 {
        unsigned long mflags = 0;
@@ -836,7 +887,10 @@ int main(int argc, char **argv)
                /*
                 * A) Mount all
                 */
-               rc = mount_all(cxt);
+               if (has_remount_flag(cxt))
+                       rc = remount_all(cxt);
+               else
+                       rc = mount_all(cxt);
                goto done;
 
        } else if (argc == 0 && (mnt_context_get_source(cxt) ||