1 From: David Teigland <teigland@redhat.com>
2 commit 892c4467e335e9050c95e0d8409c136c4dadaca2
3 Author: David Teigland <teigland@redhat.com>
4 Date: Wed Jan 7 16:48:52 2009 -0600
5 Subject: dlm: fix seq_file usage in debugfs lock dump
7 The old code would leak iterators and leave reference counts on
8 rsbs because it was ignoring the "stop" seq callback. The code
9 followed an example that used the seq operations differently.
10 This new code is based on actually understanding how the seq
11 operations work. It also improves things by saving the hash bucket
12 in the position to avoid cycling through completed buckets in start.
14 Siged-off-by: Davd Teigland <teigland@redhat.com>
15 Signed-off-by: Coly Li <coly.li@suse.de>
17 diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
18 index 2f107d1..bc4af3e 100644
19 --- a/fs/dlm/debug_fs.c
20 +++ b/fs/dlm/debug_fs.c
22 /******************************************************************************
23 *******************************************************************************
25 -** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
26 +** Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved.
28 ** This copyrighted material is made available to anyone wishing to use,
29 ** modify, copy, or redistribute it subject to the terms and conditions
30 @@ -25,19 +25,6 @@ static struct mutex debug_buf_lock;
32 static struct dentry *dlm_root;
39 - struct list_head *next;
40 - struct dlm_rsb *rsb;
44 - * dump all rsb's in the lockspace hash table
47 static char *print_lockmode(int mode)
50 @@ -60,13 +47,13 @@ static char *print_lockmode(int mode)
54 -static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
55 - struct dlm_rsb *res)
56 +static int print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
57 + struct dlm_rsb *res)
59 seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
61 - if (lkb->lkb_status == DLM_LKSTS_CONVERT
62 - || lkb->lkb_status == DLM_LKSTS_WAITING)
63 + if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
64 + lkb->lkb_status == DLM_LKSTS_WAITING)
65 seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
67 if (lkb->lkb_nodeid) {
68 @@ -80,33 +67,42 @@ static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
69 if (lkb->lkb_wait_type)
70 seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
72 - seq_printf(s, "\n");
73 + return seq_printf(s, "\n");
76 static int print_format1(struct dlm_rsb *res, struct seq_file *s)
79 int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
84 - seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
85 + rv = seq_printf(s, "\nResource %p Name (len=%d) \"",
86 + res, res->res_length);
90 for (i = 0; i < res->res_length; i++) {
91 if (isprint(res->res_name[i]))
92 seq_printf(s, "%c", res->res_name[i]);
94 seq_printf(s, "%c", '.');
97 if (res->res_nodeid > 0)
98 - seq_printf(s, "\" \nLocal Copy, Master is node %d\n",
100 + rv = seq_printf(s, "\" \nLocal Copy, Master is node %d\n",
102 else if (res->res_nodeid == 0)
103 - seq_printf(s, "\" \nMaster Copy\n");
104 + rv = seq_printf(s, "\" \nMaster Copy\n");
105 else if (res->res_nodeid == -1)
106 - seq_printf(s, "\" \nLooking up master (lkid %x)\n",
107 - res->res_first_lkid);
108 + rv = seq_printf(s, "\" \nLooking up master (lkid %x)\n",
109 + res->res_first_lkid);
111 - seq_printf(s, "\" \nInvalid master %d\n", res->res_nodeid);
112 + rv = seq_printf(s, "\" \nInvalid master %d\n",
118 if (res->res_lvbptr) {
119 @@ -119,52 +115,66 @@ static int print_format1(struct dlm_rsb *res, struct seq_file *s)
121 if (rsb_flag(res, RSB_VALNOTVALID))
122 seq_printf(s, " (INVALID)");
123 - seq_printf(s, "\n");
124 + rv = seq_printf(s, "\n");
129 root_list = !list_empty(&res->res_root_list);
130 recover_list = !list_empty(&res->res_recover_list);
132 if (root_list || recover_list) {
133 - seq_printf(s, "Recovery: root %d recover %d flags %lx "
134 - "count %d\n", root_list, recover_list,
135 - res->res_flags, res->res_recover_locks_count);
136 + rv = seq_printf(s, "Recovery: root %d recover %d flags %lx "
137 + "count %d\n", root_list, recover_list,
138 + res->res_flags, res->res_recover_locks_count);
143 /* Print the locks attached to this resource */
144 seq_printf(s, "Granted Queue\n");
145 - list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
146 - print_format1_lock(s, lkb, res);
147 + list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
148 + rv = print_format1_lock(s, lkb, res);
153 seq_printf(s, "Conversion Queue\n");
154 - list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
155 - print_format1_lock(s, lkb, res);
156 + list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
157 + rv = print_format1_lock(s, lkb, res);
162 seq_printf(s, "Waiting Queue\n");
163 - list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
164 - print_format1_lock(s, lkb, res);
165 + list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
166 + rv = print_format1_lock(s, lkb, res);
171 if (list_empty(&res->res_lookup))
174 seq_printf(s, "Lookup Queue\n");
175 list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
176 - seq_printf(s, "%08x %s", lkb->lkb_id,
177 - print_lockmode(lkb->lkb_rqmode));
178 + rv = seq_printf(s, "%08x %s", lkb->lkb_id,
179 + print_lockmode(lkb->lkb_rqmode));
180 if (lkb->lkb_wait_type)
181 seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
182 - seq_printf(s, "\n");
183 + rv = seq_printf(s, "\n");
191 -static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
193 +static int print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
200 if (lkb->lkb_flags & DLM_IFL_USER) {
202 @@ -177,69 +187,82 @@ static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
203 /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
204 r_nodeid r_len r_name */
206 - seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
211 - (unsigned long long)xid,
217 - (unsigned long long)us,
221 + rv = seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
226 + (unsigned long long)xid,
232 + (unsigned long long)us,
239 static int print_format2(struct dlm_rsb *r, struct seq_file *s)
246 - list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
247 - print_format2_lock(s, lkb, r);
249 - list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
250 - print_format2_lock(s, lkb, r);
251 + list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
252 + rv = print_format2_lock(s, lkb, r);
257 - list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
258 - print_format2_lock(s, lkb, r);
259 + list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
260 + rv = print_format2_lock(s, lkb, r);
265 + list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
266 + rv = print_format2_lock(s, lkb, r);
276 -static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
278 +static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
284 if (lkb->lkb_flags & DLM_IFL_USER) {
286 xid = lkb->lkb_ua->xid;
289 - seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
294 - (unsigned long long)xid,
302 - lkb->lkb_wait_type,
304 - (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
305 - (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
306 + rv = seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
311 + (unsigned long long)xid,
319 + lkb->lkb_wait_type,
321 + (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
322 + (unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
326 static int print_format3(struct dlm_rsb *r, struct seq_file *s)
327 @@ -247,18 +270,21 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
329 int i, lvblen = r->res_ls->ls_lvblen;
335 - seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
340 - !list_empty(&r->res_root_list),
341 - !list_empty(&r->res_recover_list),
342 - r->res_recover_locks_count,
344 + rv = seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
349 + !list_empty(&r->res_root_list),
350 + !list_empty(&r->res_recover_list),
351 + r->res_recover_locks_count,
356 for (i = 0; i < r->res_length; i++) {
357 if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
358 @@ -273,7 +299,9 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
360 seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
362 - seq_printf(s, "\n");
363 + rv = seq_printf(s, "\n");
369 @@ -282,344 +310,294 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
371 for (i = 0; i < lvblen; i++)
372 seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
373 - seq_printf(s, "\n");
374 + rv = seq_printf(s, "\n");
379 - list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
380 - print_format3_lock(s, lkb, 0);
382 - list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
383 - print_format3_lock(s, lkb, 0);
385 - list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
386 - print_format3_lock(s, lkb, 0);
388 - list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup)
389 - print_format3_lock(s, lkb, 1);
395 -static int rsb_iter_next(struct rsb_iter *ri)
397 - struct dlm_ls *ls = ri->ls;
402 - /* Find the next non-empty hash bucket */
403 - for (i = ri->entry; i < ls->ls_rsbtbl_size; i++) {
404 - read_lock(&ls->ls_rsbtbl[i].lock);
405 - if (!list_empty(&ls->ls_rsbtbl[i].list)) {
406 - ri->next = ls->ls_rsbtbl[i].list.next;
407 - ri->rsb = list_entry(ri->next, struct dlm_rsb,
409 - dlm_hold_rsb(ri->rsb);
410 - read_unlock(&ls->ls_rsbtbl[i].lock);
413 - read_unlock(&ls->ls_rsbtbl[i].lock);
417 - if (ri->entry >= ls->ls_rsbtbl_size)
420 - struct dlm_rsb *old = ri->rsb;
422 - read_lock(&ls->ls_rsbtbl[i].lock);
423 - ri->next = ri->next->next;
424 - if (ri->next->next == ls->ls_rsbtbl[i].list.next) {
425 - /* End of list - move to next bucket */
428 - read_unlock(&ls->ls_rsbtbl[i].lock);
432 - ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
433 - dlm_hold_rsb(ri->rsb);
434 - read_unlock(&ls->ls_rsbtbl[i].lock);
436 + list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
437 + rv = print_format3_lock(s, lkb, 0);
445 -static void rsb_iter_free(struct rsb_iter *ri)
450 -static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
452 - struct rsb_iter *ri;
454 - ri = kzalloc(sizeof *ri, GFP_KERNEL);
463 - if (rsb_iter_next(ri)) {
466 + list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
467 + rv = print_format3_lock(s, lkb, 0);
475 -static void *rsb_seq_start(struct seq_file *file, loff_t *pos)
477 - struct rsb_iter *ri;
480 - ri = rsb_iter_init(file->private);
485 - if (rsb_iter_next(ri)) {
489 + list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
490 + rv = print_format3_lock(s, lkb, 0);
498 -static void *rsb_seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos)
500 - struct rsb_iter *ri = iter_ptr;
504 - if (rsb_iter_next(ri)) {
507 + list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
508 + rv = print_format3_lock(s, lkb, 1);
519 -static void rsb_seq_stop(struct seq_file *file, void *iter_ptr)
521 - /* nothing for now */
523 +struct rsbtbl_iter {
524 + struct dlm_rsb *rsb;
530 -static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
531 +/* seq_printf returns -1 if the buffer is full, and 0 otherwise.
532 + If the buffer is full, seq_printf can be called again, but it
533 + does nothing and just returns -1. So, the these printing routines
534 + periodically check the return value to avoid wasting too much time
535 + trying to print to a full buffer. */
537 +static int table_seq_show(struct seq_file *seq, void *iter_ptr)
539 - struct rsb_iter *ri = iter_ptr;
540 + struct rsbtbl_iter *ri = iter_ptr;
543 switch (ri->format) {
545 - print_format1(ri->rsb, file);
546 + rv = print_format1(ri->rsb, seq);
550 - seq_printf(file, "id nodeid remid pid xid exflags "
551 - "flags sts grmode rqmode time_ms "
552 - "r_nodeid r_len r_name\n");
553 + seq_printf(seq, "id nodeid remid pid xid exflags "
554 + "flags sts grmode rqmode time_ms "
555 + "r_nodeid r_len r_name\n");
558 - print_format2(ri->rsb, file);
559 + rv = print_format2(ri->rsb, seq);
563 - seq_printf(file, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
564 + seq_printf(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
567 - print_format3(ri->rsb, file);
568 + rv = print_format3(ri->rsb, seq);
576 -static struct seq_operations rsb_seq_ops = {
577 - .start = rsb_seq_start,
578 - .next = rsb_seq_next,
579 - .stop = rsb_seq_stop,
580 - .show = rsb_seq_show,
582 +static struct seq_operations format1_seq_ops;
583 +static struct seq_operations format2_seq_ops;
584 +static struct seq_operations format3_seq_ops;
586 -static int rsb_open(struct inode *inode, struct file *file)
587 +static void *table_seq_start(struct seq_file *seq, loff_t *pos)
589 - struct seq_file *seq;
592 - ret = seq_open(file, &rsb_seq_ops);
596 - seq = file->private_data;
597 - seq->private = inode->i_private;
602 -static const struct file_operations rsb_fops = {
603 - .owner = THIS_MODULE,
606 - .llseek = seq_lseek,
607 - .release = seq_release
609 + struct dlm_ls *ls = seq->private;
610 + struct rsbtbl_iter *ri;
613 + unsigned bucket, entry;
616 - * Dump state in compact per-lock listing
619 + entry = n & ((1LL << 32) - 1);
621 -static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
623 - struct rsb_iter *ri;
624 + if (bucket >= ls->ls_rsbtbl_size)
627 - ri = kzalloc(sizeof *ri, GFP_KERNEL);
628 + ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_KERNEL);
641 - if (rsb_iter_next(ri)) {
644 + if (seq->op == &format1_seq_ops)
646 + if (seq->op == &format2_seq_ops)
648 + if (seq->op == &format3_seq_ops)
651 + read_lock(&ls->ls_rsbtbl[bucket].lock);
652 + if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
653 + list_for_each_entry(r, &ls->ls_rsbtbl[bucket].list,
658 + ri->bucket = bucket;
659 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
664 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
669 + * move to the first rsb in the next non-empty bucket
672 -static void *locks_seq_start(struct seq_file *file, loff_t *pos)
674 - struct rsb_iter *ri;
676 + /* zero the entry */
677 + n &= ~((1LL << 32) - 1);
679 - ri = locks_iter_init(file->private, pos);
687 - if (rsb_iter_next(ri)) {
689 + if (bucket >= ls->ls_rsbtbl_size) {
696 + read_lock(&ls->ls_rsbtbl[bucket].lock);
697 + if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
698 + r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
699 + struct dlm_rsb, res_hashchain);
702 + ri->bucket = bucket;
703 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
707 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
711 -static struct seq_operations locks_seq_ops = {
712 - .start = locks_seq_start,
713 - .next = rsb_seq_next,
714 - .stop = rsb_seq_stop,
715 - .show = rsb_seq_show,
718 -static int locks_open(struct inode *inode, struct file *file)
719 +static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
721 - struct seq_file *seq;
724 - ret = seq_open(file, &locks_seq_ops);
728 - seq = file->private_data;
729 - seq->private = inode->i_private;
734 -static const struct file_operations locks_fops = {
735 - .owner = THIS_MODULE,
736 - .open = locks_open,
738 - .llseek = seq_lseek,
739 - .release = seq_release
743 - * Dump all rsb/lvb/lkb state in compact listing, more complete than _locks
744 - * This can replace both formats 1 and 2 eventually.
746 + struct dlm_ls *ls = seq->private;
747 + struct rsbtbl_iter *ri = iter_ptr;
748 + struct list_head *next;
749 + struct dlm_rsb *r, *rp;
756 + * move to the next rsb in the same bucket
759 + read_lock(&ls->ls_rsbtbl[bucket].lock);
761 + next = rp->res_hashchain.next;
763 + if (next != &ls->ls_rsbtbl[bucket].list) {
764 + r = list_entry(next, struct dlm_rsb, res_hashchain);
767 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
772 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
775 -static struct rsb_iter *all_iter_init(struct dlm_ls *ls, loff_t *pos)
777 - struct rsb_iter *ri;
779 + * move to the first rsb in the next non-empty bucket
782 - ri = kzalloc(sizeof *ri, GFP_KERNEL);
785 + /* zero the entry */
786 + n &= ~((1LL << 32) - 1);
798 + if (bucket >= ls->ls_rsbtbl_size) {
803 - if (rsb_iter_next(ri)) {
806 + read_lock(&ls->ls_rsbtbl[bucket].lock);
807 + if (!list_empty(&ls->ls_rsbtbl[bucket].list)) {
808 + r = list_first_entry(&ls->ls_rsbtbl[bucket].list,
809 + struct dlm_rsb, res_hashchain);
812 + ri->bucket = bucket;
813 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
817 + read_unlock(&ls->ls_rsbtbl[bucket].lock);
823 -static void *all_seq_start(struct seq_file *file, loff_t *pos)
824 +static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
826 - struct rsb_iter *ri;
829 - ri = all_iter_init(file->private, pos);
832 + struct rsbtbl_iter *ri = iter_ptr;
835 - if (rsb_iter_next(ri)) {
840 + dlm_put_rsb(ri->rsb);
847 -static struct seq_operations all_seq_ops = {
848 - .start = all_seq_start,
849 - .next = rsb_seq_next,
850 - .stop = rsb_seq_stop,
851 - .show = rsb_seq_show,
852 +static struct seq_operations format1_seq_ops = {
853 + .start = table_seq_start,
854 + .next = table_seq_next,
855 + .stop = table_seq_stop,
856 + .show = table_seq_show,
859 -static int all_open(struct inode *inode, struct file *file)
860 +static struct seq_operations format2_seq_ops = {
861 + .start = table_seq_start,
862 + .next = table_seq_next,
863 + .stop = table_seq_stop,
864 + .show = table_seq_show,
867 +static struct seq_operations format3_seq_ops = {
868 + .start = table_seq_start,
869 + .next = table_seq_next,
870 + .stop = table_seq_stop,
871 + .show = table_seq_show,
874 +static const struct file_operations format1_fops;
875 +static const struct file_operations format2_fops;
876 +static const struct file_operations format3_fops;
878 +static int table_open(struct inode *inode, struct file *file)
880 struct seq_file *seq;
884 + if (file->f_op == &format1_fops)
885 + ret = seq_open(file, &format1_seq_ops);
886 + else if (file->f_op == &format2_fops)
887 + ret = seq_open(file, &format2_seq_ops);
888 + else if (file->f_op == &format3_fops)
889 + ret = seq_open(file, &format3_seq_ops);
891 - ret = seq_open(file, &all_seq_ops);
895 seq = file->private_data;
896 - seq->private = inode->i_private;
898 + seq->private = inode->i_private; /* the dlm_ls */
902 -static const struct file_operations all_fops = {
903 +static const struct file_operations format1_fops = {
904 + .owner = THIS_MODULE,
905 + .open = table_open,
907 + .llseek = seq_lseek,
908 + .release = seq_release
911 +static const struct file_operations format2_fops = {
912 + .owner = THIS_MODULE,
913 + .open = table_open,
915 + .llseek = seq_lseek,
916 + .release = seq_release
919 +static const struct file_operations format3_fops = {
920 .owner = THIS_MODULE,
922 + .open = table_open,
925 .release = seq_release
926 @@ -689,7 +667,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
932 if (!ls->ls_debug_rsb_dentry)
935 @@ -702,7 +680,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
941 if (!ls->ls_debug_locks_dentry)
944 @@ -715,7 +693,7 @@ int dlm_create_debug_file(struct dlm_ls *ls)
950 if (!ls->ls_debug_all_dentry)