From: Karel Zak Date: Thu, 6 Oct 2022 10:02:41 +0000 (+0200) Subject: libmount: fix mount -a to work with optlist X-Git-Tag: v2.39-rc1~242 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=01790c7d6d418b440961a769f191338e37f0df62;p=thirdparty%2Futil-linux.git libmount: fix mount -a to work with optlist The original code uses libmnt_fs instance to store mount options. The new uses libmnt_fs only for library API backward compatibility, but internally it uses libmnt_optlist. Let's use optlist also to save context template. Signed-off-by: Karel Zak --- diff --git a/libmount/src/context.c b/libmount/src/context.c index e602ce54bc..3551b0d77b 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -102,7 +102,8 @@ void mnt_free_context(struct libmnt_context *cxt) mnt_unref_table(cxt->fstab); mnt_unref_cache(cxt->cache); mnt_unref_fs(cxt->fs); - mnt_unref_fs(cxt->fs_template); + + mnt_unref_optlist(cxt->optlist_saved); mnt_unref_optlist(cxt->optlist); mnt_free_lock(cxt->lock); @@ -152,11 +153,13 @@ int mnt_reset_context(struct libmnt_context *cxt) mnt_unref_fs(cxt->fs); mnt_unref_table(cxt->mountinfo); mnt_unref_table(cxt->utab); + mnt_unref_optlist(cxt->optlist); free(cxt->helper); cxt->fs = NULL; cxt->mountinfo = NULL; + cxt->optlist = NULL; cxt->utab = NULL; cxt->helper = NULL; cxt->mountdata = NULL; @@ -194,7 +197,7 @@ int mnt_reset_context(struct libmnt_context *cxt) } /* - * Saves the current context FS setting (mount options, etc) to make it usable after + * Saves the current context setting (mount options, etc) to make it usable after * mnt_reset_context() or by mnt_context_apply_template(). This is usable for * example for mnt_context_next_mount() where for the next mount operation we * need to restore to the original context setting. @@ -203,21 +206,17 @@ int mnt_reset_context(struct libmnt_context *cxt) */ int mnt_context_save_template(struct libmnt_context *cxt) { - struct libmnt_fs *fs = NULL; - if (!cxt) return -EINVAL; - DBG(CXT, ul_debugobj(cxt, "save FS as template")); + DBG(CXT, ul_debugobj(cxt, "saving template")); - if (cxt->fs) { - fs = mnt_copy_fs(NULL, cxt->fs); - if (!fs) - return -ENOMEM; - } + /* reset old saved data */ + mnt_unref_optlist(cxt->optlist_saved); + cxt->optlist_saved = NULL; - mnt_unref_fs(cxt->fs_template); - cxt->fs_template = fs; + if (cxt->optlist) + cxt->optlist_saved = mnt_copy_optlist(cxt->optlist); return 0; } @@ -230,31 +229,22 @@ int mnt_context_save_template(struct libmnt_context *cxt) */ int mnt_context_apply_template(struct libmnt_context *cxt) { - struct libmnt_fs *fs = NULL; - int rc = 0; - if (!cxt) return -EINVAL; - if (cxt->fs_template) { - DBG(CXT, ul_debugobj(cxt, "copy FS from template")); - fs = mnt_copy_fs(NULL, cxt->fs_template); - if (!fs) - return -ENOMEM; - rc = mnt_context_set_fs(cxt, fs); - mnt_unref_fs(fs); - } else { - DBG(CXT, ul_debugobj(cxt, "no FS template, reset only")); - mnt_unref_fs(cxt->fs); - cxt->fs = NULL; - } + DBG(CXT, ul_debugobj(cxt, "restoring template")); + mnt_unref_optlist(cxt->optlist); + cxt->optlist = NULL; - return rc; + if (cxt->optlist_saved) + cxt->optlist = mnt_copy_optlist(cxt->optlist_saved); + + return 0; } int mnt_context_has_template(struct libmnt_context *cxt) { - return cxt && cxt->fs_template ? 1 : 0; + return cxt && cxt->optlist_saved ? 1 : 0; } struct libmnt_context *mnt_copy_context(struct libmnt_context *o) @@ -1163,13 +1153,10 @@ int mnt_context_append_options(struct libmnt_context *cxt, const char *optstr) */ const char *mnt_context_get_options(struct libmnt_context *cxt) { - struct libmnt_optlist *ls = mnt_context_get_optlist(cxt); const char *str = NULL; - if (!ls) - return NULL; - - mnt_optlist_get_optstr(ls, &str, NULL, 0); + if (cxt->optlist && !mnt_optlist_is_empty(cxt->optlist)) + mnt_optlist_get_optstr(cxt->optlist, &str, NULL, 0); return str; } @@ -2199,6 +2186,8 @@ static int apply_fs(struct libmnt_context *cxt, struct libmnt_fs *fs, unsigned l struct libmnt_optlist *ls; int rc; + + if (!cxt->optsmode) { if (mnt_context_is_restricted(cxt)) { DBG(CXT, ul_debugobj(cxt, "force fstab usage for non-root users!")); @@ -2210,6 +2199,9 @@ static int apply_fs(struct libmnt_context *cxt, struct libmnt_fs *fs, unsigned l } + if (!mnt_context_get_fs(cxt)) + return -ENOMEM; + DBG(CXT, ul_debugobj(cxt, "apply entry:")); DBG(CXT, mnt_fs_print_debug(fs, stderr)); DBG(CXT, ul_debugobj(cxt, "OPTSMODE (opt-part): ignore=%d, append=%d, prepend=%d, replace=%d", diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 3345a14dec..e6ac6b6651 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -371,7 +371,6 @@ struct libmnt_context char *optstr_pattern; /* for mnt_match_options() */ struct libmnt_fs *fs; /* filesystem description (type, mountpoint, device, ...) */ - struct libmnt_fs *fs_template; /* used for @fs on mnt_reset_context() */ struct libmnt_table *fstab; /* fstab entries */ struct libmnt_table *mountinfo; /* already mounted filesystems */ @@ -393,7 +392,9 @@ struct libmnt_context struct libmnt_cache *cache; /* paths cache */ struct libmnt_lock *lock; /* utab lock */ struct libmnt_update *update; /* utab update */ + struct libmnt_optlist *optlist; /* parsed mount options */ + struct libmnt_optlist *optlist_saved; /* save/apply context template */ const struct libmnt_optmap *map_linux; /* system options map */ const struct libmnt_optmap *map_userspace; /* userspace options map */ @@ -484,6 +485,8 @@ struct libmnt_optlist; extern struct libmnt_optlist *mnt_new_optlist(void); extern void mnt_ref_optlist(struct libmnt_optlist *ls); extern void mnt_unref_optlist(struct libmnt_optlist *ls); +extern struct libmnt_optlist *mnt_copy_optlist(struct libmnt_optlist *ls); +extern int mnt_optlist_is_empty(struct libmnt_optlist *ls); extern unsigned int mnt_optlist_get_age(struct libmnt_optlist *ls); extern int mnt_optlist_register_map(struct libmnt_optlist *ls, const struct libmnt_optmap *map); extern int mnt_optlist_remove_opt(struct libmnt_optlist *ls, struct libmnt_opt *opt); diff --git a/libmount/src/optlist.c b/libmount/src/optlist.c index edb9594912..7b4033aaa7 100644 --- a/libmount/src/optlist.c +++ b/libmount/src/optlist.c @@ -918,6 +918,48 @@ int mnt_optlist_get_optstr(struct libmnt_optlist *ls, const char **optstr, return 0; } +struct libmnt_optlist *mnt_copy_optlist(struct libmnt_optlist *ls) +{ + struct libmnt_optlist *n = mnt_new_optlist(); + struct libmnt_iter itr; + struct libmnt_opt *opt; + size_t i; + + if (!n) + return NULL; + + n->age = ls->age; + n->linux_map = ls->linux_map; + + for (i = 0; i < ls->nmaps; i++) + n->maps[i] = ls->maps[i]; + n->nmaps = ls->nmaps; + + mnt_reset_iter(&itr, MNT_ITER_FORWARD); + + while (mnt_optlist_next_opt(ls, &itr, &opt) == 0) { + struct libmnt_opt *no; + + no = optlist_new_opt(n, + opt->name, opt->name ? strlen(opt->name) : 0, + opt->value, opt->value ? strlen(opt->value) : 0, + opt->map, opt->ent, NULL); + if (no) { + no->src = opt->src; + no->external = opt->external; + } + } + + n->merged = ls->merged; + return n; +} + + +int mnt_optlist_is_empty(struct libmnt_optlist *ls) +{ + return ls == NULL || list_empty(&ls->opts); +} + unsigned int mnt_optlist_get_age(struct libmnt_optlist *ls) { return ls ? ls->age : 0;