From: Karel Zak Date: Thu, 18 Aug 2022 08:58:33 +0000 (+0200) Subject: libmount: (optlist) improve cache and filtering X-Git-Tag: v2.39-rc1~314 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=94c5c1daae9fb64260289200eee66086d1be4137;p=thirdparty%2Futil-linux.git libmount: (optlist) improve cache and filtering Signed-off-by: Karel Zak --- diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index 1275862a26..52abeb8aef 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -216,7 +216,7 @@ static int fix_optstr(struct libmnt_context *cxt) strdup_to_struct_member(fs, optstr, p); /* FS options */ - mnt_optlist_get_optstr(ol, &p, NULL, MNT_OPTLIST_UNKNOWN); + mnt_optlist_get_optstr(ol, &p, NULL, MNT_OL_FLTR_UNKNOWN); strdup_to_struct_member(fs, fs_optstr, p); /* VFS options */ @@ -1962,7 +1962,7 @@ static int test_fixopts(struct libmnt_test *ts, int argc, char *argv[]) mnt_optlist_get_optstr(ls, &p, NULL, 0); printf("options (dfl): '%s'\n", p); - mnt_optlist_get_optstr(ls, &p, NULL, MNT_OPTLIST_EXTERNAL); + mnt_optlist_get_optstr(ls, &p, NULL, MNT_OL_FLTR_ALL); printf("options (ex.): '%s'\n", p); mnt_free_context(cxt); diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 008fff161d..6b6f91fccd 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -511,9 +511,15 @@ extern int mnt_optlist_insert_flags(struct libmnt_optlist *ls, unsigned long fla const struct libmnt_optmap *after_map); /* "what" argument */ enum { - MNT_OPTLIST_DEFAULT = 0, /* all (including uknonwn), but exclude external options */ - MNT_OPTLIST_UNKNOWN = (1 << 1), /* only uknonwn options */ - MNT_OPTLIST_EXTERNAL = (1 << 2) /* include also external options */ + /* Default -- if @map specified then returns all options for the map, otherwise + * returns all options including uknonwn options, exclude external options */ + MNT_OL_FLTR_DFLT = 0, + /* All options -- include mapped, unknown and external options */ + MNT_OL_FLTR_ALL, + /* All unknown options -- exclude external */ + MNT_OL_FLTR_UNKNOWN, + + __MNT_OL_FLTR_COUNT /* keep it last */ }; extern int mnt_optlist_get_flags(struct libmnt_optlist *ls, unsigned long *flags, diff --git a/libmount/src/optlist.c b/libmount/src/optlist.c index a85a8eeec3..8b2fe72293 100644 --- a/libmount/src/optlist.c +++ b/libmount/src/optlist.c @@ -17,7 +17,7 @@ #include "list.h" #include "mountP.h" -#define MNT_OPTLIST_MAXMAPS 64 +#define MNT_OL_MAXMAPS 64 enum libmnt_optsrc { MNT_OPTSRC_STRING, @@ -42,12 +42,11 @@ struct libmnt_optlist { int refcount; const struct libmnt_optmap *linux_map; /* map with MS_ flags */ - const struct libmnt_optmap *maps[MNT_OPTLIST_MAXMAPS]; + const struct libmnt_optmap *maps[MNT_OL_MAXMAPS]; size_t nmaps; - char *cached_str[MNT_OPTLIST_MAXMAPS]; - char *cached_all; - char *cached_unknown; + char *cache_mapped[MNT_OL_MAXMAPS]; /* cache by map */ + char *cache_all[__MNT_OL_FLTR_COUNT]; /* from all maps, unknown, external, ... */ unsigned long propagation; /* propagation MS_ flags */ struct list_head opts; /* parsed options */ @@ -98,10 +97,10 @@ void mnt_unref_optlist(struct libmnt_optlist *ls) } for (i = 0; i < ls->nmaps; i++) - free(ls->cached_str[i]); + free(ls->cache_mapped[i]); + for (i = 0; i < __MNT_OL_FLTR_COUNT; i++) + free(ls->cache_all[i]); - free(ls->cached_all); - free(ls->cached_unknown); free(ls); } @@ -116,7 +115,7 @@ int mnt_optlist_register_map(struct libmnt_optlist *ls, const struct libmnt_optm if (ls->maps[i] == map) return 0; /* already registred, ignore */ } - if (ls->nmaps + 1 >= MNT_OPTLIST_MAXMAPS) + if (ls->nmaps + 1 >= MNT_OL_MAXMAPS) return -ERANGE; DBG(OPTLIST, ul_debugobj(ls, "registr map %p", map)); @@ -138,28 +137,27 @@ static size_t optlist_get_mapidx(struct libmnt_optlist *ls, const struct libmnt_ return (size_t) -1; } -static void optlist_cleanup_cached(struct libmnt_optlist *ls, const struct libmnt_optmap *map) +static void optlist_cleanup_cache(struct libmnt_optlist *ls, const struct libmnt_optmap *map) { + size_t i; + if (list_empty(&ls->opts)) return; - free(ls->cached_all); - ls->cached_all = NULL; - - if (map) { size_t idx = optlist_get_mapidx(ls, map); if (idx == (size_t) -1) return; - free(ls->cached_str[idx]); - ls->cached_str[idx] = NULL; - } else { - free(ls->cached_unknown); - ls->cached_unknown = NULL; + free(ls->cache_mapped[idx]); + ls->cache_mapped[idx] = NULL; } + for (i = 0; i < __MNT_OL_FLTR_COUNT; i++) { + free(ls->cache_all[i]); + ls->cache_all[i] = NULL; + } } int mnt_optlist_remove_opt(struct libmnt_optlist *ls, struct libmnt_opt *opt) @@ -176,7 +174,7 @@ int mnt_optlist_remove_opt(struct libmnt_optlist *ls, struct libmnt_opt *opt) ls->remount = 0; } - optlist_cleanup_cached(ls, opt->map); + optlist_cleanup_cache(ls, opt->map); list_del_init(&opt->opts); free(opt->value); @@ -393,7 +391,7 @@ static int optlist_add_optstr(struct libmnt_optlist *ls, const char *optstr, opt->src = MNT_OPTSRC_STRING; } - optlist_cleanup_cached(ls, map); + optlist_cleanup_cache(ls, map); return 0; } @@ -494,7 +492,7 @@ static int optlist_add_flags(struct libmnt_optlist *ls, unsigned long flags, opt->src = MNT_OPTSRC_FLAG; } - optlist_cleanup_cached(ls, map); + optlist_cleanup_cache(ls, map); return 0; } @@ -586,19 +584,15 @@ int mnt_optlist_get_flags(struct libmnt_optlist *ls, unsigned long *flags, struct libmnt_opt *opt; unsigned long fl = *flags; - if (!ls || !map || ((what & MNT_OPTLIST_UNKNOWN) && map)) + if (!ls || !map) return -EINVAL; mnt_reset_iter(&itr, MNT_ITER_FORWARD); while (mnt_optlist_next_opt(ls, &itr, &opt) == 0) { - if ((what & MNT_OPTLIST_UNKNOWN) && opt->map) - continue; - if (map && opt->map != map) - continue; if (!opt->ent || !opt->ent->id) continue; - if (opt->external && !(what & MNT_OPTLIST_EXTERNAL)) + if (opt->external && !(what & MNT_OL_FLTR_ALL)) continue; if (opt->ent->mask & MNT_INVERT) @@ -622,27 +616,30 @@ int mnt_optlist_get_optstr(struct libmnt_optlist *ls, const char **optstr, char *str = NULL, **cache = NULL; int rc = 0; - if (!ls || !optstr || ((what & MNT_OPTLIST_UNKNOWN) && map)) + if (!ls || !optstr) return -EINVAL; *optstr = NULL; switch (what) { - case MNT_OPTLIST_DEFAULT: + case MNT_OL_FLTR_DFLT: if (map) { idx = optlist_get_mapidx(ls, map); if (idx == (size_t) -1) return -EINVAL; - if (ls->cached_str[idx]) - cache = &ls->cached_str[idx]; + if (ls->cache_mapped[idx]) + cache = &ls->cache_mapped[idx]; } else - cache = &ls->cached_all; + cache = &ls->cache_all[MNT_OL_FLTR_DFLT]; break; - case MNT_OPTLIST_UNKNOWN: - cache = &ls->cached_unknown; + case MNT_OL_FLTR_ALL: + cache = &ls->cache_all[MNT_OL_FLTR_ALL]; break; - default: + case MNT_OL_FLTR_UNKNOWN: + cache = &ls->cache_all[MNT_OL_FLTR_UNKNOWN]; break; + default: + return -EINVAL; } if (cache && *cache) { @@ -650,33 +647,45 @@ int mnt_optlist_get_optstr(struct libmnt_optlist *ls, const char **optstr, goto done; } - /* For generic options string prepend 'rw' if 'ro' not specified */ - if (!map) { + /* For generic options stings ro/rw is expected at the begining */ + if (!map && (what == MNT_OL_FLTR_DFLT || what == MNT_OL_FLTR_ALL)) { opt = mnt_optlist_get_opt(ls, MS_RDONLY, ls->linux_map); - if (!opt - && (rc = mnt_buffer_append_option(&buf, "rw", 2, NULL, 0))) + rc = mnt_buffer_append_option(&buf, opt ? "ro" : "rw", 2, NULL, 0); + if (rc) goto fail; } mnt_reset_iter(&itr, MNT_ITER_FORWARD); while (mnt_optlist_next_opt(ls, &itr, &opt) == 0) { - if ((what & MNT_OPTLIST_UNKNOWN) && opt->map) - continue; - if (map && opt->map != map) - continue; + if (!opt->name) continue; - if (opt->external && !(what & MNT_OPTLIST_EXTERNAL)) + + if (opt->map == ls->linux_map && opt->ent->id == MS_RDONLY) continue; + switch (what) { + case MNT_OL_FLTR_DFLT: + if (opt->external) + continue; + if (map && opt->map != map) + continue; + break; + case MNT_OL_FLTR_ALL: + break; + case MNT_OL_FLTR_UNKNOWN: + if (opt->map || opt->external) + continue; + break; + } + rc = mnt_buffer_append_option(&buf, opt->name, strlen(opt->name), opt->value, opt->value ? strlen(opt->value) : 0); if (rc) goto fail; - } str = ul_buffer_get_data(&buf, NULL, NULL); @@ -918,19 +927,38 @@ static int test_set_flg(struct libmnt_test *ts, int argc, char *argv[]) static int test_get_str(struct libmnt_test *ts, int argc, char *argv[]) { struct libmnt_optlist *ol; + const struct libmnt_optmap *map; const char *str = NULL; int rc; if (argc < 2) return -EINVAL; rc = mk_optlist(&ol, argv[1]); - if (!rc) { - mnt_optlist_merge_opts(ol); - rc = mnt_optlist_get_optstr(ol, &str, get_map(argv[2]), 0); + if (rc) + goto done; + + map = get_map(argv[2]); + mnt_optlist_merge_opts(ol); + + if (map) { + rc = mnt_optlist_get_optstr(ol, &str, map, MNT_OL_FLTR_DFLT); + if (!rc) + printf("Default: %s (in %s map)\n", str, argv[2]); } + + rc = mnt_optlist_get_optstr(ol, &str, NULL, MNT_OL_FLTR_DFLT); + if (!rc) + printf("Default: %s\n", str); + + + rc = mnt_optlist_get_optstr(ol, &str, NULL, MNT_OL_FLTR_ALL); if (!rc) - printf("'%s'\n", str); + printf("All: %s\n", str); + rc = mnt_optlist_get_optstr(ol, &str, NULL, MNT_OL_FLTR_UNKNOWN); + if (!rc) + printf("Unknown: %s\n", str); +done: mnt_unref_optlist(ol); return rc; }