debug_fs.c 18.3 KB
Newer Older
1 2 3
/******************************************************************************
*******************************************************************************
**
4
**  Copyright (C) 2005-2009 Red Hat, Inc.  All rights reserved.
5 6 7 8 9 10 11 12 13 14 15 16 17
**
**  This copyrighted material is made available to anyone wishing to use,
**  modify, copy, or redistribute it subject to the terms and conditions
**  of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/

#include <linux/pagemap.h>
#include <linux/seq_file.h>
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
18
#include <linux/slab.h>
19 20

#include "dlm_internal.h"
21
#include "lock.h"
22

D
David Teigland 已提交
23 24 25
#define DLM_DEBUG_BUF_LEN 4096
static char debug_buf[DLM_DEBUG_BUF_LEN];
static struct mutex debug_buf_lock;
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

static struct dentry *dlm_root;

static char *print_lockmode(int mode)
{
	switch (mode) {
	case DLM_LOCK_IV:
		return "--";
	case DLM_LOCK_NL:
		return "NL";
	case DLM_LOCK_CR:
		return "CR";
	case DLM_LOCK_CW:
		return "CW";
	case DLM_LOCK_PR:
		return "PR";
	case DLM_LOCK_PW:
		return "PW";
	case DLM_LOCK_EX:
		return "EX";
	default:
		return "??";
	}
}

51 52
static int print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
			      struct dlm_rsb *res)
53 54 55
{
	seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));

56 57
	if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
	    lkb->lkb_status == DLM_LKSTS_WAITING)
58 59 60 61 62 63 64 65 66 67 68 69 70
		seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));

	if (lkb->lkb_nodeid) {
		if (lkb->lkb_nodeid != res->res_nodeid)
			seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid,
				   lkb->lkb_remid);
		else
			seq_printf(s, " Master:     %08x", lkb->lkb_remid);
	}

	if (lkb->lkb_wait_type)
		seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);

71
	return seq_puts(s, "\n");
72 73
}

D
David Teigland 已提交
74
static int print_format1(struct dlm_rsb *res, struct seq_file *s)
75 76
{
	struct dlm_lkb *lkb;
D
David Teigland 已提交
77
	int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
78
	int rv;
79

D
David Teigland 已提交
80 81
	lock_rsb(res);

82 83 84 85 86
	rv = seq_printf(s, "\nResource %p Name (len=%d) \"",
			res, res->res_length);
	if (rv)
		goto out;

87 88 89 90 91 92
	for (i = 0; i < res->res_length; i++) {
		if (isprint(res->res_name[i]))
			seq_printf(s, "%c", res->res_name[i]);
		else
			seq_printf(s, "%c", '.');
	}
93

94
	if (res->res_nodeid > 0)
95
		rv = seq_printf(s, "\"\nLocal Copy, Master is node %d\n",
96
				res->res_nodeid);
97
	else if (res->res_nodeid == 0)
98
		rv = seq_puts(s, "\"\nMaster Copy\n");
99
	else if (res->res_nodeid == -1)
100
		rv = seq_printf(s, "\"\nLooking up master (lkid %x)\n",
101
			   	res->res_first_lkid);
102
	else
103
		rv = seq_printf(s, "\"\nInvalid master %d\n",
104 105 106
				res->res_nodeid);
	if (rv)
		goto out;
107 108 109

	/* Print the LVB: */
	if (res->res_lvbptr) {
110
		seq_puts(s, "LVB: ");
111 112
		for (i = 0; i < lvblen; i++) {
			if (i == lvblen / 2)
113
				seq_puts(s, "\n     ");
114 115 116 117
			seq_printf(s, "%02x ",
				   (unsigned char) res->res_lvbptr[i]);
		}
		if (rsb_flag(res, RSB_VALNOTVALID))
118 119
			seq_puts(s, " (INVALID)");
		rv = seq_puts(s, "\n");
120 121
		if (rv)
			goto out;
122 123
	}

