libmount: add support for MS_REMOUNT on --all

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>
This commit is contained in:
Karel Zak 2019-01-16 15:00:07 +01:00
parent 12d12102d6
commit 189a1bf3b3
9 changed files with 217 additions and 6 deletions

View 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

View 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

View 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

View 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
*/

View 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);

View File

@ -344,4 +344,5 @@ MOUNT_2.33 {
MOUNT_2.34 {
mnt_guess_system_root;
mnt_context_next_remount;
} MOUNT_2.33;

View 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);

View 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.

View 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) ||