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[] = {
[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;
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;
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,
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;
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;
}
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;