diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2008-02-19 04:02:29 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-02-19 04:04:00 -0500 |
commit | ffc4e7595734cf768fa60cea8a4d545dfef8231a (patch) | |
tree | 9b95aca67ea7c9e87254da501f73cca64504051d /block/blk-ioc.c | |
parent | 84e9e03c55c2456799ab19f1d577e72f721fdd39 (diff) |
cfq-iosched: add hlist for browsing parallel to the radix tree
It's cumbersome to browse a radix tree from start to finish, especially
since we modify keys when a process exits. So add a hlist for the single
purpose of browsing over all known cfq_io_contexts, used for exit,
io prio change, etc.
This fixes http://bugzilla.kernel.org/show_bug.cgi?id=9948
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/blk-ioc.c')
-rw-r--r-- | block/blk-ioc.c | 35 |
1 files changed, 15 insertions, 20 deletions
diff --git a/block/blk-ioc.c b/block/blk-ioc.c index 4ae0929c6e38..e34df7c9fc36 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c | |||
@@ -17,17 +17,13 @@ static struct kmem_cache *iocontext_cachep; | |||
17 | 17 | ||
18 | static void cfq_dtor(struct io_context *ioc) | 18 | static void cfq_dtor(struct io_context *ioc) |
19 | { | 19 | { |
20 | struct cfq_io_context *cic[1]; | 20 | if (!hlist_empty(&ioc->cic_list)) { |
21 | int r; | 21 | struct cfq_io_context *cic; |
22 | 22 | ||
23 | /* | 23 | cic = list_entry(ioc->cic_list.first, struct cfq_io_context, |
24 | * We don't have a specific key to lookup with, so use the gang | 24 | cic_list); |
25 | * lookup to just retrieve the first item stored. The cfq exit | 25 | cic->dtor(ioc); |
26 | * function will iterate the full tree, so any member will do. | 26 | } |
27 | */ | ||
28 | r = radix_tree_gang_lookup(&ioc->radix_root, (void **) cic, 0, 1); | ||
29 | if (r > 0) | ||
30 | cic[0]->dtor(ioc); | ||
31 | } | 27 | } |
32 | 28 | ||
33 | /* | 29 | /* |
@@ -57,18 +53,16 @@ EXPORT_SYMBOL(put_io_context); | |||
57 | 53 | ||
58 | static void cfq_exit(struct io_context *ioc) | 54 | static void cfq_exit(struct io_context *ioc) |
59 | { | 55 | { |
60 | struct cfq_io_context *cic[1]; | ||
61 | int r; | ||
62 | |||
63 | rcu_read_lock(); | 56 | rcu_read_lock(); |
64 | /* | ||
65 | * See comment for cfq_dtor() | ||
66 | */ | ||
67 | r = radix_tree_gang_lookup(&ioc->radix_root, (void **) cic, 0, 1); | ||
68 | rcu_read_unlock(); | ||
69 | 57 | ||
70 | if (r > 0) | 58 | if (!hlist_empty(&ioc->cic_list)) { |
71 | cic[0]->exit(ioc); | 59 | struct cfq_io_context *cic; |
60 | |||
61 | cic = list_entry(ioc->cic_list.first, struct cfq_io_context, | ||
62 | cic_list); | ||
63 | cic->exit(ioc); | ||
64 | } | ||
65 | rcu_read_unlock(); | ||
72 | } | 66 | } |
73 | 67 | ||
74 | /* Called by the exitting task */ | 68 | /* Called by the exitting task */ |
@@ -105,6 +99,7 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node) | |||
105 | ret->nr_batch_requests = 0; /* because this is 0 */ | 99 | ret->nr_batch_requests = 0; /* because this is 0 */ |
106 | ret->aic = NULL; | 100 | ret->aic = NULL; |
107 | INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH); | 101 | INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH); |
102 | INIT_HLIST_HEAD(&ret->cic_list); | ||
108 | ret->ioc_data = NULL; | 103 | ret->ioc_data = NULL; |
109 | } | 104 | } |
110 | 105 | ||