aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm/debug_fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dlm/debug_fs.c')
-rw-r--r--fs/dlm/debug_fs.c186
1 files changed, 178 insertions, 8 deletions
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 61ba670b9e02..12c3bfd5e660 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -17,6 +17,7 @@
17#include <linux/debugfs.h> 17#include <linux/debugfs.h>
18 18
19#include "dlm_internal.h" 19#include "dlm_internal.h"
20#include "lock.h"
20 21
21#define DLM_DEBUG_BUF_LEN 4096 22#define DLM_DEBUG_BUF_LEN 4096
22static char debug_buf[DLM_DEBUG_BUF_LEN]; 23static char debug_buf[DLM_DEBUG_BUF_LEN];
@@ -26,6 +27,8 @@ static struct dentry *dlm_root;
26 27
27struct rsb_iter { 28struct rsb_iter {
28 int entry; 29 int entry;
30 int locks;
31 int header;
29 struct dlm_ls *ls; 32 struct dlm_ls *ls;
30 struct list_head *next; 33 struct list_head *next;
31 struct dlm_rsb *rsb; 34 struct dlm_rsb *rsb;
@@ -57,8 +60,8 @@ static char *print_lockmode(int mode)
57 } 60 }
58} 61}
59 62
60static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, 63static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
61 struct dlm_rsb *res) 64 struct dlm_rsb *res)
62{ 65{
63 seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode)); 66 seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
64 67
@@ -85,6 +88,8 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
85 struct dlm_lkb *lkb; 88 struct dlm_lkb *lkb;
86 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;
87 90
91 lock_rsb(res);
92
88 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);
89 for (i = 0; i < res->res_length; i++) { 94 for (i = 0; i < res->res_length; i++) {
90 if (isprint(res->res_name[i])) 95 if (isprint(res->res_name[i]))
@@ -129,15 +134,15 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
129 /* Print the locks attached to this resource */ 134 /* Print the locks attached to this resource */
130 seq_printf(s, "Granted Queue\n"); 135 seq_printf(s, "Granted Queue\n");
131 list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) 136 list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
132 print_lock(s, lkb, res); 137 print_resource_lock(s, lkb, res);
133 138
134 seq_printf(s, "Conversion Queue\n"); 139 seq_printf(s, "Conversion Queue\n");
135 list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) 140 list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
136 print_lock(s, lkb, res); 141 print_resource_lock(s, lkb, res);
137 142
138 seq_printf(s, "Waiting Queue\n"); 143 seq_printf(s, "Waiting Queue\n");
139 list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) 144 list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
140 print_lock(s, lkb, res); 145 print_resource_lock(s, lkb, res);
141 146
142 if (list_empty(&res->res_lookup)) 147 if (list_empty(&res->res_lookup))
143 goto out; 148 goto out;
@@ -151,6 +156,61 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
151 seq_printf(s, "\n"); 156 seq_printf(s, "\n");
152 } 157 }
153 out: 158 out:
159 unlock_rsb(res);
160 return 0;
161}
162
163static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r)
164{
165 struct dlm_user_args *ua;
166 unsigned int waiting = 0;
167 uint64_t xid = 0;
168
169 if (lkb->lkb_flags & DLM_IFL_USER) {
170 ua = (struct dlm_user_args *) lkb->lkb_astparam;
171 if (ua)
172 xid = ua->xid;
173 }
174
175 if (lkb->lkb_timestamp)
176 waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp);
177
178 /* id nodeid remid pid xid exflags flags sts grmode rqmode time_ms
179 r_nodeid r_len r_name */
180
181 seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %u %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_flags,
189 lkb->lkb_status,
190 lkb->lkb_grmode,
191 lkb->lkb_rqmode,
192 waiting,
193 r->res_nodeid,
194 r->res_length,
195 r->res_name);
196}
197
198static int print_locks(struct dlm_rsb *r, struct seq_file *s)
199{
200 struct dlm_lkb *lkb;
201
202 lock_rsb(r);
203
204 list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
205 print_lock(s, lkb, r);
206
207 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
208 print_lock(s, lkb, r);
209
210 list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
211 print_lock(s, lkb, r);
212
213 unlock_rsb(r);
154 return 0; 214 return 0;
155} 215}
156 216
@@ -166,6 +226,9 @@ static int rsb_iter_next(struct rsb_iter *ri)
166 read_lock(&ls->ls_rsbtbl[i].lock); 226 read_lock(&ls->ls_rsbtbl[i].lock);
167 if (!list_empty(&ls->ls_rsbtbl[i].list)) { 227 if (!list_empty(&ls->ls_rsbtbl[i].list)) {
168 ri->next = ls->ls_rsbtbl[i].list.next; 228 ri->next = ls->ls_rsbtbl[i].list.next;
229 ri->rsb = list_entry(ri->next, struct dlm_rsb,
230 res_hashchain);
231 dlm_hold_rsb(ri->rsb);
169 read_unlock(&ls->ls_rsbtbl[i].lock); 232 read_unlock(&ls->ls_rsbtbl[i].lock);
170 break; 233 break;
171 } 234 }
@@ -176,6 +239,7 @@ static int rsb_iter_next(struct rsb_iter *ri)
176 if (ri->entry >= ls->ls_rsbtbl_size) 239 if (ri->entry >= ls->ls_rsbtbl_size)
177 return 1; 240 return 1;
178 } else { 241 } else {
242 struct dlm_rsb *old = ri->rsb;
179 i = ri->entry; 243 i = ri->entry;
180 read_lock(&ls->ls_rsbtbl[i].lock); 244 read_lock(&ls->ls_rsbtbl[i].lock);
181 ri->next = ri->next->next; 245 ri->next = ri->next->next;
@@ -184,11 +248,14 @@ static int rsb_iter_next(struct rsb_iter *ri)
184 ri->next = NULL; 248 ri->next = NULL;
185 ri->entry++; 249 ri->entry++;
186 read_unlock(&ls->ls_rsbtbl[i].lock); 250 read_unlock(&ls->ls_rsbtbl[i].lock);
251 dlm_put_rsb(old);
187 goto top; 252 goto top;
188 } 253 }
254 ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
255 dlm_hold_rsb(ri->rsb);
189 read_unlock(&ls->ls_rsbtbl[i].lock); 256 read_unlock(&ls->ls_rsbtbl[i].lock);
257 dlm_put_rsb(old);
190 } 258 }
191 ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
192 259
193 return 0; 260 return 0;
194} 261}
@@ -202,7 +269,7 @@ static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
202{ 269{
203 struct rsb_iter *ri; 270 struct rsb_iter *ri;
204 271
205 ri = kmalloc(sizeof *ri, GFP_KERNEL); 272 ri = kzalloc(sizeof *ri, GFP_KERNEL);
206 if (!ri) 273 if (!ri)
207 return NULL; 274 return NULL;
208 275
@@ -260,7 +327,17 @@ static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
260{ 327{
261 struct rsb_iter *ri = iter_ptr; 328 struct rsb_iter *ri = iter_ptr;
262 329
263 print_resource(ri->rsb, file); 330 if (ri->locks) {
331 if (ri->header) {
332 seq_printf(file, "id nodeid remid pid xid exflags flags "
333 "sts grmode rqmode time_ms r_nodeid "
334 "r_len r_name\n");
335 ri->header = 0;
336 }
337 print_locks(ri->rsb, file);
338 } else {
339 print_resource(ri->rsb, file);
340 }
264 341
265 return 0; 342 return 0;
266} 343}
@@ -296,6 +373,83 @@ static const struct file_operations rsb_fops = {
296}; 373};
297 374
298/* 375/*
376 * Dump state in compact per-lock listing
377 */
378
379static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
380{
381 struct rsb_iter *ri;
382
383 ri = kzalloc(sizeof *ri, GFP_KERNEL);
384 if (!ri)
385 return NULL;
386
387 ri->ls = ls;
388 ri->entry = 0;
389 ri->next = NULL;
390 ri->locks = 1;
391
392 if (*pos == 0)
393 ri->header = 1;
394
395 if (rsb_iter_next(ri)) {
396 rsb_iter_free(ri);
397 return NULL;
398 }
399
400 return ri;
401}
402
403static void *locks_seq_start(struct seq_file *file, loff_t *pos)
404{
405 struct rsb_iter *ri;
406 loff_t n = *pos;
407
408 ri = locks_iter_init(file->private, pos);
409 if (!ri)
410 return NULL;
411
412 while (n--) {
413 if (rsb_iter_next(ri)) {
414 rsb_iter_free(ri);
415 return NULL;
416 }
417 }
418
419 return ri;
420}
421
422static struct seq_operations locks_seq_ops = {
423 .start = locks_seq_start,
424 .next = rsb_seq_next,
425 .stop = rsb_seq_stop,
426 .show = rsb_seq_show,
427};
428
429static int locks_open(struct inode *inode, struct file *file)
430{
431 struct seq_file *seq;
432 int ret;
433
434 ret = seq_open(file, &locks_seq_ops);
435 if (ret)
436 return ret;
437
438 seq = file->private_data;
439 seq->private = inode->i_private;
440
441 return 0;
442}
443
444static const struct file_operations locks_fops = {
445 .owner = THIS_MODULE,
446 .open = locks_open,
447 .read = seq_read,
448 .llseek = seq_lseek,
449 .release = seq_release
450};
451
452/*
299 * dump lkb's on the ls_waiters list 453 * dump lkb's on the ls_waiters list
300 */ 454 */
301 455
@@ -362,6 +516,20 @@ int dlm_create_debug_file(struct dlm_ls *ls)
362 return -ENOMEM; 516 return -ENOMEM;
363 } 517 }
364 518
519 memset(name, 0, sizeof(name));
520 snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
521
522 ls->ls_debug_locks_dentry = debugfs_create_file(name,
523 S_IFREG | S_IRUGO,
524 dlm_root,
525 ls,
526 &locks_fops);
527 if (!ls->ls_debug_locks_dentry) {
528 debugfs_remove(ls->ls_debug_waiters_dentry);
529 debugfs_remove(ls->ls_debug_rsb_dentry);
530 return -ENOMEM;
531 }
532
365 return 0; 533 return 0;
366} 534}
367 535
@@ -371,6 +539,8 @@ void dlm_delete_debug_file(struct dlm_ls *ls)
371 debugfs_remove(ls->ls_debug_rsb_dentry); 539 debugfs_remove(ls->ls_debug_rsb_dentry);
372 if (ls->ls_debug_waiters_dentry) 540 if (ls->ls_debug_waiters_dentry)
373 debugfs_remove(ls->ls_debug_waiters_dentry); 541 debugfs_remove(ls->ls_debug_waiters_dentry);
542 if (ls->ls_debug_locks_dentry)
543 debugfs_remove(ls->ls_debug_locks_dentry);
374} 544}
375 545
376int dlm_register_debugfs(void) 546int dlm_register_debugfs(void)