diff options
-rw-r--r-- | fs/dlm/debug_fs.c | 164 | ||||
-rw-r--r-- | fs/dlm/dlm_internal.h | 1 |
2 files changed, 163 insertions, 2 deletions
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 9e27a1675794..184be9870c63 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c | |||
@@ -27,6 +27,8 @@ static struct dentry *dlm_root; | |||
27 | 27 | ||
28 | struct rsb_iter { | 28 | struct rsb_iter { |
29 | int entry; | 29 | int entry; |
30 | int master; | ||
31 | int header; | ||
30 | struct dlm_ls *ls; | 32 | struct dlm_ls *ls; |
31 | struct list_head *next; | 33 | struct list_head *next; |
32 | struct dlm_rsb *rsb; | 34 | struct dlm_rsb *rsb; |
@@ -86,6 +88,8 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s) | |||
86 | struct dlm_lkb *lkb; | 88 | struct dlm_lkb *lkb; |
87 | int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list; | 89 | int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list; |
88 | 90 | ||
91 | lock_rsb(res); | ||
92 | |||
89 | seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length); | 93 | seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length); |
90 | for (i = 0; i < res->res_length; i++) { | 94 | for (i = 0; i < res->res_length; i++) { |
91 | if (isprint(res->res_name[i])) | 95 | if (isprint(res->res_name[i])) |
@@ -152,6 +156,59 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s) | |||
152 | seq_printf(s, "\n"); | 156 | seq_printf(s, "\n"); |
153 | } | 157 | } |
154 | out: | 158 | out: |
159 | unlock_rsb(res); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static void print_master_lock(struct seq_file *s, struct dlm_lkb *lkb, | ||
164 | struct dlm_rsb *r) | ||
165 | { | ||
166 | struct dlm_user_args *ua; | ||
167 | unsigned int waiting = 0; | ||
168 | uint64_t xid = 0; | ||
169 | |||
170 | if (lkb->lkb_flags & DLM_IFL_USER) { | ||
171 | ua = (struct dlm_user_args *) lkb->lkb_astparam; | ||
172 | if (ua) | ||
173 | xid = ua->xid; | ||
174 | } | ||
175 | |||
176 | if (lkb->lkb_timestamp) | ||
177 | waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp); | ||
178 | |||
179 | /* id nodeid remid pid xid flags sts grmode rqmode time_ms len name */ | ||
180 | |||
181 | seq_printf(s, "%x %d %x %u %llu %x %d %d %d %u %d \"%s\"\n", | ||
182 | lkb->lkb_id, | ||
183 | lkb->lkb_nodeid, | ||
184 | lkb->lkb_remid, | ||
185 | lkb->lkb_ownpid, | ||
186 | (unsigned long long)xid, | ||
187 | lkb->lkb_exflags, | ||
188 | lkb->lkb_status, | ||
189 | lkb->lkb_grmode, | ||
190 | lkb->lkb_rqmode, | ||
191 | waiting, | ||
192 | r->res_length, | ||
193 | r->res_name); | ||
194 | } | ||
195 | |||
196 | static int print_master_resource(struct dlm_rsb *r, struct seq_file *s) | ||
197 | { | ||
198 | struct dlm_lkb *lkb; | ||
199 | |||
200 | lock_rsb(r); | ||
201 | |||
202 | list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) | ||
203 | print_master_lock(s, lkb, r); | ||
204 | |||
205 | list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) | ||
206 | print_master_lock(s, lkb, r); | ||
207 | |||
208 | list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) | ||
209 | print_master_lock(s, lkb, r); | ||
210 | |||
211 | unlock_rsb(r); | ||
155 | return 0; | 212 | return 0; |
156 | } | 213 | } |
157 | 214 | ||
@@ -209,7 +266,7 @@ static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls) | |||
209 | { | 266 | { |
210 | struct rsb_iter *ri; | 267 | struct rsb_iter *ri; |
211 | 268 | ||
212 | ri = kmalloc(sizeof *ri, GFP_KERNEL); | 269 | ri = kzalloc(sizeof *ri, GFP_KERNEL); |
213 | if (!ri) | 270 | if (!ri) |
214 | return NULL; | 271 | return NULL; |
215 | 272 | ||
@@ -267,7 +324,17 @@ static int rsb_seq_show(struct seq_file *file, void *iter_ptr) | |||
267 | { | 324 | { |
268 | struct rsb_iter *ri = iter_ptr; | 325 | struct rsb_iter *ri = iter_ptr; |
269 | 326 | ||
270 | print_resource(ri->rsb, file); | 327 | if (ri->master) { |
328 | if (ri->header) { | ||
329 | seq_printf(file, "id nodeid remid pid xid flags sts " | ||
330 | "grmode rqmode time_ms len name\n"); | ||
331 | ri->header = 0; | ||
332 | } | ||
333 | if (is_master(ri->rsb)) | ||
334 | print_master_resource(ri->rsb, file); | ||
335 | } else { | ||
336 | print_resource(ri->rsb, file); | ||
337 | } | ||
271 | 338 | ||
272 | return 0; | 339 | return 0; |
273 | } | 340 | } |
@@ -303,6 +370,83 @@ static const struct file_operations rsb_fops = { | |||
303 | }; | 370 | }; |
304 | 371 | ||
305 | /* | 372 | /* |
373 | * Dump master lock state | ||
374 | */ | ||
375 | |||
376 | static struct rsb_iter *master_iter_init(struct dlm_ls *ls, loff_t *pos) | ||
377 | { | ||
378 | struct rsb_iter *ri; | ||
379 | |||
380 | ri = kzalloc(sizeof *ri, GFP_KERNEL); | ||
381 | if (!ri) | ||
382 | return NULL; | ||
383 | |||
384 | ri->ls = ls; | ||
385 | ri->entry = 0; | ||
386 | ri->next = NULL; | ||
387 | ri->master = 1; | ||
388 | |||
389 | if (*pos == 0) | ||
390 | ri->header = 1; | ||
391 | |||
392 | if (rsb_iter_next(ri)) { | ||
393 | rsb_iter_free(ri); | ||
394 | return NULL; | ||
395 | } | ||
396 | |||
397 | return ri; | ||
398 | } | ||
399 | |||
400 | static void *master_seq_start(struct seq_file *file, loff_t *pos) | ||
401 | { | ||
402 | struct rsb_iter *ri; | ||
403 | loff_t n = *pos; | ||
404 | |||
405 | ri = master_iter_init(file->private, pos); | ||
406 | if (!ri) | ||
407 | return NULL; | ||
408 | |||
409 | while (n--) { | ||
410 | if (rsb_iter_next(ri)) { | ||
411 | rsb_iter_free(ri); | ||
412 | return NULL; | ||
413 | } | ||
414 | } | ||
415 | |||
416 | return ri; | ||
417 | } | ||
418 | |||
419 | static struct seq_operations master_seq_ops = { | ||
420 | .start = master_seq_start, | ||
421 | .next = rsb_seq_next, | ||
422 | .stop = rsb_seq_stop, | ||
423 | .show = rsb_seq_show, | ||
424 | }; | ||
425 | |||
426 | static int master_open(struct inode *inode, struct file *file) | ||
427 | { | ||
428 | struct seq_file *seq; | ||
429 | int ret; | ||
430 | |||
431 | ret = seq_open(file, &master_seq_ops); | ||
432 | if (ret) | ||
433 | return ret; | ||
434 | |||
435 | seq = file->private_data; | ||
436 | seq->private = inode->i_private; | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static const struct file_operations master_fops = { | ||
442 | .owner = THIS_MODULE, | ||
443 | .open = master_open, | ||
444 | .read = seq_read, | ||
445 | .llseek = seq_lseek, | ||
446 | .release = seq_release | ||
447 | }; | ||
448 | |||
449 | /* | ||
306 | * dump lkb's on the ls_waiters list | 450 | * dump lkb's on the ls_waiters list |
307 | */ | 451 | */ |
308 | 452 | ||
@@ -369,6 +513,20 @@ int dlm_create_debug_file(struct dlm_ls *ls) | |||
369 | return -ENOMEM; | 513 | return -ENOMEM; |
370 | } | 514 | } |
371 | 515 | ||
516 | memset(name, 0, sizeof(name)); | ||
517 | snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_master", ls->ls_name); | ||
518 | |||
519 | ls->ls_debug_master_dentry = debugfs_create_file(name, | ||
520 | S_IFREG | S_IRUGO, | ||
521 | dlm_root, | ||
522 | ls, | ||
523 | &master_fops); | ||
524 | if (!ls->ls_debug_master_dentry) { | ||
525 | debugfs_remove(ls->ls_debug_waiters_dentry); | ||
526 | debugfs_remove(ls->ls_debug_rsb_dentry); | ||
527 | return -ENOMEM; | ||
528 | } | ||
529 | |||
372 | return 0; | 530 | return 0; |
373 | } | 531 | } |
374 | 532 | ||
@@ -378,6 +536,8 @@ void dlm_delete_debug_file(struct dlm_ls *ls) | |||
378 | debugfs_remove(ls->ls_debug_rsb_dentry); | 536 | debugfs_remove(ls->ls_debug_rsb_dentry); |
379 | if (ls->ls_debug_waiters_dentry) | 537 | if (ls->ls_debug_waiters_dentry) |
380 | debugfs_remove(ls->ls_debug_waiters_dentry); | 538 | debugfs_remove(ls->ls_debug_waiters_dentry); |
539 | if (ls->ls_debug_master_dentry) | ||
540 | debugfs_remove(ls->ls_debug_master_dentry); | ||
381 | } | 541 | } |
382 | 542 | ||
383 | int dlm_register_debugfs(void) | 543 | int dlm_register_debugfs(void) |
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index a006fa59e7da..f2c85493c0c6 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -470,6 +470,7 @@ struct dlm_ls { | |||
470 | 470 | ||
471 | struct dentry *ls_debug_rsb_dentry; /* debugfs */ | 471 | struct dentry *ls_debug_rsb_dentry; /* debugfs */ |
472 | struct dentry *ls_debug_waiters_dentry; /* debugfs */ | 472 | struct dentry *ls_debug_waiters_dentry; /* debugfs */ |
473 | struct dentry *ls_debug_master_dentry; /* debugfs */ | ||
473 | 474 | ||
474 | wait_queue_head_t ls_uevent_wait; /* user part of join/leave */ | 475 | wait_queue_head_t ls_uevent_wait; /* user part of join/leave */ |
475 | int ls_uevent_result; | 476 | int ls_uevent_result; |