aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-02-08 15:35:26 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-02-08 15:35:26 -0500
commit58edf8ee5e3319373dae9d9038e1a8469a83bb76 (patch)
tree68d03381fb822e6a931b0113b27c4cf133c6eb4e
parent1fb25cb8b83e85f5bf1a4adb3c9a254c4ce92405 (diff)
parentf7de7621f07495ad14fb23a812003bcf8f6af65a (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/arjan/linux-2.6-async-update
* git://git.kernel.org/pub/scm/linux/kernel/git/arjan/linux-2.6-async-update: async: use list_move_tail async: Rename _special -> _domain for clarity. async: Add some documentation. async: Handle kthread_run() return codes. async: Fix running list handling.
-rw-r--r--fs/super.c4
-rw-r--r--include/linux/async.h8
-rw-r--r--kernel/async.c82
3 files changed, 76 insertions, 18 deletions
diff --git a/fs/super.c b/fs/super.c
index 645e5403f2a0..61dce001dd57 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -301,7 +301,7 @@ void generic_shutdown_super(struct super_block *sb)
301 /* 301 /*
302 * wait for asynchronous fs operations to finish before going further 302 * wait for asynchronous fs operations to finish before going further
303 */ 303 */
304 async_synchronize_full_special(&sb->s_async_list); 304 async_synchronize_full_domain(&sb->s_async_list);
305 305
306 /* bad name - it should be evict_inodes() */ 306 /* bad name - it should be evict_inodes() */
307 invalidate_inodes(sb); 307 invalidate_inodes(sb);
@@ -470,7 +470,7 @@ restart:
470 sb->s_count++; 470 sb->s_count++;
471 spin_unlock(&sb_lock); 471 spin_unlock(&sb_lock);
472 down_read(&sb->s_umount); 472 down_read(&sb->s_umount);
473 async_synchronize_full_special(&sb->s_async_list); 473 async_synchronize_full_domain(&sb->s_async_list);
474 if (sb->s_root && (wait || sb->s_dirt)) 474 if (sb->s_root && (wait || sb->s_dirt))
475 sb->s_op->sync_fs(sb, wait); 475 sb->s_op->sync_fs(sb, wait);
476 up_read(&sb->s_umount); 476 up_read(&sb->s_umount);
diff --git a/include/linux/async.h b/include/linux/async.h
index c4ecacd0b327..68a9530196f2 100644
--- a/include/linux/async.h
+++ b/include/linux/async.h
@@ -17,9 +17,11 @@ typedef u64 async_cookie_t;
17typedef void (async_func_ptr) (void *data, async_cookie_t cookie); 17typedef void (async_func_ptr) (void *data, async_cookie_t cookie);
18 18
19extern async_cookie_t async_schedule(async_func_ptr *ptr, void *data); 19extern async_cookie_t async_schedule(async_func_ptr *ptr, void *data);
20extern async_cookie_t async_schedule_special(async_func_ptr *ptr, void *data, struct list_head *list); 20extern async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data,
21 struct list_head *list);
21extern void async_synchronize_full(void); 22extern void async_synchronize_full(void);
22extern void async_synchronize_full_special(struct list_head *list); 23extern void async_synchronize_full_domain(struct list_head *list);
23extern void async_synchronize_cookie(async_cookie_t cookie); 24extern void async_synchronize_cookie(async_cookie_t cookie);
24extern void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *list); 25extern void async_synchronize_cookie_domain(async_cookie_t cookie,
26 struct list_head *list);
25 27
diff --git a/kernel/async.c b/kernel/async.c
index 67a2be71f517..f565891f2c9b 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -54,6 +54,7 @@ asynchronous and synchronous parts of the kernel.
54#include <linux/sched.h> 54#include <linux/sched.h>
55#include <linux/init.h> 55#include <linux/init.h>
56#include <linux/kthread.h> 56#include <linux/kthread.h>
57#include <linux/delay.h>
57#include <asm/atomic.h> 58#include <asm/atomic.h>
58 59
59static async_cookie_t next_cookie = 1; 60static async_cookie_t next_cookie = 1;
@@ -132,8 +133,7 @@ static void run_one_entry(void)
132 entry = list_first_entry(&async_pending, struct async_entry, list); 133 entry = list_first_entry(&async_pending, struct async_entry, list);
133 134
134 /* 2) move it to the running queue */ 135 /* 2) move it to the running queue */
135 list_del(&entry->list); 136 list_move_tail(&entry->list, entry->running);
136 list_add_tail(&entry->list, &async_running);
137 spin_unlock_irqrestore(&async_lock, flags); 137 spin_unlock_irqrestore(&async_lock, flags);
138 138
139 /* 3) run it (and print duration)*/ 139 /* 3) run it (and print duration)*/
@@ -208,18 +208,44 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct l
208 return newcookie; 208 return newcookie;
209} 209}
210 210
211/**
212 * async_schedule - schedule a function for asynchronous execution
213 * @ptr: function to execute asynchronously
214 * @data: data pointer to pass to the function
215 *
216 * Returns an async_cookie_t that may be used for checkpointing later.
217 * Note: This function may be called from atomic or non-atomic contexts.
218 */
211async_cookie_t async_schedule(async_func_ptr *ptr, void *data) 219async_cookie_t async_schedule(async_func_ptr *ptr, void *data)
212{ 220{
213 return __async_schedule(ptr, data, &async_pending); 221 return __async_schedule(ptr, data, &async_running);
214} 222}
215EXPORT_SYMBOL_GPL(async_schedule); 223EXPORT_SYMBOL_GPL(async_schedule);
216 224
217async_cookie_t async_schedule_special(async_func_ptr *ptr, void *data, struct list_head *running) 225/**
226 * async_schedule_domain - schedule a function for asynchronous execution within a certain domain
227 * @ptr: function to execute asynchronously
228 * @data: data pointer to pass to the function
229 * @running: running list for the domain
230 *
231 * Returns an async_cookie_t that may be used for checkpointing later.
232 * @running may be used in the async_synchronize_*_domain() functions
233 * to wait within a certain synchronization domain rather than globally.
234 * A synchronization domain is specified via the running queue @running to use.
235 * Note: This function may be called from atomic or non-atomic contexts.
236 */
237async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data,
238 struct list_head *running)
218{ 239{
219 return __async_schedule(ptr, data, running); 240 return __async_schedule(ptr, data, running);
220} 241}
221EXPORT_SYMBOL_GPL(async_schedule_special); 242EXPORT_SYMBOL_GPL(async_schedule_domain);
222 243
244/**
245 * async_synchronize_full - synchronize all asynchronous function calls
246 *
247 * This function waits until all asynchronous function calls have been done.
248 */
223void async_synchronize_full(void) 249void async_synchronize_full(void)
224{ 250{
225 do { 251 do {
@@ -228,13 +254,30 @@ void async_synchronize_full(void)
228} 254}
229EXPORT_SYMBOL_GPL(async_synchronize_full); 255EXPORT_SYMBOL_GPL(async_synchronize_full);
230 256
231void async_synchronize_full_special(struct list_head *list) 257/**
258 * async_synchronize_full_domain - synchronize all asynchronous function within a certain domain
259 * @list: running list to synchronize on
260 *
261 * This function waits until all asynchronous function calls for the
262 * synchronization domain specified by the running list @list have been done.
263 */
264void async_synchronize_full_domain(struct list_head *list)
232{ 265{
233 async_synchronize_cookie_special(next_cookie, list); 266 async_synchronize_cookie_domain(next_cookie, list);
234} 267}
235EXPORT_SYMBOL_GPL(async_synchronize_full_special); 268EXPORT_SYMBOL_GPL(async_synchronize_full_domain);
236 269
237void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *running) 270/**
271 * async_synchronize_cookie_domain - synchronize asynchronous function calls within a certain domain with cookie checkpointing
272 * @cookie: async_cookie_t to use as checkpoint
273 * @running: running list to synchronize on
274 *
275 * This function waits until all asynchronous function calls for the
276 * synchronization domain specified by the running list @list submitted
277 * prior to @cookie have been done.
278 */
279void async_synchronize_cookie_domain(async_cookie_t cookie,
280 struct list_head *running)
238{ 281{
239 ktime_t starttime, delta, endtime; 282 ktime_t starttime, delta, endtime;
240 283
@@ -254,11 +297,18 @@ void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *r
254 (long long)ktime_to_ns(delta) >> 10); 297 (long long)ktime_to_ns(delta) >> 10);
255 } 298 }
256} 299}
257EXPORT_SYMBOL_GPL(async_synchronize_cookie_special); 300EXPORT_SYMBOL_GPL(async_synchronize_cookie_domain);
258 301
302/**
303 * async_synchronize_cookie - synchronize asynchronous function calls with cookie checkpointing
304 * @cookie: async_cookie_t to use as checkpoint
305 *
306 * This function waits until all asynchronous function calls prior to @cookie
307 * have been done.
308 */
259void async_synchronize_cookie(async_cookie_t cookie) 309void async_synchronize_cookie(async_cookie_t cookie)
260{ 310{
261 async_synchronize_cookie_special(cookie, &async_running); 311 async_synchronize_cookie_domain(cookie, &async_running);
262} 312}
263EXPORT_SYMBOL_GPL(async_synchronize_cookie); 313EXPORT_SYMBOL_GPL(async_synchronize_cookie);
264 314
@@ -319,7 +369,11 @@ static int async_manager_thread(void *unused)
319 ec = atomic_read(&entry_count); 369 ec = atomic_read(&entry_count);
320 370
321 while (tc < ec && tc < MAX_THREADS) { 371 while (tc < ec && tc < MAX_THREADS) {
322 kthread_run(async_thread, NULL, "async/%i", tc); 372 if (IS_ERR(kthread_run(async_thread, NULL, "async/%i",
373 tc))) {
374 msleep(100);
375 continue;
376 }
323 atomic_inc(&thread_count); 377 atomic_inc(&thread_count);
324 tc++; 378 tc++;
325 } 379 }
@@ -334,7 +388,9 @@ static int async_manager_thread(void *unused)
334static int __init async_init(void) 388static int __init async_init(void)
335{ 389{
336 if (async_enabled) 390 if (async_enabled)
337 kthread_run(async_manager_thread, NULL, "async/mgr"); 391 if (IS_ERR(kthread_run(async_manager_thread, NULL,
392 "async/mgr")))
393 async_enabled = 0;
338 return 0; 394 return 0;
339} 395}
340 396