From: Karel Zak Date: Wed, 22 Feb 2023 20:22:32 +0000 (+0100) Subject: libmount: make it possible to define order of hooks X-Git-Tag: v2.39-rc1~60 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=211bb3c9df0f6764a2ae62753c0c1ed930ca37f0;p=thirdparty%2Futil-linux.git libmount: make it possible to define order of hooks In some cases we have more hooks in the same stage and it's necessary to call some hooks after another. Signed-off-by: Karel Zak --- diff --git a/libmount/src/hooks.c b/libmount/src/hooks.c index 2dd795590b..db204ec28e 100644 --- a/libmount/src/hooks.c +++ b/libmount/src/hooks.c @@ -66,10 +66,12 @@ struct hookset_hook { const struct libmnt_hookset *hookset; int stage; void *data; + const char *after; int (*func)(struct libmnt_context *, const struct libmnt_hookset *, void *); struct list_head hooks; + unsigned int executed : 1; }; static const char *stagenames[] = { @@ -88,6 +90,9 @@ static const char *stagenames[] = { [MNT_STAGE_POST] = "post", }; +static int call_depend_hooks(struct libmnt_context *cxt, const char *name, int stage); + + int mnt_context_deinit_hooksets(struct libmnt_context *cxt) { size_t i; @@ -188,13 +193,14 @@ void *mnt_context_get_hookset_data(struct libmnt_context *cxt, return hd ? hd->data : NULL; } -int mnt_context_append_hook(struct libmnt_context *cxt, +static int append_hook(struct libmnt_context *cxt, const struct libmnt_hookset *hs, int stage, void *data, int (*func)(struct libmnt_context *, const struct libmnt_hookset *, - void *)) + void *), + const char *after) { struct hookset_hook *hook; @@ -215,11 +221,35 @@ int mnt_context_append_hook(struct libmnt_context *cxt, hook->data = data; hook->func = func; hook->stage = stage; + hook->after = after; list_add_tail(&hook->hooks, &cxt->hooksets_hooks); return 0; } +int mnt_context_append_hook(struct libmnt_context *cxt, + const struct libmnt_hookset *hs, + int stage, + void *data, + int (*func)(struct libmnt_context *, + const struct libmnt_hookset *, + void *)) +{ + return append_hook(cxt, hs, stage, data, func, NULL); +} + +int mnt_context_insert_hook(struct libmnt_context *cxt, + const char *after, + const struct libmnt_hookset *hs, + int stage, + void *data, + int (*func)(struct libmnt_context *, + const struct libmnt_hookset *, + void *)) +{ + return append_hook(cxt, hs, stage, data, func, after); +} + static struct hookset_hook *get_hookset_hook(struct libmnt_context *cxt, const struct libmnt_hookset *hs, int stage, @@ -277,9 +307,40 @@ int mnt_context_has_hook(struct libmnt_context *cxt, return get_hookset_hook(cxt, hs, stage, data) ? 1 : 0; } +static int call_hook(struct libmnt_context *cxt, struct hookset_hook *hook) +{ + int rc = hook->func(cxt, hook->hookset, hook->data); + + hook->executed = 1; + if (!rc) + rc = call_depend_hooks(cxt, hook->hookset->name, hook->stage); + return rc; +} + +static int call_depend_hooks(struct libmnt_context *cxt, const char *name, int stage) +{ + struct list_head *p = NULL, *next = NULL; + int rc = 0; + + list_for_each_safe(p, next, &cxt->hooksets_hooks) { + struct hookset_hook *x = list_entry(p, struct hookset_hook, hooks); + + if (x->stage != stage || x->executed || + x->after == NULL || strcmp(x->after, name) != 0) + continue; + + DBG(CXT, ul_debugobj(cxt, "calling %s [after]", x->hookset->name)); + rc = call_hook(cxt, x); + if (rc) + break; + } + + return rc; +} + int mnt_context_call_hooks(struct libmnt_context *cxt, int stage) { - struct list_head *p, *next; + struct list_head *p = NULL, *next = NULL; size_t i; int rc = 0; @@ -292,9 +353,11 @@ int mnt_context_call_hooks(struct libmnt_context *cxt, int stage) if (hs->firststage != stage) continue; - DBG(CXT, ul_debugobj(cxt, "calling %s hook", hs->name)); + DBG(CXT, ul_debugobj(cxt, "calling %s [first]", hs->name)); rc = hs->firstcall(cxt, hs, NULL); + if (!rc) + rc = call_depend_hooks(cxt, hs->name, stage); if (rc < 0) goto done; } @@ -303,17 +366,26 @@ int mnt_context_call_hooks(struct libmnt_context *cxt, int stage) list_for_each_safe(p, next, &cxt->hooksets_hooks) { struct hookset_hook *x = list_entry(p, struct hookset_hook, hooks); - if (x->stage != stage) + if (x->stage != stage || x->executed) continue; - DBG(CXT, ul_debugobj(cxt, "calling %s hook", x->hookset->name)); - - rc = x->func(cxt, x->hookset, x->data); + DBG(CXT, ul_debugobj(cxt, "calling %s [active]", x->hookset->name)); + rc = call_hook(cxt, x); if (rc < 0) goto done; } done: + /* zeroize status */ + p = next = NULL; + list_for_each_safe(p, next, &cxt->hooksets_hooks) { + struct hookset_hook *x = list_entry(p, struct hookset_hook, hooks); + + if (x->stage != stage) + continue; + x->executed = 0; + } + DBG(CXT, ul_debugobj(cxt, "<--- stage:%s [rc=%d status=%d]", stagenames[stage], rc, cxt->syscall_status)); return rc; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 38c0a6d512..e390f39b28 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -349,6 +349,14 @@ extern int mnt_context_append_hook(struct libmnt_context *cxt, int (*func)(struct libmnt_context *, const struct libmnt_hookset *, void *)); +extern int mnt_context_insert_hook(struct libmnt_context *cxt, + const char *after, + const struct libmnt_hookset *hs, + int stage, + void *data, + int (*func)(struct libmnt_context *, + const struct libmnt_hookset *, + void *)); extern int mnt_context_remove_hook(struct libmnt_context *cxt, const struct libmnt_hookset *hs,