diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2009-01-05 04:17:25 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-01-30 06:34:36 -0500 |
commit | f48fc4d32e24c0b6a18aad30305d819bcc68c049 (patch) | |
tree | d993ccadfe87a0c481fba7e697107bb5cc701b4a /block | |
parent | 322316385dde5cd879e682bcb598c56d0659fb60 (diff) |
block: get rid of the manual directory counting in blktrace
It can result in a stuck blktrace system, if --kill is used.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blktrace.c | 72 |
1 files changed, 21 insertions, 51 deletions
diff --git a/block/blktrace.c b/block/blktrace.c index b0a2cae886db..39cc3bfe56e4 100644 --- a/block/blktrace.c +++ b/block/blktrace.c | |||
@@ -187,59 +187,12 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, | |||
187 | 187 | ||
188 | static struct dentry *blk_tree_root; | 188 | static struct dentry *blk_tree_root; |
189 | static DEFINE_MUTEX(blk_tree_mutex); | 189 | static DEFINE_MUTEX(blk_tree_mutex); |
190 | static unsigned int root_users; | ||
191 | |||
192 | static inline void blk_remove_root(void) | ||
193 | { | ||
194 | if (blk_tree_root) { | ||
195 | debugfs_remove(blk_tree_root); | ||
196 | blk_tree_root = NULL; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | static void blk_remove_tree(struct dentry *dir) | ||
201 | { | ||
202 | mutex_lock(&blk_tree_mutex); | ||
203 | debugfs_remove(dir); | ||
204 | if (--root_users == 0) | ||
205 | blk_remove_root(); | ||
206 | mutex_unlock(&blk_tree_mutex); | ||
207 | } | ||
208 | |||
209 | static struct dentry *blk_create_tree(const char *blk_name) | ||
210 | { | ||
211 | struct dentry *dir = NULL; | ||
212 | int created = 0; | ||
213 | |||
214 | mutex_lock(&blk_tree_mutex); | ||
215 | |||
216 | if (!blk_tree_root) { | ||
217 | blk_tree_root = debugfs_create_dir("block", NULL); | ||
218 | if (!blk_tree_root) | ||
219 | goto err; | ||
220 | created = 1; | ||
221 | } | ||
222 | |||
223 | dir = debugfs_create_dir(blk_name, blk_tree_root); | ||
224 | if (dir) | ||
225 | root_users++; | ||
226 | else { | ||
227 | /* Delete root only if we created it */ | ||
228 | if (created) | ||
229 | blk_remove_root(); | ||
230 | } | ||
231 | |||
232 | err: | ||
233 | mutex_unlock(&blk_tree_mutex); | ||
234 | return dir; | ||
235 | } | ||
236 | 190 | ||
237 | static void blk_trace_cleanup(struct blk_trace *bt) | 191 | static void blk_trace_cleanup(struct blk_trace *bt) |
238 | { | 192 | { |
239 | relay_close(bt->rchan); | ||
240 | debugfs_remove(bt->msg_file); | 193 | debugfs_remove(bt->msg_file); |
241 | debugfs_remove(bt->dropped_file); | 194 | debugfs_remove(bt->dropped_file); |
242 | blk_remove_tree(bt->dir); | 195 | relay_close(bt->rchan); |
243 | free_percpu(bt->sequence); | 196 | free_percpu(bt->sequence); |
244 | free_percpu(bt->msg_data); | 197 | free_percpu(bt->msg_data); |
245 | kfree(bt); | 198 | kfree(bt); |
@@ -346,7 +299,18 @@ static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf, | |||
346 | 299 | ||
347 | static int blk_remove_buf_file_callback(struct dentry *dentry) | 300 | static int blk_remove_buf_file_callback(struct dentry *dentry) |
348 | { | 301 | { |
302 | struct dentry *parent = dentry->d_parent; | ||
349 | debugfs_remove(dentry); | 303 | debugfs_remove(dentry); |
304 | |||
305 | /* | ||
306 | * this will fail for all but the last file, but that is ok. what we | ||
307 | * care about is the top level buts->name directory going away, when | ||
308 | * the last trace file is gone. Then we don't have to rmdir() that | ||
309 | * manually on trace stop, so it nicely solves the issue with | ||
310 | * force killing of running traces. | ||
311 | */ | ||
312 | |||
313 | debugfs_remove(parent); | ||
350 | return 0; | 314 | return 0; |
351 | } | 315 | } |
352 | 316 | ||
@@ -404,7 +368,15 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | |||
404 | goto err; | 368 | goto err; |
405 | 369 | ||
406 | ret = -ENOENT; | 370 | ret = -ENOENT; |
407 | dir = blk_create_tree(buts->name); | 371 | |
372 | if (!blk_tree_root) { | ||
373 | blk_tree_root = debugfs_create_dir("block", NULL); | ||
374 | if (!blk_tree_root) | ||
375 | return -ENOMEM; | ||
376 | } | ||
377 | |||
378 | dir = debugfs_create_dir(buts->name, blk_tree_root); | ||
379 | |||
408 | if (!dir) | 380 | if (!dir) |
409 | goto err; | 381 | goto err; |
410 | 382 | ||
@@ -458,8 +430,6 @@ probe_err: | |||
458 | atomic_dec(&blk_probes_ref); | 430 | atomic_dec(&blk_probes_ref); |
459 | mutex_unlock(&blk_probe_mutex); | 431 | mutex_unlock(&blk_probe_mutex); |
460 | err: | 432 | err: |
461 | if (dir) | ||
462 | blk_remove_tree(dir); | ||
463 | if (bt) { | 433 | if (bt) { |
464 | if (bt->msg_file) | 434 | if (bt->msg_file) |
465 | debugfs_remove(bt->msg_file); | 435 | debugfs_remove(bt->msg_file); |