diff options
author | Tejun Heo <tj@kernel.org> | 2012-01-10 18:11:35 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 19:30:54 -0500 |
commit | b196be89cdc14a88cc637cdad845a75c5886c82d (patch) | |
tree | 195816e6ab82362969409b3317d223421502224a | |
parent | 0499680a42141d86417a8fbaa8c8db806bea1201 (diff) |
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>
-rw-r--r-- | include/linux/workqueue.h | 47 | ||||
-rw-r--r-- | kernel/workqueue.c | 32 |
2 files changed, 53 insertions, 26 deletions
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 0d556deb497b..eb8b9f15f2e0 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h | |||
@@ -297,32 +297,50 @@ extern struct workqueue_struct *system_unbound_wq; | |||
297 | extern struct workqueue_struct *system_freezable_wq; | 297 | extern struct workqueue_struct *system_freezable_wq; |
298 | 298 | ||
299 | extern struct workqueue_struct * | 299 | extern struct workqueue_struct * |
300 | __alloc_workqueue_key(const char *name, unsigned int flags, int max_active, | 300 | __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, |
301 | struct lock_class_key *key, const char *lock_name); | 301 | struct lock_class_key *key, const char *lock_name, ...) __printf(1, 6); |
302 | 302 | ||
303 | /** | ||
304 | * alloc_workqueue - allocate a workqueue | ||
305 | * @fmt: printf format for the name of the workqueue | ||
306 | * @flags: WQ_* flags | ||
307 | * @max_active: max in-flight work items, 0 for default | ||
308 | * @args: args for @fmt | ||
309 | * | ||
310 | * Allocate a workqueue with the specified parameters. For detailed | ||
311 | * information on WQ_* flags, please refer to Documentation/workqueue.txt. | ||
312 | * | ||
313 | * The __lock_name macro dance is to guarantee that single lock_class_key | ||
314 | * doesn't end up with different namesm, which isn't allowed by lockdep. | ||
315 | * | ||
316 | * RETURNS: | ||
317 | * Pointer to the allocated workqueue on success, %NULL on failure. | ||
318 | */ | ||
303 | #ifdef CONFIG_LOCKDEP | 319 | #ifdef CONFIG_LOCKDEP |
304 | #define alloc_workqueue(name, flags, max_active) \ | 320 | #define alloc_workqueue(fmt, flags, max_active, args...) \ |
305 | ({ \ | 321 | ({ \ |
306 | static struct lock_class_key __key; \ | 322 | static struct lock_class_key __key; \ |
307 | const char *__lock_name; \ | 323 | const char *__lock_name; \ |
308 | \ | 324 | \ |
309 | if (__builtin_constant_p(name)) \ | 325 | if (__builtin_constant_p(fmt)) \ |
310 | __lock_name = (name); \ | 326 | __lock_name = (fmt); \ |
311 | else \ | 327 | else \ |
312 | __lock_name = #name; \ | 328 | __lock_name = #fmt; \ |
313 | \ | 329 | \ |
314 | __alloc_workqueue_key((name), (flags), (max_active), \ | 330 | __alloc_workqueue_key((fmt), (flags), (max_active), \ |
315 | &__key, __lock_name); \ | 331 | &__key, __lock_name, ##args); \ |
316 | }) | 332 | }) |
317 | #else | 333 | #else |
318 | #define alloc_workqueue(name, flags, max_active) \ | 334 | #define alloc_workqueue(fmt, flags, max_active, args...) \ |
319 | __alloc_workqueue_key((name), (flags), (max_active), NULL, NULL) | 335 | __alloc_workqueue_key((fmt), (flags), (max_active), \ |
336 | NULL, NULL, ##args) | ||
320 | #endif | 337 | #endif |
321 | 338 | ||
322 | /** | 339 | /** |
323 | * alloc_ordered_workqueue - allocate an ordered workqueue | 340 | * alloc_ordered_workqueue - allocate an ordered workqueue |
324 | * @name: name of the workqueue | 341 | * @fmt: printf format for the name of the workqueue |
325 | * @flags: WQ_* flags (only WQ_FREEZABLE and WQ_MEM_RECLAIM are meaningful) | 342 | * @flags: WQ_* flags (only WQ_FREEZABLE and WQ_MEM_RECLAIM are meaningful) |
343 | * @args: args for @fmt | ||
326 | * | 344 | * |
327 | * Allocate an ordered workqueue. An ordered workqueue executes at | 345 | * Allocate an ordered workqueue. An ordered workqueue executes at |
328 | * most one work item at any given time in the queued order. They are | 346 | * 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, | |||
331 | * RETURNS: | 349 | * RETURNS: |
332 | * Pointer to the allocated workqueue on success, %NULL on failure. | 350 | * Pointer to the allocated workqueue on success, %NULL on failure. |
333 | */ | 351 | */ |
334 | static inline struct workqueue_struct * | 352 | #define alloc_ordered_workqueue(fmt, flags, args...) \ |
335 | alloc_ordered_workqueue(const char *name, unsigned int flags) | 353 | alloc_workqueue(fmt, WQ_UNBOUND | (flags), 1, ##args) |
336 | { | ||
337 | return alloc_workqueue(name, WQ_UNBOUND | flags, 1); | ||
338 | } | ||
339 | 354 | ||
340 | #define create_workqueue(name) \ | 355 | #define create_workqueue(name) \ |
341 | alloc_workqueue((name), WQ_MEM_RECLAIM, 1) | 356 | alloc_workqueue((name), WQ_MEM_RECLAIM, 1) |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 42fa9ad0a810..bec7b5b53e03 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -242,10 +242,10 @@ struct workqueue_struct { | |||
242 | 242 | ||
243 | int nr_drainers; /* W: drain in progress */ | 243 | int nr_drainers; /* W: drain in progress */ |
244 | int saved_max_active; /* W: saved cwq max_active */ | 244 | int saved_max_active; /* W: saved cwq max_active */ |
245 | const char *name; /* I: workqueue name */ | ||
246 | #ifdef CONFIG_LOCKDEP | 245 | #ifdef CONFIG_LOCKDEP |
247 | struct lockdep_map lockdep_map; | 246 | struct lockdep_map lockdep_map; |
248 | #endif | 247 | #endif |
248 | char name[]; /* I: workqueue name */ | ||
249 | }; | 249 | }; |
250 | 250 | ||
251 | struct workqueue_struct *system_wq __read_mostly; | 251 | struct workqueue_struct *system_wq __read_mostly; |
@@ -2954,14 +2954,29 @@ static int wq_clamp_max_active(int max_active, unsigned int flags, | |||
2954 | return clamp_val(max_active, 1, lim); | 2954 | return clamp_val(max_active, 1, lim); |
2955 | } | 2955 | } |
2956 | 2956 | ||
2957 | struct workqueue_struct *__alloc_workqueue_key(const char *name, | 2957 | struct workqueue_struct *__alloc_workqueue_key(const char *fmt, |
2958 | unsigned int flags, | 2958 | unsigned int flags, |
2959 | int max_active, | 2959 | int max_active, |
2960 | struct lock_class_key *key, | 2960 | struct lock_class_key *key, |
2961 | const char *lock_name) | 2961 | const char *lock_name, ...) |
2962 | { | 2962 | { |
2963 | va_list args, args1; | ||
2963 | struct workqueue_struct *wq; | 2964 | struct workqueue_struct *wq; |
2964 | unsigned int cpu; | 2965 | unsigned int cpu; |
2966 | size_t namelen; | ||
2967 | |||
2968 | /* determine namelen, allocate wq and format name */ | ||
2969 | va_start(args, lock_name); | ||
2970 | va_copy(args1, args); | ||
2971 | namelen = vsnprintf(NULL, 0, fmt, args) + 1; | ||
2972 | |||
2973 | wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL); | ||
2974 | if (!wq) | ||
2975 | goto err; | ||
2976 | |||
2977 | vsnprintf(wq->name, namelen, fmt, args1); | ||
2978 | va_end(args); | ||
2979 | va_end(args1); | ||
2965 | 2980 | ||
2966 | /* | 2981 | /* |
2967 | * Workqueues which may be used during memory reclaim should | 2982 | * Workqueues which may be used during memory reclaim should |
@@ -2978,12 +2993,9 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name, | |||
2978 | flags |= WQ_HIGHPRI; | 2993 | flags |= WQ_HIGHPRI; |
2979 | 2994 | ||
2980 | max_active = max_active ?: WQ_DFL_ACTIVE; | 2995 | max_active = max_active ?: WQ_DFL_ACTIVE; |
2981 | max_active = wq_clamp_max_active(max_active, flags, name); | 2996 | max_active = wq_clamp_max_active(max_active, flags, wq->name); |
2982 | |||
2983 | wq = kzalloc(sizeof(*wq), GFP_KERNEL); | ||
2984 | if (!wq) | ||
2985 | goto err; | ||
2986 | 2997 | ||
2998 | /* init wq */ | ||
2987 | wq->flags = flags; | 2999 | wq->flags = flags; |
2988 | wq->saved_max_active = max_active; | 3000 | wq->saved_max_active = max_active; |
2989 | mutex_init(&wq->flush_mutex); | 3001 | mutex_init(&wq->flush_mutex); |
@@ -2991,7 +3003,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name, | |||
2991 | INIT_LIST_HEAD(&wq->flusher_queue); | 3003 | INIT_LIST_HEAD(&wq->flusher_queue); |
2992 | INIT_LIST_HEAD(&wq->flusher_overflow); | 3004 | INIT_LIST_HEAD(&wq->flusher_overflow); |
2993 | 3005 | ||
2994 | wq->name = name; | ||
2995 | lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); | 3006 | lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); |
2996 | INIT_LIST_HEAD(&wq->list); | 3007 | INIT_LIST_HEAD(&wq->list); |
2997 | 3008 | ||
@@ -3020,7 +3031,8 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name, | |||
3020 | if (!rescuer) | 3031 | if (!rescuer) |
3021 | goto err; | 3032 | goto err; |
3022 | 3033 | ||
3023 | rescuer->task = kthread_create(rescuer_thread, wq, "%s", name); | 3034 | rescuer->task = kthread_create(rescuer_thread, wq, "%s", |
3035 | wq->name); | ||
3024 | if (IS_ERR(rescuer->task)) | 3036 | if (IS_ERR(rescuer->task)) |
3025 | goto err; | 3037 | goto err; |
3026 | 3038 | ||