On 07/16/2013 02:57 PM, Johannes Berg wrote: > From: Johannes Berg <johannes.berg@xxxxxxxxx> > > Since kernel version 3.3, workqueue names could be > sprintf'ed instead of just pointing to a name. This > wasn't used a lot so never needed to be backported, > but now it's used everywhere. Backport this API. > > Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx> > --- > backport/backport-include/linux/workqueue.h | 47 ++++++++++++++++---- > backport/compat/compat-3.3.c | 69 +++++++++++++++++++++++++++++ > 2 files changed, 108 insertions(+), 8 deletions(-) > > diff --git a/backport/backport-include/linux/workqueue.h b/backport/backport-include/linux/workqueue.h > index 9958715..54c9090 100644 > --- a/backport/backport-include/linux/workqueue.h > +++ b/backport/backport-include/linux/workqueue.h > @@ -14,16 +14,47 @@ bool mod_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, > #define create_freezable_workqueue create_freezeable_workqueue > #endif > > -#ifndef alloc_ordered_workqueue > -#define alloc_ordered_workqueue(name, flags) create_singlethread_workqueue(name) > +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) > +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) Why not do a check for #ifndef WQ_UNBOUND that way we do not get that many problems when someone tries a kernel that already backported this. > +#define WQ_UNBOUND 0 > #endif > - > -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) > -#define alloc_workqueue(name, flags, max_active) __create_workqueue(name, flags, max_active) > +#define __WQ_ORDERED 0 > +/* > + * commit b196be89cdc14a88cc637cdad845a75c5886c82d > + * Author: Tejun Heo <tj@xxxxxxxxxx> > + * Date: Tue Jan 10 15:11:35 2012 -0800 > + * > + * workqueue: make alloc_workqueue() take printf fmt and args for name > + */ > +struct workqueue_struct * > +backport_alloc_workqueue(const char *fmt, unsigned int flags, > + int max_active, struct lock_class_key *key, > + const char *lock_name, ...); > +#undef alloc_workqueue > +#ifdef CONFIG_LOCKDEP > +#define alloc_workqueue(fmt, flags, max_active, args...) \ > +({ \ > + static struct lock_class_key __key; \ > + const char *__lock_name; \ > + \ > + if (__builtin_constant_p(fmt)) \ > + __lock_name = (fmt); \ > + else \ > + __lock_name = #fmt; \ > + \ > + backport_alloc_workqueue((fmt), (flags), (max_active), \ > + &__key, __lock_name, ##args); \ > +}) > +#else > +#define alloc_workqueue(fmt, flags, max_active, args...) \ > + backport_alloc_workqueue((fmt), (flags), (max_active), \ > + NULL, NULL, ##args) > #endif > - > -#ifndef alloc_workqueue > -#define alloc_workqueue(name, flags, max_active) __create_workqueue(name, flags, max_active, 0) > +#undef alloc_ordered_workqueue > +#define alloc_ordered_workqueue(fmt, flags, args...) \ > + alloc_workqueue(fmt, WQ_UNBOUND | __WQ_ORDERED | (flags), 1, ##args) > +#define destroy_workqueue backport_destroy_workqueue The #undef destroy_workqueue in compat-3.3.c does not look nice to me. What about this and then call orig_destroy_workqueue(wq)? static inline void orig_destroy_workqueue(struct workqueue_struct *wq) { destroy_workqueue(wq); } #define destroy_workqueue(wq) backport_destroy_workqueue(wq) > +void backport_destroy_workqueue(struct workqueue_struct *wq); > #endif > > #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) > diff --git a/backport/compat/compat-3.3.c b/backport/compat/compat-3.3.c > index a44f59d..d86b40e 100644 > --- a/backport/compat/compat-3.3.c > +++ b/backport/compat/compat-3.3.c > @@ -12,6 +12,7 @@ > #include <linux/version.h> > #include <linux/skbuff.h> > #include <linux/module.h> > +#include <linux/workqueue.h> > #include <net/dst.h> > #include <net/xfrm.h> > > @@ -171,3 +172,71 @@ out: > return n; > } > EXPORT_SYMBOL_GPL(__pskb_copy); > + > +static DEFINE_SPINLOCK(wq_name_lock); > +static struct list_head wq_name_list; > + > +struct wq_name { > + struct list_head list; > + struct workqueue_struct *wq; > + char name[24]; > +}; > + > +struct workqueue_struct * > +backport_alloc_workqueue(const char *fmt, unsigned int flags, > + int max_active, struct lock_class_key *key, > + const char *lock_name, ...) > +{ > + struct workqueue_struct *wq; > + struct wq_name *n = kzalloc(sizeof(*n), GFP_KERNEL); > + va_list args; > + > + if (!n) > + return NULL; > + > + va_start(args, lock_name); > + vsnprintf(n->name, sizeof(n->name), fmt, args); > + va_end(args); > + > +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) > + wq = __create_workqueue_key(n->name, max_active == 1, 0, > +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) > + 0, > +#endif > + key, lock_name); > +#else > + wq = __alloc_workqueue_key(n->name, flags, max_active, key, lock_name); > +#endif > + if (!wq) { > + kfree(n); > + return NULL; > + } > + > + n->wq = wq; > + spin_lock(&wq_name_lock); > + list_add(&n->list, &wq_name_list); > + spin_unlock(&wq_name_lock); > + > + return wq; > +} > +EXPORT_SYMBOL_GPL(backport_alloc_workqueue); > + > +void backport_destroy_workqueue(struct workqueue_struct *wq) > +{ > + struct wq_name *n, *tmp; > + > + /* call original */ > +#undef destroy_workqueue > + destroy_workqueue(wq); > + > + spin_lock(&wq_name_lock); > + list_for_each_entry_safe(n, tmp, &wq_name_list, list) { > + if (n->wq == wq) { > + list_del(&n->list); > + kfree(n); > + break; > + } > + } > + spin_unlock(&wq_name_lock); > +} > +EXPORT_SYMBOL_GPL(backport_destroy_workqueue); > -- To unsubscribe from this list: send the line "unsubscribe backports" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html