D
David Teigland 已提交
124 125 126 127
	root_list = !list_empty(&res->res_root_list);
	recover_list = !list_empty(&res->res_recover_list);

	if (root_list || recover_list) {
128 129 130 131 132
		rv = seq_printf(s, "Recovery: root %d recover %d flags %lx "
				"count %d\n", root_list, recover_list,
			   	res->res_flags, res->res_recover_locks_count);
		if (rv)
			goto out;
D
David Teigland 已提交
133 134
	}

135
	/* Print the locks attached to this resource */
136
	seq_puts(s, "Granted Queue\n");
137 138 139 140 141
	list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
		rv = print_format1_lock(s, lkb, res);
		if (rv)
			goto out;
	}
142

143
	seq_puts(s, "Conversion Queue\n");
144 145 146 147 148
	list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
		rv = print_format1_lock(s, lkb, res);
		if (rv)
			goto out;
	}
149

150
	seq_puts(s, "Waiting Queue\n");
151 152 153 154 155
	list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
		rv = print_format1_lock(s, lkb, res);
		if (rv)
			goto out;
	}
156

D
David Teigland 已提交
157 158 159
	if (list_empty(&res->res_lookup))
		goto out;

160
	seq_puts(s, "Lookup Queue\n");
D
David Teigland 已提交
161
	list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
162 163
		rv = seq_printf(s, "%08x %s", lkb->lkb_id,
				print_lockmode(lkb->lkb_rqmode));
D
David Teigland 已提交
164 165
		if (lkb->lkb_wait_type)
			seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
166
		rv = seq_puts(s, "\n");
D
David Teigland 已提交
167 168
	}
 out:
D
David Teigland 已提交
169
	unlock_rsb(res);
170
	return rv;
D
David Teigland 已提交
171 172
}

173 174
static int print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
			      struct dlm_rsb *r)
D
David Teigland 已提交
175
{
D
David Teigland 已提交
176 177
	u64 xid = 0;
	u64 us;
178
	int rv;
D
David Teigland 已提交
179 180

	if (lkb->lkb_flags & DLM_IFL_USER) {
181 182
		if (lkb->lkb_ua)
			xid = lkb->lkb_ua->xid;
D
David Teigland 已提交
183 184
	}

D
David Teigland 已提交
185 186
	/* microseconds since lkb was added to current queue */
	us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
D
David Teigland 已提交
187

D
David Teigland 已提交
188
	/* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
D
David Teigland 已提交
189
	   r_nodeid r_len r_name */
D
David Teigland 已提交
190

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
	rv = seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
			lkb->lkb_id,
			lkb->lkb_nodeid,
			lkb->lkb_remid,
			lkb->lkb_ownpid,
			(unsigned long long)xid,
			lkb->lkb_exflags,
			lkb->lkb_flags,
			lkb->lkb_status,
			lkb->lkb_grmode,
			lkb->lkb_rqmode,
			(unsigned long long)us,
			r->res_nodeid,
			r->res_length,
			r->res_name);
	return rv;
D
David Teigland 已提交
207 208
}

D
David Teigland 已提交
209
static int print_format2(struct dlm_rsb *r, struct seq_file *s)
D
David Teigland 已提交
210 211
{
	struct dlm_lkb *lkb;
212
	int rv = 0;
D
David Teigland 已提交
213 214 215

	lock_rsb(r);

216 217 218 219 220
	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
		rv = print_format2_lock(s, lkb, r);
		if (rv)
			goto out;
	}
D
David Teigland 已提交
221

222 223 224 225 226
	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
		rv = print_format2_lock(s, lkb, r);
		if (rv)
			goto out;
	}
D
David Teigland 已提交
227

228 229 230 231 232 233
	list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
		rv = print_format2_lock(s, lkb, r);
		if (rv)
			goto out;
	}
 out:
D
David Teigland 已提交
234
	unlock_rsb(r);
235
	return rv;
D
David Teigland 已提交
236 237
}

238 239
static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
			      int rsb_lookup)
