backport: backport sprintf-style workqueue naming
authorJohannes Berg <johannes.berg@intel.com>
Tue, 16 Jul 2013 12:57:57 +0000 (15:57 +0300)
committerLuis R. Rodriguez <mcgrof@do-not-panic.com>
Fri, 19 Jul 2013 22:05:32 +0000 (15:05 -0700)
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@intel.com>
[mcgrof: add WQ_HIGHPRI and WQ_MEM_RECLAIM defines]
Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
backport/backport-include/linux/workqueue.h
backport/compat/compat-3.3.c

index 9958715bd2e39a7576abed97ead31d88ff98c261..1e9ca71c9100aaa6e1617864e0b02bbd8e640e6f 100644 (file)
@@ -14,16 +14,52 @@ 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(2,6,36)
+#define WQ_HIGHPRI 0
+#define WQ_MEM_RECLAIM 0
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-#define alloc_workqueue(name, flags, max_active) __create_workqueue(name, flags, max_active)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
+#define WQ_UNBOUND     0
 #endif
-
-#ifndef alloc_workqueue
-#define alloc_workqueue(name, flags, max_active) __create_workqueue(name, flags, max_active, 0)
+#define __WQ_ORDERED   0
+/*
+ * commit b196be89cdc14a88cc637cdad845a75c5886c82d
+ * Author: Tejun Heo <tj@kernel.org>
+ * 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
+#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
+void backport_destroy_workqueue(struct workqueue_struct *wq);
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
index a44f59dd9c649c7c6a765ff3c9649fd701ace84a..d86b40e2510a8454eb8c687b48ef26460797e94f 100644 (file)
@@ -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);