If we do add the destructor hook, I think it looks like this.
It would merit some write-up in utrace.tmpl text too.

I'm not especially convinced it's a very good idea.
But I won't object if people serious about using the API think it helps.


Thanks,
Roland


---
 include/linux/utrace.h |    8 ++++++++
 kernel/utrace.c        |    3 +++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/include/linux/utrace.h b/include/linux/utrace.h
index c19c01b..f968792 100644
--- a/include/linux/utrace.h
+++ b/include/linux/utrace.h
@@ -322,6 +322,7 @@ static inline enum utrace_syscall_action 
utrace_syscall_action(u32 action)
 struct utrace_engine {
 /* private: */
        struct kref kref;
+       void (*release)(void *);
        struct list_head entry;
 
 /* public: */
@@ -539,6 +540,12 @@ static inline void utrace_engine_put(struct utrace_engine 
*engine)
  *     Unlike other callbacks, this can be called from the parent's context
  *     rather than from the traced thread itself--it must not delay the
  *     parent by blocking.
+ *
+ * @release:
+ *     If not %NULL, this is called after the last utrace_engine_put()
+ *     call for a &struct utrace_engine, which could be implicit after
+ *     a %UTRACE_DETACH return from another callback.  Its argument is
+ *     the engine's @data member.
  */
 struct utrace_engine_ops {
        u32 (*report_quiesce)(enum utrace_resume_action action,
@@ -584,6 +591,7 @@ struct utrace_engine_ops {
                            bool group_dead, int signal);
        void (*report_reap)(struct utrace_engine *engine,
                            struct task_struct *task);
+       void (*release)(void *data);
 };
 
 /**
diff --git a/kernel/utrace.c b/kernel/utrace.c
index 35be909..3b7ac74 100644
--- a/kernel/utrace.c
+++ b/kernel/utrace.c
@@ -79,6 +79,8 @@ void __utrace_engine_release(struct kref *kref)
        struct utrace_engine *engine = container_of(kref, struct utrace_engine,
                                                    kref);
        BUG_ON(!list_empty(&engine->entry));
+       if (engine->release)
+               (*engine->release)(engine->data);
        kmem_cache_free(utrace_engine_cachep, engine);
 }
 EXPORT_SYMBOL_GPL(__utrace_engine_release);
@@ -271,6 +273,7 @@ struct utrace_engine *utrace_attach_task(
        engine->flags = 0;
        engine->ops = ops;
        engine->data = data;
+       engine->release = ops->release;
 
        ret = utrace_attach_delay(target);
        if (likely(!ret))

Reply via email to