D
David Teigland 已提交
240 241
{
	u64 xid = 0;
242
	int rv;
D
David Teigland 已提交
243 244 245 246 247 248

	if (lkb->lkb_flags & DLM_IFL_USER) {
		if (lkb->lkb_ua)
			xid = lkb->lkb_ua->xid;
	}

249 250 251 252 253 254 255 256 257 258 259
	rv = seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
			lkb->lkb_id,
			lkb->lkb_nodeid,
			lkb->lkb_remid,
			lkb->lkb_ownpid,
			(unsigned long long)xid,
			lkb->lkb_exflags,
			lkb->lkb_flags,
			lkb->lkb_status,
			lkb->lkb_grmode,
			lkb->lkb_rqmode,
D
David Teigland 已提交
260
			lkb->lkb_last_bast.mode,
261 262 263 264
			rsb_lookup,
			lkb->lkb_wait_type,
			lkb->lkb_lvbseq,
			(unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
D
David Teigland 已提交
265
			(unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time));
266
	return rv;
D
David Teigland 已提交
267 268 269 270 271 272 273
}

static int print_format3(struct dlm_rsb *r, struct seq_file *s)
{
	struct dlm_lkb *lkb;
	int i, lvblen = r->res_ls->ls_lvblen;
	int print_name = 1;
274
	int rv;
D
David Teigland 已提交
275 276 277

	lock_rsb(r);

278 279 280 281 282 283 284 285 286 287 288
	rv = seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
			r,
			r->res_nodeid,
			r->res_first_lkid,
			r->res_flags,
			!list_empty(&r->res_root_list),
			!list_empty(&r->res_recover_list),
			r->res_recover_locks_count,
			r->res_length);
	if (rv)
		goto out;
D
David Teigland 已提交
289 290 291 292 293 294 295 296 297 298 299 300 301 302

	for (i = 0; i < r->res_length; i++) {
		if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
			print_name = 0;
	}

	seq_printf(s, "%s", print_name ? "str " : "hex");

	for (i = 0; i < r->res_length; i++) {
		if (print_name)
			seq_printf(s, "%c", r->res_name[i]);
		else
			seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
	}
303
	rv = seq_puts(s, "\n");
304 305
	if (rv)
		goto out;
D
David Teigland 已提交
306 307 308 309 310 311 312 313

	if (!r->res_lvbptr)
		goto do_locks;

	seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);

	for (i = 0; i < lvblen; i++)
		seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
314
	rv = seq_puts(s, "\n");
315 316
	if (rv)
		goto out;
D
David Teigland 已提交
317 318

 do_locks:
319 320 321 322
	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
		rv = print_format3_lock(s, lkb, 0);
		if (rv)
			goto out;
323 324
	}

325 326 327 328
	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
		rv = print_format3_lock(s, lkb, 0);
		if (rv)
			goto out;
329 330
	}

331 332 333 334
	list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
		rv = print_format3_lock(s, lkb, 0);
		if (rv)
			goto out;
335 336
	}

337 338 339 340
	list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
		rv = print_format3_lock(s, lkb, 1);
		if (rv)
			goto out;
341
	}
342 343 344
 out:
	unlock_rsb(r);
	return rv;
345 346
}

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
static int print_format4(struct dlm_rsb *r, struct seq_file *s)
{
	int our_nodeid = dlm_our_nodeid();
	int print_name = 1;
	int i, rv;

	lock_rsb(r);

	rv = seq_printf(s, "rsb %p %d %d %d %d %lu %lx %d ",
			r,
			r->res_nodeid,
			r->res_master_nodeid,
			r->res_dir_nodeid,
			our_nodeid,
			r->res_toss_time,
			r->res_flags,
			r->res_length);
	if (rv)
		goto out;

	for (i = 0; i < r->res_length; i++) {
		if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
			print_name = 0;
	}

	seq_printf(s, "%s", print_name ? "str " : "hex");

	for (i = 0; i < r->res_length; i++) {
		if (print_name)
			seq_printf(s, "%c", r->res_name[i]);
		else
			seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
	}
380
	rv = seq_puts(s, "\n");
381 382 383 384 385
 out:
	unlock_rsb(r);
	return rv;
}

