diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 15:05:53 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2006-03-18 18:34:15 -0500 |
commit | 334e94de9bea353156abd6f2242d3cc4a24562b0 (patch) | |
tree | ff4a253e9e3bf487be03bf58727a7ea40a34ba87 /block/as-iosched.c | |
parent | e17a9489b4a686bb5e9615e1d375c67619cb99c5 (diff) |
[PATCH] deal with rmmod/put_io_context() races
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'block/as-iosched.c')
-rw-r--r-- | block/as-iosched.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/block/as-iosched.c b/block/as-iosched.c index d2ee2af44b58..55a997fc4bb4 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c | |||
@@ -182,6 +182,9 @@ struct as_rq { | |||
182 | 182 | ||
183 | static kmem_cache_t *arq_pool; | 183 | static kmem_cache_t *arq_pool; |
184 | 184 | ||
185 | static atomic_t ioc_count = ATOMIC_INIT(0); | ||
186 | static struct completion *ioc_gone; | ||
187 | |||
185 | static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq); | 188 | static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq); |
186 | static void as_antic_stop(struct as_data *ad); | 189 | static void as_antic_stop(struct as_data *ad); |
187 | 190 | ||
@@ -193,11 +196,14 @@ static void as_antic_stop(struct as_data *ad); | |||
193 | static void free_as_io_context(struct as_io_context *aic) | 196 | static void free_as_io_context(struct as_io_context *aic) |
194 | { | 197 | { |
195 | kfree(aic); | 198 | kfree(aic); |
199 | if (atomic_dec_and_test(&ioc_count) && ioc_gone) | ||
200 | complete(ioc_gone); | ||
196 | } | 201 | } |
197 | 202 | ||
198 | static void as_trim(struct io_context *ioc) | 203 | static void as_trim(struct io_context *ioc) |
199 | { | 204 | { |
200 | kfree(ioc->aic); | 205 | if (ioc->aic) |
206 | free_as_io_context(ioc->aic); | ||
201 | ioc->aic = NULL; | 207 | ioc->aic = NULL; |
202 | } | 208 | } |
203 | 209 | ||
@@ -226,6 +232,7 @@ static struct as_io_context *alloc_as_io_context(void) | |||
226 | ret->seek_total = 0; | 232 | ret->seek_total = 0; |
227 | ret->seek_samples = 0; | 233 | ret->seek_samples = 0; |
228 | ret->seek_mean = 0; | 234 | ret->seek_mean = 0; |
235 | atomic_inc(&ioc_count); | ||
229 | } | 236 | } |
230 | 237 | ||
231 | return ret; | 238 | return ret; |
@@ -1900,7 +1907,13 @@ static int __init as_init(void) | |||
1900 | 1907 | ||
1901 | static void __exit as_exit(void) | 1908 | static void __exit as_exit(void) |
1902 | { | 1909 | { |
1910 | DECLARE_COMPLETION(all_gone); | ||
1903 | elv_unregister(&iosched_as); | 1911 | elv_unregister(&iosched_as); |
1912 | ioc_gone = &all_gone; | ||
1913 | barrier(); | ||
1914 | if (atomic_read(&ioc_count)) | ||
1915 | complete(ioc_gone); | ||
1916 | synchronize_rcu(); | ||
1904 | kmem_cache_destroy(arq_pool); | 1917 | kmem_cache_destroy(arq_pool); |
1905 | } | 1918 | } |
1906 | 1919 | ||