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:
parent
12d12102d6
commit
189a1bf3b3
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -344,4 +344,5 @@ MOUNT_2.33 {
|
|||
|
||||
MOUNT_2.34 {
|
||||
mnt_guess_system_root;
|
||||
mnt_context_next_remount;
|
||||
} MOUNT_2.33;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) ||
|
||||
|
|
Loading…
Reference in New Issue