386 387 388 389 390 391
struct rsbtbl_iter {
	struct dlm_rsb *rsb;
	unsigned bucket;
	int format;
	int header;
};
392

393 394 395 396 397 398 399
/* seq_printf returns -1 if the buffer is full, and 0 otherwise.
   If the buffer is full, seq_printf can be called again, but it
   does nothing and just returns -1.  So, the these printing routines
   periodically check the return value to avoid wasting too much time
   trying to print to a full buffer. */

static int table_seq_show(struct seq_file *seq, void *iter_ptr)
400
{
401 402
	struct rsbtbl_iter *ri = iter_ptr;
	int rv = 0;
403

D
David Teigland 已提交
404 405
	switch (ri->format) {
	case 1:
406
		rv = print_format1(ri->rsb, seq);
D
David Teigland 已提交
407 408
		break;
	case 2:
D
David Teigland 已提交
409
		if (ri->header) {
410 411 412
			seq_printf(seq, "id nodeid remid pid xid exflags "
					"flags sts grmode rqmode time_ms "
					"r_nodeid r_len r_name\n");
D
David Teigland 已提交
413 414
			ri->header = 0;
		}
415
		rv = print_format2(ri->rsb, seq);
D
David Teigland 已提交
416 417 418
		break;
	case 3:
		if (ri->header) {
419
			seq_printf(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
D
David Teigland 已提交
420 421
			ri->header = 0;
		}
422
		rv = print_format3(ri->rsb, seq);
D
David Teigland 已提交
423
		break;
424 425 426 427 428 429 430
	case 4:
		if (ri->header) {
			seq_printf(seq, "version 4 rsb 2\n");
			ri->header = 0;
		}
		rv = print_format4(ri->rsb, seq);
		break;
D
David Teigland 已提交
431
	}
432

433
	return rv;
434 435
}

J
James Morris 已提交
436 437 438
static const struct seq_operations format1_seq_ops;
static const struct seq_operations format2_seq_ops;
static const struct seq_operations format3_seq_ops;
439
static const struct seq_operations format4_seq_ops;
440

441
static void *table_seq_start(struct seq_file *seq, loff_t *pos)
442
{
443
	struct rb_root *tree;
B
Bob Peterson 已提交
444
	struct rb_node *node;
445 446 447 448 449
	struct dlm_ls *ls = seq->private;
	struct rsbtbl_iter *ri;
	struct dlm_rsb *r;
	loff_t n = *pos;
	unsigned bucket, entry;
450
	int toss = (seq->op == &format4_seq_ops);
451

452 453
	bucket = n >> 32;
	entry = n & ((1LL << 32) - 1);
D
David Teigland 已提交
454

455 456
	if (bucket >= ls->ls_rsbtbl_size)
		return NULL;
D
David Teigland 已提交
457

D
David Teigland 已提交
458
	ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_NOFS);
D
David Teigland 已提交
459 460
	if (!ri)
		return NULL;
461
	if (n == 0)
D
David Teigland 已提交
462
		ri->header = 1;
463 464 465 466 467 468
	if (seq->op == &format1_seq_ops)
		ri->format = 1;
	if (seq->op == &format2_seq_ops)
		ri->format = 2;
	if (seq->op == &format3_seq_ops)
		ri->format = 3;
469 470 471 472
	if (seq->op == &format4_seq_ops)
		ri->format = 4;

	tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
473

474
	spin_lock(&ls->ls_rsbtbl[bucket].lock);
475 476
	if (!RB_EMPTY_ROOT(tree)) {
		for (node = rb_first(tree); node; node = rb_next(node)) {
B
Bob Peterson 已提交
477
			r = rb_entry(node, struct dlm_rsb, res_hashnode);
478 479 480 481
			if (!entry--) {
				dlm_hold_rsb(r);
				ri->rsb = r;
				ri->bucket = bucket;
482
				spin_unlock(&ls->ls_rsbtbl[bucket].lock);
483 484 485
				return ri;
			}
		}
D
David Teigland 已提交
486
	}
487
	spin_unlock(&ls->ls_rsbtbl[bucket].lock);
D
David Teigland 已提交
488

489 490 491
	/*
	 * move to the first rsb in the next non-empty bucket
	 */
D
David Teigland 已提交
492

493 494
	/* zero the entry */
	n &= ~((1LL << 32) - 1);
D
David Teigland 已提交
495

496 497 498
	while (1) {
		bucket++;
		n += 1LL << 32;
D
David Teigland 已提交
499

500 501
		if (bucket >= ls->ls_rsbtbl_size) {
			kfree(ri);
D
David Teigland 已提交
502 503
			return NULL;
		}
504
		tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
D
David Teigland 已提交
505

506
		spin_lock(&ls->ls_rsbtbl[bucket].lock);
507 508
		if (!RB_EMPTY_ROOT(tree)) {
			node = rb_first(tree);
B
Bob Peterson 已提交
509
			r = rb_entry(node, struct dlm_rsb, res_hashnode);
510 511 512
			dlm_hold_rsb(r);
			ri->rsb = r;
			ri->bucket = bucket;
513
			spin_unlock(&ls->ls_rsbtbl[bucket].lock);
514 515 516
			*pos = n;
			return ri;
		}
517
		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
518
	}
D
David Teigland 已提交
519 520
}

