Blame view
fs/dlm/debug_fs.c
18.1 KB
e7fd41792
|
1 2 3 |
/****************************************************************************** ******************************************************************************* ** |
892c4467e
|
4 |
** Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved. |
e7fd41792
|
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> |
5a0e3ad6a
|
18 |
#include <linux/slab.h> |
e7fd41792
|
19 20 |
#include "dlm_internal.h" |
916297aad
|
21 |
#include "lock.h" |
e7fd41792
|
22 |
|
5de6319b1
|
23 24 25 |
#define DLM_DEBUG_BUF_LEN 4096 static char debug_buf[DLM_DEBUG_BUF_LEN]; static struct mutex debug_buf_lock; |
e7fd41792
|
26 27 |
static struct dentry *dlm_root; |
e7fd41792
|
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
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 "??"; } } |
d6d906b23
|
49 50 |
static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *res) |
e7fd41792
|
51 52 |
{ seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode)); |
892c4467e
|
53 54 |
if (lkb->lkb_status == DLM_LKSTS_CONVERT || lkb->lkb_status == DLM_LKSTS_WAITING) |
e7fd41792
|
55 |
seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode)); |
e7fd41792
|
56 57 58 59 60 61 62 63 64 65 |
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); |
d6d906b23
|
66 67 |
seq_puts(s, " "); |
e7fd41792
|
68 |
} |
d6d906b23
|
69 |
static void print_format1(struct dlm_rsb *res, struct seq_file *s) |
e7fd41792
|
70 71 |
{ struct dlm_lkb *lkb; |
5de6319b1
|
72 |
int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list; |
e7fd41792
|
73 |
|
9dd592d70
|
74 |
lock_rsb(res); |
d6d906b23
|
75 76 |
seq_printf(s, " Resource %p Name (len=%d) \"", res, res->res_length); |
892c4467e
|
77 |
|
e7fd41792
|
78 79 80 81 82 83 |
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", '.'); } |
892c4467e
|
84 |
|
e7fd41792
|
85 |
if (res->res_nodeid > 0) |
d6d906b23
|
86 87 88 89 |
seq_printf(s, "\" Local Copy, Master is node %d ", res->res_nodeid); |
e7fd41792
|
90 |
else if (res->res_nodeid == 0) |
d6d906b23
|
91 92 93 |
seq_puts(s, "\" Master Copy "); |
e7fd41792
|
94 |
else if (res->res_nodeid == -1) |
d6d906b23
|
95 96 97 98 |
seq_printf(s, "\" Looking up master (lkid %x) ", res->res_first_lkid); |
e7fd41792
|
99 |
else |
d6d906b23
|
100 101 102 103 |
seq_printf(s, "\" Invalid master %d ", res->res_nodeid); if (seq_has_overflowed(s)) |
892c4467e
|
104 |
goto out; |
e7fd41792
|
105 106 107 |
/* Print the LVB: */ if (res->res_lvbptr) { |
c1d4518c4
|
108 |
seq_puts(s, "LVB: "); |
e7fd41792
|
109 110 |
for (i = 0; i < lvblen; i++) { if (i == lvblen / 2) |
c1d4518c4
|
111 112 |
seq_puts(s, " "); |
e7fd41792
|
113 114 115 116 |
seq_printf(s, "%02x ", (unsigned char) res->res_lvbptr[i]); } if (rsb_flag(res, RSB_VALNOTVALID)) |
c1d4518c4
|
117 |
seq_puts(s, " (INVALID)"); |
d6d906b23
|
118 119 120 |
seq_puts(s, " "); if (seq_has_overflowed(s)) |
892c4467e
|
121 |
goto out; |
e7fd41792
|
122 |
} |
5de6319b1
|
123 124 125 126 |
root_list = !list_empty(&res->res_root_list); recover_list = !list_empty(&res->res_recover_list); if (root_list || recover_list) { |
d6d906b23
|
127 128 129 130 |
seq_printf(s, "Recovery: root %d recover %d flags %lx count %d ", root_list, recover_list, res->res_flags, res->res_recover_locks_count); |
5de6319b1
|
131 |
} |
e7fd41792
|
132 |
/* Print the locks attached to this resource */ |
c1d4518c4
|
133 134 |
seq_puts(s, "Granted Queue "); |
892c4467e
|
135 |
list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) { |
d6d906b23
|
136 137 |
print_format1_lock(s, lkb, res); if (seq_has_overflowed(s)) |
892c4467e
|
138 139 |
goto out; } |
e7fd41792
|
140 |
|
c1d4518c4
|
141 142 |
seq_puts(s, "Conversion Queue "); |
892c4467e
|
143 |
list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) { |
d6d906b23
|
144 145 |
print_format1_lock(s, lkb, res); if (seq_has_overflowed(s)) |
892c4467e
|
146 147 |
goto out; } |
e7fd41792
|
148 |
|
c1d4518c4
|
149 150 |
seq_puts(s, "Waiting Queue "); |
892c4467e
|
151 |
list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) { |
d6d906b23
|
152 153 |
print_format1_lock(s, lkb, res); if (seq_has_overflowed(s)) |
892c4467e
|
154 155 |
goto out; } |
e7fd41792
|
156 |
|
5de6319b1
|
157 158 |
if (list_empty(&res->res_lookup)) goto out; |
c1d4518c4
|
159 160 |
seq_puts(s, "Lookup Queue "); |
5de6319b1
|
161 |
list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) { |
d6d906b23
|
162 163 |
seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_rqmode)); |
5de6319b1
|
164 165 |
if (lkb->lkb_wait_type) seq_printf(s, " wait_type: %d", lkb->lkb_wait_type); |
d6d906b23
|
166 167 168 169 |
seq_puts(s, " "); if (seq_has_overflowed(s)) goto out; |
5de6319b1
|
170 171 |
} out: |
9dd592d70
|
172 |
unlock_rsb(res); |
9dd592d70
|
173 |
} |
d6d906b23
|
174 175 |
static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r) |
9dd592d70
|
176 |
{ |
eeda418d8
|
177 178 |
u64 xid = 0; u64 us; |
9dd592d70
|
179 180 |
if (lkb->lkb_flags & DLM_IFL_USER) { |
d292c0cc4
|
181 182 |
if (lkb->lkb_ua) xid = lkb->lkb_ua->xid; |
9dd592d70
|
183 |
} |
eeda418d8
|
184 185 |
/* microseconds since lkb was added to current queue */ us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp)); |
9dd592d70
|
186 |
|
eeda418d8
|
187 |
/* id nodeid remid pid xid exflags flags sts grmode rqmode time_us |
ac90a2552
|
188 |
r_nodeid r_len r_name */ |
9dd592d70
|
189 |
|
d6d906b23
|
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\" ", 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); |
9dd592d70
|
206 |
} |
d6d906b23
|
207 |
static void print_format2(struct dlm_rsb *r, struct seq_file *s) |
9dd592d70
|
208 209 210 211 |
{ struct dlm_lkb *lkb; lock_rsb(r); |
892c4467e
|
212 |
list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) { |
d6d906b23
|
213 214 |
print_format2_lock(s, lkb, r); if (seq_has_overflowed(s)) |
892c4467e
|
215 216 |
goto out; } |
9dd592d70
|
217 |
|
892c4467e
|
218 |
list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) { |
d6d906b23
|
219 220 |
print_format2_lock(s, lkb, r); if (seq_has_overflowed(s)) |
892c4467e
|
221 222 |
goto out; } |
d022509d1
|
223 |
|
892c4467e
|
224 |
list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) { |
d6d906b23
|
225 226 |
print_format2_lock(s, lkb, r); if (seq_has_overflowed(s)) |
892c4467e
|
227 228 229 |
goto out; } out: |
d022509d1
|
230 |
unlock_rsb(r); |
d022509d1
|
231 |
} |
d6d906b23
|
232 |
static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb, |
892c4467e
|
233 |
int rsb_lookup) |
d022509d1
|
234 235 236 237 238 239 240 |
{ u64 xid = 0; if (lkb->lkb_flags & DLM_IFL_USER) { if (lkb->lkb_ua) xid = lkb->lkb_ua->xid; } |
d6d906b23
|
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu ", 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, lkb->lkb_last_bast.mode, rsb_lookup, lkb->lkb_wait_type, lkb->lkb_lvbseq, (unsigned long long)ktime_to_ns(lkb->lkb_timestamp), (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time)); |
d022509d1
|
259 |
} |
d6d906b23
|
260 |
static void print_format3(struct dlm_rsb *r, struct seq_file *s) |
d022509d1
|
261 262 263 264 265 266 |
{ struct dlm_lkb *lkb; int i, lvblen = r->res_ls->ls_lvblen; int print_name = 1; lock_rsb(r); |
d6d906b23
|
267 268 269 270 271 272 273 274 275 276 |
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 (seq_has_overflowed(s)) |
892c4467e
|
277 |
goto out; |
d022509d1
|
278 279 280 281 282 |
for (i = 0; i < r->res_length; i++) { if (!isascii(r->res_name[i]) || !isprint(r->res_name[i])) print_name = 0; } |
f365ef9b7
|
283 |
seq_puts(s, print_name ? "str " : "hex"); |
d022509d1
|
284 285 286 287 288 289 290 |
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]); } |
d6d906b23
|
291 292 293 |
seq_puts(s, " "); if (seq_has_overflowed(s)) |
892c4467e
|
294 |
goto out; |
d022509d1
|
295 296 297 298 299 300 301 302 |
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]); |
d6d906b23
|
303 304 305 |
seq_puts(s, " "); if (seq_has_overflowed(s)) |
892c4467e
|
306 |
goto out; |
d022509d1
|
307 308 |
do_locks: |
892c4467e
|
309 |
list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) { |
d6d906b23
|
310 311 |
print_format3_lock(s, lkb, 0); if (seq_has_overflowed(s)) |
892c4467e
|
312 |
goto out; |
e7fd41792
|
313 |
} |
e7fd41792
|
314 |
|
892c4467e
|
315 |
list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) { |
d6d906b23
|
316 317 |
print_format3_lock(s, lkb, 0); if (seq_has_overflowed(s)) |
892c4467e
|
318 |
goto out; |
e7fd41792
|
319 |
} |
892c4467e
|
320 |
list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) { |
d6d906b23
|
321 322 |
print_format3_lock(s, lkb, 0); if (seq_has_overflowed(s)) |
892c4467e
|
323 |
goto out; |
e7fd41792
|
324 |
} |
892c4467e
|
325 |
list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) { |
d6d906b23
|
326 327 |
print_format3_lock(s, lkb, 1); if (seq_has_overflowed(s)) |
892c4467e
|
328 |
goto out; |
e7fd41792
|
329 |
} |
892c4467e
|
330 331 |
out: unlock_rsb(r); |
e7fd41792
|
332 |
} |
d6d906b23
|
333 |
static void print_format4(struct dlm_rsb *r, struct seq_file *s) |
c04fecb4d
|
334 335 336 |
{ int our_nodeid = dlm_our_nodeid(); int print_name = 1; |
d6d906b23
|
337 |
int i; |
c04fecb4d
|
338 339 |
lock_rsb(r); |
d6d906b23
|
340 341 342 343 344 345 346 347 348 |
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); |
c04fecb4d
|
349 350 351 352 353 |
for (i = 0; i < r->res_length; i++) { if (!isascii(r->res_name[i]) || !isprint(r->res_name[i])) print_name = 0; } |
f365ef9b7
|
354 |
seq_puts(s, print_name ? "str " : "hex"); |
c04fecb4d
|
355 356 357 358 359 360 361 |
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]); } |
d6d906b23
|
362 363 |
seq_puts(s, " "); |
c04fecb4d
|
364 |
unlock_rsb(r); |
c04fecb4d
|
365 |
} |
892c4467e
|
366 367 368 369 370 371 |
struct rsbtbl_iter { struct dlm_rsb *rsb; unsigned bucket; int format; int header; }; |
e7fd41792
|
372 |
|
d6d906b23
|
373 374 375 376 377 378 |
/* * If the buffer is full, seq_printf can be called again, but it * does nothing. So, the these printing routines periodically check * seq_has_overflowed to avoid wasting too much time trying to print to * a full buffer. */ |
892c4467e
|
379 380 |
static int table_seq_show(struct seq_file *seq, void *iter_ptr) |
e7fd41792
|
381 |
{ |
892c4467e
|
382 |
struct rsbtbl_iter *ri = iter_ptr; |
e7fd41792
|
383 |
|
d022509d1
|
384 385 |
switch (ri->format) { case 1: |
d6d906b23
|
386 |
print_format1(ri->rsb, seq); |
d022509d1
|
387 388 |
break; case 2: |
9dd592d70
|
389 |
if (ri->header) { |
f365ef9b7
|
390 391 |
seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name "); |
9dd592d70
|
392 393 |
ri->header = 0; } |
d6d906b23
|
394 |
print_format2(ri->rsb, seq); |
d022509d1
|
395 396 397 |
break; case 3: if (ri->header) { |
f365ef9b7
|
398 399 |
seq_puts(seq, "version rsb 1.1 lvb 1.1 lkb 1.1 "); |
d022509d1
|
400 401 |
ri->header = 0; } |
d6d906b23
|
402 |
print_format3(ri->rsb, seq); |
d022509d1
|
403 |
break; |
c04fecb4d
|
404 405 |
case 4: if (ri->header) { |
f365ef9b7
|
406 407 |
seq_puts(seq, "version 4 rsb 2 "); |
c04fecb4d
|
408 409 |
ri->header = 0; } |
d6d906b23
|
410 |
print_format4(ri->rsb, seq); |
c04fecb4d
|
411 |
break; |
9dd592d70
|
412 |
} |
e7fd41792
|
413 |
|
d6d906b23
|
414 |
return 0; |
e7fd41792
|
415 |
} |
88e9d34c7
|
416 417 418 |
static const struct seq_operations format1_seq_ops; static const struct seq_operations format2_seq_ops; static const struct seq_operations format3_seq_ops; |
c04fecb4d
|
419 |
static const struct seq_operations format4_seq_ops; |
e7fd41792
|
420 |
|
892c4467e
|
421 |
static void *table_seq_start(struct seq_file *seq, loff_t *pos) |
e7fd41792
|
422 |
{ |
c04fecb4d
|
423 |
struct rb_root *tree; |
9beb3bf5a
|
424 |
struct rb_node *node; |
892c4467e
|
425 426 427 428 429 |
struct dlm_ls *ls = seq->private; struct rsbtbl_iter *ri; struct dlm_rsb *r; loff_t n = *pos; unsigned bucket, entry; |
c04fecb4d
|
430 |
int toss = (seq->op == &format4_seq_ops); |
e7fd41792
|
431 |
|
892c4467e
|
432 433 |
bucket = n >> 32; entry = n & ((1LL << 32) - 1); |
9dd592d70
|
434 |
|
892c4467e
|
435 436 |
if (bucket >= ls->ls_rsbtbl_size) return NULL; |
9dd592d70
|
437 |
|
573c24c4a
|
438 |
ri = kzalloc(sizeof(struct rsbtbl_iter), GFP_NOFS); |
9dd592d70
|
439 440 |
if (!ri) return NULL; |
892c4467e
|
441 |
if (n == 0) |
9dd592d70
|
442 |
ri->header = 1; |
892c4467e
|
443 444 445 446 447 448 |
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; |
c04fecb4d
|
449 450 451 452 |
if (seq->op == &format4_seq_ops) ri->format = 4; tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep; |
892c4467e
|
453 |
|
c7be761a8
|
454 |
spin_lock(&ls->ls_rsbtbl[bucket].lock); |
c04fecb4d
|
455 456 |
if (!RB_EMPTY_ROOT(tree)) { for (node = rb_first(tree); node; node = rb_next(node)) { |
9beb3bf5a
|
457 |
r = rb_entry(node, struct dlm_rsb, res_hashnode); |
892c4467e
|
458 459 460 461 |
if (!entry--) { dlm_hold_rsb(r); ri->rsb = r; ri->bucket = bucket; |
c7be761a8
|
462 |
spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
892c4467e
|
463 464 465 |
return ri; } } |
9dd592d70
|
466 |
} |
c7be761a8
|
467 |
spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
9dd592d70
|
468 |
|
892c4467e
|
469 470 471 |
/* * move to the first rsb in the next non-empty bucket */ |
9dd592d70
|
472 |
|
892c4467e
|
473 474 |
/* zero the entry */ n &= ~((1LL << 32) - 1); |
9dd592d70
|
475 |
|
892c4467e
|
476 477 478 |
while (1) { bucket++; n += 1LL << 32; |
9dd592d70
|
479 |
|
892c4467e
|
480 481 |
if (bucket >= ls->ls_rsbtbl_size) { kfree(ri); |
9dd592d70
|
482 483 |
return NULL; } |
c04fecb4d
|
484 |
tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep; |
9dd592d70
|
485 |
|
c7be761a8
|
486 |
spin_lock(&ls->ls_rsbtbl[bucket].lock); |
c04fecb4d
|
487 488 |
if (!RB_EMPTY_ROOT(tree)) { node = rb_first(tree); |
9beb3bf5a
|
489 |
r = rb_entry(node, struct dlm_rsb, res_hashnode); |
892c4467e
|
490 491 492 |
dlm_hold_rsb(r); ri->rsb = r; ri->bucket = bucket; |
c7be761a8
|
493 |
spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
892c4467e
|
494 495 496 |
*pos = n; return ri; } |
c7be761a8
|
497 |
spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
892c4467e
|
498 |
} |
9dd592d70
|
499 |
} |
892c4467e
|
500 |
static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos) |
9dd592d70
|
501 |
{ |
892c4467e
|
502 503 |
struct dlm_ls *ls = seq->private; struct rsbtbl_iter *ri = iter_ptr; |
c04fecb4d
|
504 |
struct rb_root *tree; |
9beb3bf5a
|
505 |
struct rb_node *next; |
892c4467e
|
506 507 508 |
struct dlm_rsb *r, *rp; loff_t n = *pos; unsigned bucket; |
c04fecb4d
|
509 |
int toss = (seq->op == &format4_seq_ops); |
892c4467e
|
510 511 512 513 514 515 |
bucket = n >> 32; /* * move to the next rsb in the same bucket */ |
c7be761a8
|
516 |
spin_lock(&ls->ls_rsbtbl[bucket].lock); |
892c4467e
|
517 |
rp = ri->rsb; |
9beb3bf5a
|
518 |
next = rb_next(&rp->res_hashnode); |
892c4467e
|
519 |
|
9beb3bf5a
|
520 521 |
if (next) { r = rb_entry(next, struct dlm_rsb, res_hashnode); |
892c4467e
|
522 523 |
dlm_hold_rsb(r); ri->rsb = r; |
c7be761a8
|
524 |
spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
892c4467e
|
525 526 527 528 |
dlm_put_rsb(rp); ++*pos; return ri; } |
c7be761a8
|
529 |
spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
892c4467e
|
530 |
dlm_put_rsb(rp); |
d022509d1
|
531 |
|
892c4467e
|
532 533 534 |
/* * move to the first rsb in the next non-empty bucket */ |
d022509d1
|
535 |
|
892c4467e
|
536 537 |
/* zero the entry */ n &= ~((1LL << 32) - 1); |
d022509d1
|
538 |
|
892c4467e
|
539 540 541 |
while (1) { bucket++; n += 1LL << 32; |
d022509d1
|
542 |
|
892c4467e
|
543 544 545 546 |
if (bucket >= ls->ls_rsbtbl_size) { kfree(ri); return NULL; } |
c04fecb4d
|
547 |
tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep; |
d022509d1
|
548 |
|
c7be761a8
|
549 |
spin_lock(&ls->ls_rsbtbl[bucket].lock); |
c04fecb4d
|
550 551 |
if (!RB_EMPTY_ROOT(tree)) { next = rb_first(tree); |
9beb3bf5a
|
552 |
r = rb_entry(next, struct dlm_rsb, res_hashnode); |
892c4467e
|
553 554 555 |
dlm_hold_rsb(r); ri->rsb = r; ri->bucket = bucket; |
c7be761a8
|
556 |
spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
892c4467e
|
557 558 559 |
*pos = n; return ri; } |
c7be761a8
|
560 |
spin_unlock(&ls->ls_rsbtbl[bucket].lock); |
d022509d1
|
561 |
} |
d022509d1
|
562 |
} |
892c4467e
|
563 |
static void table_seq_stop(struct seq_file *seq, void *iter_ptr) |
d022509d1
|
564 |
{ |
892c4467e
|
565 |
struct rsbtbl_iter *ri = iter_ptr; |
d022509d1
|
566 |
|
892c4467e
|
567 568 569 |
if (ri) { dlm_put_rsb(ri->rsb); kfree(ri); |
d022509d1
|
570 |
} |
d022509d1
|
571 |
} |
88e9d34c7
|
572 |
static const struct seq_operations format1_seq_ops = { |
892c4467e
|
573 574 575 576 |
.start = table_seq_start, .next = table_seq_next, .stop = table_seq_stop, .show = table_seq_show, |
d022509d1
|
577 |
}; |
88e9d34c7
|
578 |
static const struct seq_operations format2_seq_ops = { |
892c4467e
|
579 580 581 582 583 |
.start = table_seq_start, .next = table_seq_next, .stop = table_seq_stop, .show = table_seq_show, }; |
88e9d34c7
|
584 |
static const struct seq_operations format3_seq_ops = { |
892c4467e
|
585 586 587 588 589 |
.start = table_seq_start, .next = table_seq_next, .stop = table_seq_stop, .show = table_seq_show, }; |
c04fecb4d
|
590 591 592 593 594 595 |
static const struct seq_operations format4_seq_ops = { .start = table_seq_start, .next = table_seq_next, .stop = table_seq_stop, .show = table_seq_show, }; |
892c4467e
|
596 597 598 |
static const struct file_operations format1_fops; static const struct file_operations format2_fops; static const struct file_operations format3_fops; |
c04fecb4d
|
599 |
static const struct file_operations format4_fops; |
892c4467e
|
600 601 |
static int table_open(struct inode *inode, struct file *file) |
d022509d1
|
602 603 |
{ struct seq_file *seq; |
892c4467e
|
604 605 606 607 608 609 610 611 |
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); |
c04fecb4d
|
612 613 |
else if (file->f_op == &format4_fops) ret = seq_open(file, &format4_seq_ops); |
d022509d1
|
614 |
|
d022509d1
|
615 616 617 618 |
if (ret) return ret; seq = file->private_data; |
892c4467e
|
619 |
seq->private = inode->i_private; /* the dlm_ls */ |
d022509d1
|
620 621 |
return 0; } |
892c4467e
|
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 |
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 = { |
d022509d1
|
639 |
.owner = THIS_MODULE, |
892c4467e
|
640 |
.open = table_open, |
d022509d1
|
641 642 643 644 |
.read = seq_read, .llseek = seq_lseek, .release = seq_release }; |
c04fecb4d
|
645 646 647 648 649 650 651 |
static const struct file_operations format4_fops = { .owner = THIS_MODULE, .open = table_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release }; |
d022509d1
|
652 |
/* |
5de6319b1
|
653 654 |
* dump lkb's on the ls_waiters list */ |
5de6319b1
|
655 656 657 658 659 |
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; |
06442440b
|
660 |
size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv; |
5de6319b1
|
661 662 663 664 665 666 |
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) { |
06442440b
|
667 668 669 670 671 672 673 |
ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s ", lkb->lkb_id, lkb->lkb_wait_type, lkb->lkb_nodeid, lkb->lkb_resource->res_name); if (ret >= len - pos) break; pos += ret; |
5de6319b1
|
674 675 676 677 678 679 680 |
} mutex_unlock(&ls->ls_waiters_mutex); rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos); mutex_unlock(&debug_buf_lock); return rv; } |
00977a59b
|
681 |
static const struct file_operations waiters_fops = { |
5de6319b1
|
682 |
.owner = THIS_MODULE, |
234e34058
|
683 |
.open = simple_open, |
6038f373a
|
684 685 |
.read = waiters_read, .llseek = default_llseek, |
5de6319b1
|
686 |
}; |
d022509d1
|
687 688 |
void dlm_delete_debug_file(struct dlm_ls *ls) { |
e0d9bf4cc
|
689 690 691 692 693 |
debugfs_remove(ls->ls_debug_rsb_dentry); debugfs_remove(ls->ls_debug_waiters_dentry); debugfs_remove(ls->ls_debug_locks_dentry); debugfs_remove(ls->ls_debug_all_dentry); debugfs_remove(ls->ls_debug_toss_dentry); |
d022509d1
|
694 |
} |
e7fd41792
|
695 696 |
int dlm_create_debug_file(struct dlm_ls *ls) { |
5de6319b1
|
697 |
char name[DLM_LOCKSPACE_LEN+8]; |
d022509d1
|
698 |
/* format 1 */ |
5de6319b1
|
699 700 701 702 |
ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name, S_IFREG | S_IRUGO, dlm_root, ls, |
892c4467e
|
703 |
&format1_fops); |
20abf975f
|
704 |
if (!ls->ls_debug_rsb_dentry) |
d022509d1
|
705 |
goto fail; |
5de6319b1
|
706 |
|
d022509d1
|
707 |
/* format 2 */ |
5de6319b1
|
708 |
|
9dd592d70
|
709 |
memset(name, 0, sizeof(name)); |
ac90a2552
|
710 711 712 713 714 715 |
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, |
892c4467e
|
716 |
&format2_fops); |
d022509d1
|
717 718 719 720 721 722 723 724 725 726 727 728 |
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, |
892c4467e
|
729 |
&format3_fops); |
d022509d1
|
730 731 |
if (!ls->ls_debug_all_dentry) goto fail; |
c04fecb4d
|
732 733 734 735 736 737 738 739 740 741 742 743 |
/* 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; |
d022509d1
|
744 745 746 747 748 749 750 751 752 753 |
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; |
9dd592d70
|
754 |
|
5de6319b1
|
755 |
return 0; |
e7fd41792
|
756 |
|
d022509d1
|
757 758 759 |
fail: dlm_delete_debug_file(ls); return -ENOMEM; |
e7fd41792
|
760 |
} |
30727174b
|
761 |
int __init dlm_register_debugfs(void) |
e7fd41792
|
762 |
{ |
5de6319b1
|
763 |
mutex_init(&debug_buf_lock); |
e7fd41792
|
764 765 766 767 768 769 770 771 |
dlm_root = debugfs_create_dir("dlm", NULL); return dlm_root ? 0 : -ENOMEM; } void dlm_unregister_debugfs(void) { debugfs_remove(dlm_root); } |