workqueue: make alloc_workqueue() take printf fmt and args for name

alloc_workqueue() currently expects the passed in @name pointer to remain
accessible.  This is inconvenient and a bit silly given that the whole wq
is being dynamically allocated.  This patch updates alloc_workqueue() and
friends to take printf format string instead of opaque string and matching
varargs at the end.  The name is allocated together with the wq and
formatted.

alloc_ordered_workqueue() is converted to a macro to unify varargs
handling with alloc_workqueue(), and, while at it, add comment to
alloc_workqueue().

None of the current in-kernel users pass in string with '%' as constant
name and this change shouldn't cause any problem.

[akpm@linux-foundation.org: use __printf]
Signed-off-by: Tejun Heo <tj@kernel.org>
Suggested-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Tejun Heo 2012-01-10 15:11:35 -08:00 committed by Linus Torvalds
parent 0499680a42
commit b196be89cd
2 changed files with 53 additions and 26 deletions

View File

@ -297,32 +297,50 @@ extern struct workqueue_struct *system_unbound_wq;
extern struct workqueue_struct *system_freezable_wq; extern struct workqueue_struct *system_freezable_wq;
extern struct workqueue_struct * extern struct workqueue_struct *
__alloc_workqueue_key(const char *name, unsigned int flags, int max_active, __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
struct lock_class_key *key, const char *lock_name); struct lock_class_key *key, const char *lock_name, ...) __printf(1, 6);
/**
* alloc_workqueue - allocate a workqueue
* @fmt: printf format for the name of the workqueue
* @flags: WQ_* flags
* @max_active: max in-flight work items, 0 for default
* @args: args for @fmt
*
* Allocate a workqueue with the specified parameters. For detailed
* information on WQ_* flags, please refer to Documentation/workqueue.txt.
*
* The __lock_name macro dance is to guarantee that single lock_class_key
* doesn't end up with different namesm, which isn't allowed by lockdep.
*
* RETURNS:
* Pointer to the allocated workqueue on success, %NULL on failure.
*/
#ifdef CONFIG_LOCKDEP #ifdef CONFIG_LOCKDEP
#define alloc_workqueue(name, flags, max_active) \ #define alloc_workqueue(fmt, flags, max_active, args...) \
({ \ ({ \
static struct lock_class_key __key; \ static struct lock_class_key __key; \
const char *__lock_name; \ const char *__lock_name; \
\ \
if (__builtin_constant_p(name)) \ if (__builtin_constant_p(fmt)) \
__lock_name = (name); \ __lock_name = (fmt); \
else \ else \
__lock_name = #name; \ __lock_name = #fmt; \
\ \
__alloc_workqueue_key((name), (flags), (max_active), \ __alloc_workqueue_key((fmt), (flags), (max_active), \
&__key, __lock_name); \ &__key, __lock_name, ##args); \
}) })
#else #else
#define alloc_workqueue(name, flags, max_active) \ #define alloc_workqueue(fmt, flags, max_active, args...) \
__alloc_workqueue_key((name), (flags), (max_active), NULL, NULL) __alloc_workqueue_key((fmt), (flags), (max_active), \
NULL, NULL, ##args)
#endif #endif
/** /**
* alloc_ordered_workqueue - allocate an ordered workqueue * alloc_ordered_workqueue - allocate an ordered workqueue
* @name: name of the workqueue * @fmt: printf format for the name of the workqueue
* @flags: WQ_* flags (only WQ_FREEZABLE and WQ_MEM_RECLAIM are meaningful) * @flags: WQ_* flags (only WQ_FREEZABLE and WQ_MEM_RECLAIM are meaningful)
* @args: args for @fmt
* *
* Allocate an ordered workqueue. An ordered workqueue executes at * Allocate an ordered workqueue. An ordered workqueue executes at
* most one work item at any given time in the queued order. They are * most one work item at any given time in the queued order. They are
@ -331,11 +349,8 @@ __alloc_workqueue_key(const char *name, unsigned int flags, int max_active,
* RETURNS: * RETURNS:
* Pointer to the allocated workqueue on success, %NULL on failure. * Pointer to the allocated workqueue on success, %NULL on failure.
*/ */
static inline struct workqueue_struct * #define alloc_ordered_workqueue(fmt, flags, args...) \
alloc_ordered_workqueue(const char *name, unsigned int flags) alloc_workqueue(fmt, WQ_UNBOUND | (flags), 1, ##args)
{
return alloc_workqueue(name, WQ_UNBOUND | flags, 1);
}
#define create_workqueue(name) \ #define create_workqueue(name) \
alloc_workqueue((name), WQ_MEM_RECLAIM, 1) alloc_workqueue((name), WQ_MEM_RECLAIM, 1)

View File

@ -242,10 +242,10 @@ struct workqueue_struct {
int nr_drainers; /* W: drain in progress */ int nr_drainers; /* W: drain in progress */
int saved_max_active; /* W: saved cwq max_active */ int saved_max_active; /* W: saved cwq max_active */
const char *name; /* I: workqueue name */
#ifdef CONFIG_LOCKDEP #ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map; struct lockdep_map lockdep_map;
#endif #endif
char name[]; /* I: workqueue name */
}; };
struct workqueue_struct *system_wq __read_mostly; struct workqueue_struct *system_wq __read_mostly;
@ -2954,14 +2954,29 @@ static int wq_clamp_max_active(int max_active, unsigned int flags,
return clamp_val(max_active, 1, lim); return clamp_val(max_active, 1, lim);
} }
struct workqueue_struct *__alloc_workqueue_key(const char *name, struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
unsigned int flags, unsigned int flags,
int max_active, int max_active,
struct lock_class_key *key, struct lock_class_key *key,
const char *lock_name) const char *lock_name, ...)
{ {
va_list args, args1;
struct workqueue_struct *wq; struct workqueue_struct *wq;
unsigned int cpu; unsigned int cpu;
size_t namelen;
/* determine namelen, allocate wq and format name */
va_start(args, lock_name);
va_copy(args1, args);
namelen = vsnprintf(NULL, 0, fmt, args) + 1;
wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL);
if (!wq)
goto err;
vsnprintf(wq->name, namelen, fmt, args1);
va_end(args);
va_end(args1);
/* /*
* Workqueues which may be used during memory reclaim should * Workqueues which may be used during memory reclaim should
@ -2978,12 +2993,9 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
flags |= WQ_HIGHPRI; flags |= WQ_HIGHPRI;
max_active = max_active ?: WQ_DFL_ACTIVE; max_active = max_active ?: WQ_DFL_ACTIVE;
max_active = wq_clamp_max_active(max_active, flags, name); max_active = wq_clamp_max_active(max_active, flags, wq->name);
wq = kzalloc(sizeof(*wq), GFP_KERNEL);
if (!wq)
goto err;
/* init wq */
wq->flags = flags; wq->flags = flags;
wq->saved_max_active = max_active; wq->saved_max_active = max_active;
mutex_init(&wq->flush_mutex); mutex_init(&wq->flush_mutex);
@ -2991,7 +3003,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
INIT_LIST_HEAD(&wq->flusher_queue); INIT_LIST_HEAD(&wq->flusher_queue);
INIT_LIST_HEAD(&wq->flusher_overflow); INIT_LIST_HEAD(&wq->flusher_overflow);
wq->name = name;
lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); lockdep_init_map(&wq->lockdep_map, lock_name, key, 0);
INIT_LIST_HEAD(&wq->list); INIT_LIST_HEAD(&wq->list);
@ -3020,7 +3031,8 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name,
if (!rescuer) if (!rescuer)
goto err; goto err;
rescuer->task = kthread_create(rescuer_thread, wq, "%s", name); rescuer->task = kthread_create(rescuer_thread, wq, "%s",
wq->name);
if (IS_ERR(rescuer->task)) if (IS_ERR(rescuer->task))
goto err; goto err;