521
static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
D
David Teigland 已提交
522
{
523 524
	struct dlm_ls *ls = seq->private;
	struct rsbtbl_iter *ri = iter_ptr;
525
	struct rb_root *tree;
B
Bob Peterson 已提交
526
	struct rb_node *next;
527 528 529
	struct dlm_rsb *r, *rp;
	loff_t n = *pos;
	unsigned bucket;
530
	int toss = (seq->op == &format4_seq_ops);
531 532 533 534 535 536 537

	bucket = n >> 32;

	/*
	 * move to the next rsb in the same bucket
	 */

538
	spin_lock(&ls->ls_rsbtbl[bucket].lock);
539
	rp = ri->rsb;
B
Bob Peterson 已提交
540
	next = rb_next(&rp->res_hashnode);
541

B
Bob Peterson 已提交
542 543
	if (next) {
		r = rb_entry(next, struct dlm_rsb, res_hashnode);
544 545
		dlm_hold_rsb(r);
		ri->rsb = r;
546
		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
547 548 549 550
		dlm_put_rsb(rp);
		++*pos;
		return ri;
	}
551
	spin_unlock(&ls->ls_rsbtbl[bucket].lock);
552
	dlm_put_rsb(rp);
D
David Teigland 已提交
553

554 555 556
	/*
	 * move to the first rsb in the next non-empty bucket
	 */
D
David Teigland 已提交
557

558 559
	/* zero the entry */
	n &= ~((1LL << 32) - 1);
D
David Teigland 已提交
560

561 562 563
	while (1) {
		bucket++;
		n += 1LL << 32;
D
David Teigland 已提交
564

565 566 567 568
		if (bucket >= ls->ls_rsbtbl_size) {
			kfree(ri);
			return NULL;
		}
569
		tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
D
David Teigland 已提交
570

571
		spin_lock(&ls->ls_rsbtbl[bucket].lock);
572 573
		if (!RB_EMPTY_ROOT(tree)) {
			next = rb_first(tree);
B
Bob Peterson 已提交
574
			r = rb_entry(next, struct dlm_rsb, res_hashnode);
575 576 577
			dlm_hold_rsb(r);
			ri->rsb = r;
			ri->bucket = bucket;
578
			spin_unlock(&ls->ls_rsbtbl[bucket].lock);
579 580 581
			*pos = n;
			return ri;
		}
582
		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
D
David Teigland 已提交
583 584 585
	}
}

586
static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
D
David Teigland 已提交
587
{
588
	struct rsbtbl_iter *ri = iter_ptr;
D
David Teigland 已提交
589

590 591 592
	if (ri) {
		dlm_put_rsb(ri->rsb);
		kfree(ri);
D
David Teigland 已提交
593 594 595
	}
}

