]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: make it possible to define order of hooks
authorKarel Zak <kzak@redhat.com>
Wed, 22 Feb 2023 20:22:32 +0000 (21:22 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 22 Feb 2023 20:22:32 +0000 (21:22 +0100)
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>
libmount/src/hooks.c
libmount/src/mountP.h

index 2dd795590b428721ef3aa3adbb0829c72e554a44..db204ec28ec92a47d62b40c555846c8484c015a9 100644 (file)
@@ -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;
index 38c0a6d5123e27b61f47fcc19bde4921488640da..e390f39b28960f3eb38b8f0e539b9f8fc2dd3b26 100644 (file)
@@ -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,