What would you think to this? +++ b/include/linux/delayed_call.h @@ -14,13 +14,12 @@ struct delayed_call { #define DEFINE_DELAYED_CALL(name) struct delayed_call name = {NULL, NULL} -/* I really wish we had closures with sane typechecking... */ -static inline void set_delayed_call(struct delayed_call *call, - void (*fn)(void *), void *arg) -{ - call->fn = fn; - call->arg = arg; -} +/* Typecheck the arg is appropriate for the function */ +#define set_delayed_call(call, _fn, _arg) do { \ + (void)sizeof(_fn(_arg)); \ + (call)->fn = (void (*)(void *))(_fn); \ + (call)->arg = (_arg); \ +} while (0) static inline void do_delayed_call(struct delayed_call *call) { That should give us the possibility of passing any pointer to the function, but gets us away from void pointers. I did this as a followup: -extern void page_put_link(void *); +extern void page_put_link(struct folio *); ... -void page_put_link(void *arg) +void page_put_link(struct folio *folio) { - put_page(arg); + folio_put(folio); } EXPORT_SYMBOL(page_put_link); and similar changes to the three callers. Or is there something newer and shinier we should be using instead of delayed_call?