J
James Morris 已提交
596
static const struct seq_operations format1_seq_ops = {
597 598 599 600
	.start = table_seq_start,
	.next  = table_seq_next,
	.stop  = table_seq_stop,
	.show  = table_seq_show,
D
David Teigland 已提交
601 602
};

J
James Morris 已提交
603
static const struct seq_operations format2_seq_ops = {
604 605 606 607 608 609
	.start = table_seq_start,
	.next  = table_seq_next,
	.stop  = table_seq_stop,
	.show  = table_seq_show,
};

J
James Morris 已提交
610
static const struct seq_operations format3_seq_ops = {
611 612 613 614 615 616
	.start = table_seq_start,
	.next  = table_seq_next,
	.stop  = table_seq_stop,
	.show  = table_seq_show,
};

617 618 619 620 621 622 623
static const struct seq_operations format4_seq_ops = {
	.start = table_seq_start,
	.next  = table_seq_next,
	.stop  = table_seq_stop,
	.show  = table_seq_show,
};

624 625 626
static const struct file_operations format1_fops;
static const struct file_operations format2_fops;
static const struct file_operations format3_fops;
627
static const struct file_operations format4_fops;
628 629

static int table_open(struct inode *inode, struct file *file)
D
David Teigland 已提交
630 631
{
	struct seq_file *seq;
632 633 634 635 636 637 638 639
	int ret = -1;

	if (file->f_op == &format1_fops)
		ret = seq_open(file, &format1_seq_ops);
	else if (file->f_op == &format2_fops)
		ret = seq_open(file, &format2_seq_ops);
	else if (file->f_op == &format3_fops)
		ret = seq_open(file, &format3_seq_ops);
640 641
	else if (file->f_op == &format4_fops)
		ret = seq_open(file, &format4_seq_ops);
D
David Teigland 已提交
642 643 644 645 646

	if (ret)
		return ret;

	seq = file->private_data;
647
	seq->private = inode->i_private; /* the dlm_ls */
D
David Teigland 已提交
648 649 650
	return 0;
}

651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
static const struct file_operations format1_fops = {
	.owner   = THIS_MODULE,
	.open    = table_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release
};

static const struct file_operations format2_fops = {
	.owner   = THIS_MODULE,
	.open    = table_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release
};

static const struct file_operations format3_fops = {
D
David Teigland 已提交
668
	.owner   = THIS_MODULE,
669
	.open    = table_open,
D
David Teigland 已提交
670 671 672 673 674
	.read    = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release
};

675 676 677 678 679 680 681 682
static const struct file_operations format4_fops = {
	.owner   = THIS_MODULE,
	.open    = table_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release
};

D
David Teigland 已提交
683 684 685 686 687 688 689 690
/*
 * dump lkb's on the ls_waiters list
 */
static ssize_t waiters_read(struct file *file, char __user *userbuf,
			    size_t count, loff_t *ppos)
{
	struct dlm_ls *ls = file->private_data;
	struct dlm_lkb *lkb;
D
David Teigland 已提交
691
	size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
D
David Teigland 已提交
692 693 694 695 696 697

	mutex_lock(&debug_buf_lock);
	mutex_lock(&ls->ls_waiters_mutex);
	memset(debug_buf, 0, sizeof(debug_buf));

	list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
D
David Teigland 已提交
698 699 700 701 702 703
		ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
			       lkb->lkb_id, lkb->lkb_wait_type,
			       lkb->lkb_nodeid, lkb->lkb_resource->res_name);
		if (ret >= len - pos)
			break;
		pos += ret;
D
David Teigland 已提交
704 705 706 707 708 709 710 711
	}
	mutex_unlock(&ls->ls_waiters_mutex);

	rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
	mutex_unlock(&debug_buf_lock);
	return rv;
}

