aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2007-05-29 09:47:04 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-07-09 03:22:56 -0400
commit9dd592d70be0db6fa8e4e19d7642cfaa424b200e (patch)
tree6694d26986949a0bc8aac3895c7b61f94af97452
parent8b4021fa436f7c76a2299e6d85d4d4a619724e9a (diff)
[DLM] dumping master locks
Add a new debugfs file that dumps a compact list of mastered locks. This will be used by a userland daemon to collect state for deadlock detection. Also, for the existing function that prints all lock state, lock the rsb before going through the lock lists since they can be changing in the course of normal dlm activity. Signed-off-by: David Teigland <teigland@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/dlm/debug_fs.c164
-rw-r--r--fs/dlm/dlm_internal.h1
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
28struct rsb_iter { 28struct 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
163static 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
196static 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
376static 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
400static 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
419static 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
426static 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
441static 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
383int dlm_register_debugfs(void) 543int 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;