diff options
| author | Karel Zak <kzak@redhat.com> | 2023-02-22 21:22:32 +0100 |
|---|---|---|
| committer | Karel Zak <kzak@redhat.com> | 2023-02-22 21:22:32 +0100 |
| commit | 211bb3c9df0f6764a2ae62753c0c1ed930ca37f0 (patch) | |
| tree | 5bcc53e9553fdb9b523ca659ab9d37ac21953093 /libmount/src/hooks.c | |
| parent | 1a75b4f92685147c4aaf915e9028d41cac305d69 (diff) | |
| download | util-linux-211bb3c9df0f6764a2ae62753c0c1ed930ca37f0.tar.gz | |
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 <kzak@redhat.com>
Diffstat (limited to 'libmount/src/hooks.c')
| -rw-r--r-- | libmount/src/hooks.c | 88 |
1 files changed, 80 insertions, 8 deletions
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; |