712
static const struct file_operations waiters_fops = {
D
David Teigland 已提交
713
	.owner   = THIS_MODULE,
714
	.open    = simple_open,
715 716
	.read    = waiters_read,
	.llseek  = default_llseek,
D
David Teigland 已提交
717 718
};

D
David Teigland 已提交
719 720 721 722 723 724 725 726 727 728
void dlm_delete_debug_file(struct dlm_ls *ls)
{
	if (ls->ls_debug_rsb_dentry)
		debugfs_remove(ls->ls_debug_rsb_dentry);
	if (ls->ls_debug_waiters_dentry)
		debugfs_remove(ls->ls_debug_waiters_dentry);
	if (ls->ls_debug_locks_dentry)
		debugfs_remove(ls->ls_debug_locks_dentry);
	if (ls->ls_debug_all_dentry)
		debugfs_remove(ls->ls_debug_all_dentry);
729 730
	if (ls->ls_debug_toss_dentry)
		debugfs_remove(ls->ls_debug_toss_dentry);
D
David Teigland 已提交
731 732
}

733 734
int dlm_create_debug_file(struct dlm_ls *ls)
{
D
David Teigland 已提交
735 736
	char name[DLM_LOCKSPACE_LEN+8];

D
David Teigland 已提交
737 738
	/* format 1 */

D
David Teigland 已提交
739 740 741 742
	ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
						      S_IFREG | S_IRUGO,
						      dlm_root,
						      ls,
743
						      &format1_fops);
D
David Teigland 已提交
744
	if (!ls->ls_debug_rsb_dentry)
D
David Teigland 已提交
745
		goto fail;
D
David Teigland 已提交
746

D
David Teigland 已提交
747
	/* format 2 */
D
David Teigland 已提交
748

D
David Teigland 已提交
749
	memset(name, 0, sizeof(name));
D
David Teigland 已提交
750 751 752 753 754 755
	snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);

	ls->ls_debug_locks_dentry = debugfs_create_file(name,
							S_IFREG | S_IRUGO,
							dlm_root,
							ls,
756
							&format2_fops);
D
David Teigland 已提交
757 758 759 760 761 762 763 764 765 766 767 768
	if (!ls->ls_debug_locks_dentry)
		goto fail;

	/* format 3 */

	memset(name, 0, sizeof(name));
	snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_all", ls->ls_name);

	ls->ls_debug_all_dentry = debugfs_create_file(name,
						      S_IFREG | S_IRUGO,
						      dlm_root,
						      ls,
769
						      &format3_fops);
D
David Teigland 已提交
770 771 772
	if (!ls->ls_debug_all_dentry)
		goto fail;

773 774 775 776 777 778 779 780 781 782 783 784 785
	/* format 4 */

	memset(name, 0, sizeof(name));
	snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_toss", ls->ls_name);

	ls->ls_debug_toss_dentry = debugfs_create_file(name,
						       S_IFREG | S_IRUGO,
						       dlm_root,
						       ls,
						       &format4_fops);
	if (!ls->ls_debug_toss_dentry)
		goto fail;

D
David Teigland 已提交
786 787 788 789 790 791 792 793 794 795
	memset(name, 0, sizeof(name));
	snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);

	ls->ls_debug_waiters_dentry = debugfs_create_file(name,
							  S_IFREG | S_IRUGO,
							  dlm_root,
							  ls,
							  &waiters_fops);
	if (!ls->ls_debug_waiters_dentry)
		goto fail;
D
David Teigland 已提交
796

D
David Teigland 已提交
797
	return 0;
798

D
David Teigland 已提交
799 800 801
 fail:
	dlm_delete_debug_file(ls);
	return -ENOMEM;
802 803
}

804
int __init dlm_register_debugfs(void)
805
{
D
David Teigland 已提交
806
	mutex_init(&debug_buf_lock);
807 808 809 810 811 812 813 814 815
	dlm_root = debugfs_create_dir("dlm", NULL);
	return dlm_root ? 0 : -ENOMEM;
}

void dlm_unregister_debugfs(void)
{
	debugfs_remove(dlm_root);
}