]> Git Repo - J-linux.git/blob - fs/ocfs2/dlm/dlmdebug.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / fs / ocfs2 / dlm / dlmdebug.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * dlmdebug.c
4  *
5  * debug functionality for the dlm
6  *
7  * Copyright (C) 2004, 2008 Oracle.  All rights reserved.
8  */
9
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <linux/highmem.h>
13 #include <linux/sysctl.h>
14 #include <linux/spinlock.h>
15 #include <linux/debugfs.h>
16 #include <linux/export.h>
17
18 #include "../cluster/heartbeat.h"
19 #include "../cluster/nodemanager.h"
20 #include "../cluster/tcp.h"
21
22 #include "dlmapi.h"
23 #include "dlmcommon.h"
24 #include "dlmdomain.h"
25 #include "dlmdebug.h"
26
27 #define MLOG_MASK_PREFIX ML_DLM
28 #include "../cluster/masklog.h"
29
30 static int stringify_lockname(const char *lockname, int locklen, char *buf,
31                               int len);
32
33 void dlm_print_one_lock_resource(struct dlm_lock_resource *res)
34 {
35         spin_lock(&res->spinlock);
36         __dlm_print_one_lock_resource(res);
37         spin_unlock(&res->spinlock);
38 }
39
40 static void dlm_print_lockres_refmap(struct dlm_lock_resource *res)
41 {
42         int bit;
43         assert_spin_locked(&res->spinlock);
44
45         printk("  refmap nodes: [ ");
46         bit = 0;
47         while (1) {
48                 bit = find_next_bit(res->refmap, O2NM_MAX_NODES, bit);
49                 if (bit >= O2NM_MAX_NODES)
50                         break;
51                 printk("%u ", bit);
52                 bit++;
53         }
54         printk("], inflight=%u\n", res->inflight_locks);
55 }
56
57 static void __dlm_print_lock(struct dlm_lock *lock)
58 {
59         spin_lock(&lock->spinlock);
60
61         printk("    type=%d, conv=%d, node=%u, cookie=%u:%llu, "
62                "ref=%u, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c), "
63                "pending=(conv=%c,lock=%c,cancel=%c,unlock=%c)\n",
64                lock->ml.type, lock->ml.convert_type, lock->ml.node,
65                dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
66                dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
67                kref_read(&lock->lock_refs),
68                (list_empty(&lock->ast_list) ? 'y' : 'n'),
69                (lock->ast_pending ? 'y' : 'n'),
70                (list_empty(&lock->bast_list) ? 'y' : 'n'),
71                (lock->bast_pending ? 'y' : 'n'),
72                (lock->convert_pending ? 'y' : 'n'),
73                (lock->lock_pending ? 'y' : 'n'),
74                (lock->cancel_pending ? 'y' : 'n'),
75                (lock->unlock_pending ? 'y' : 'n'));
76
77         spin_unlock(&lock->spinlock);
78 }
79
80 void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
81 {
82         struct dlm_lock *lock;
83         char buf[DLM_LOCKID_NAME_MAX];
84
85         assert_spin_locked(&res->spinlock);
86
87         stringify_lockname(res->lockname.name, res->lockname.len,
88                            buf, sizeof(buf));
89         printk("lockres: %s, owner=%u, state=%u\n",
90                buf, res->owner, res->state);
91         printk("  last used: %lu, refcnt: %u, on purge list: %s\n",
92                res->last_used, kref_read(&res->refs),
93                list_empty(&res->purge) ? "no" : "yes");
94         printk("  on dirty list: %s, on reco list: %s, "
95                "migrating pending: %s\n",
96                list_empty(&res->dirty) ? "no" : "yes",
97                list_empty(&res->recovering) ? "no" : "yes",
98                res->migration_pending ? "yes" : "no");
99         printk("  inflight locks: %d, asts reserved: %d\n",
100                res->inflight_locks, atomic_read(&res->asts_reserved));
101         dlm_print_lockres_refmap(res);
102         printk("  granted queue:\n");
103         list_for_each_entry(lock, &res->granted, list) {
104                 __dlm_print_lock(lock);
105         }
106         printk("  converting queue:\n");
107         list_for_each_entry(lock, &res->converting, list) {
108                 __dlm_print_lock(lock);
109         }
110         printk("  blocked queue:\n");
111         list_for_each_entry(lock, &res->blocked, list) {
112                 __dlm_print_lock(lock);
113         }
114 }
115
116 void dlm_print_one_lock(struct dlm_lock *lockid)
117 {
118         dlm_print_one_lock_resource(lockid->lockres);
119 }
120 EXPORT_SYMBOL_GPL(dlm_print_one_lock);
121
122 static const char *dlm_errnames[] = {
123         [DLM_NORMAL] =                  "DLM_NORMAL",
124         [DLM_GRANTED] =                 "DLM_GRANTED",
125         [DLM_DENIED] =                  "DLM_DENIED",
126         [DLM_DENIED_NOLOCKS] =          "DLM_DENIED_NOLOCKS",
127         [DLM_WORKING] =                 "DLM_WORKING",
128         [DLM_BLOCKED] =                 "DLM_BLOCKED",
129         [DLM_BLOCKED_ORPHAN] =          "DLM_BLOCKED_ORPHAN",
130         [DLM_DENIED_GRACE_PERIOD] =     "DLM_DENIED_GRACE_PERIOD",
131         [DLM_SYSERR] =                  "DLM_SYSERR",
132         [DLM_NOSUPPORT] =               "DLM_NOSUPPORT",
133         [DLM_CANCELGRANT] =             "DLM_CANCELGRANT",
134         [DLM_IVLOCKID] =                "DLM_IVLOCKID",
135         [DLM_SYNC] =                    "DLM_SYNC",
136         [DLM_BADTYPE] =                 "DLM_BADTYPE",
137         [DLM_BADRESOURCE] =             "DLM_BADRESOURCE",
138         [DLM_MAXHANDLES] =              "DLM_MAXHANDLES",
139         [DLM_NOCLINFO] =                "DLM_NOCLINFO",
140         [DLM_NOLOCKMGR] =               "DLM_NOLOCKMGR",
141         [DLM_NOPURGED] =                "DLM_NOPURGED",
142         [DLM_BADARGS] =                 "DLM_BADARGS",
143         [DLM_VOID] =                    "DLM_VOID",
144         [DLM_NOTQUEUED] =               "DLM_NOTQUEUED",
145         [DLM_IVBUFLEN] =                "DLM_IVBUFLEN",
146         [DLM_CVTUNGRANT] =              "DLM_CVTUNGRANT",
147         [DLM_BADPARAM] =                "DLM_BADPARAM",
148         [DLM_VALNOTVALID] =             "DLM_VALNOTVALID",
149         [DLM_REJECTED] =                "DLM_REJECTED",
150         [DLM_ABORT] =                   "DLM_ABORT",
151         [DLM_CANCEL] =                  "DLM_CANCEL",
152         [DLM_IVRESHANDLE] =             "DLM_IVRESHANDLE",
153         [DLM_DEADLOCK] =                "DLM_DEADLOCK",
154         [DLM_DENIED_NOASTS] =           "DLM_DENIED_NOASTS",
155         [DLM_FORWARD] =                 "DLM_FORWARD",
156         [DLM_TIMEOUT] =                 "DLM_TIMEOUT",
157         [DLM_IVGROUPID] =               "DLM_IVGROUPID",
158         [DLM_VERS_CONFLICT] =           "DLM_VERS_CONFLICT",
159         [DLM_BAD_DEVICE_PATH] =         "DLM_BAD_DEVICE_PATH",
160         [DLM_NO_DEVICE_PERMISSION] =    "DLM_NO_DEVICE_PERMISSION",
161         [DLM_NO_CONTROL_DEVICE ] =      "DLM_NO_CONTROL_DEVICE ",
162         [DLM_RECOVERING] =              "DLM_RECOVERING",
163         [DLM_MIGRATING] =               "DLM_MIGRATING",
164         [DLM_MAXSTATS] =                "DLM_MAXSTATS",
165 };
166
167 const char *dlm_errname(enum dlm_status err)
168 {
169         if (err >= DLM_MAXSTATS || err < 0)
170                 return dlm_errnames[DLM_MAXSTATS];
171         return dlm_errnames[err];
172 }
173 EXPORT_SYMBOL_GPL(dlm_errname);
174
175 /* NOTE: This function converts a lockname into a string. It uses knowledge
176  * of the format of the lockname that should be outside the purview of the dlm.
177  * We are adding only to make dlm debugging slightly easier.
178  *
179  * For more on lockname formats, please refer to dlmglue.c and ocfs2_lockid.h.
180  */
181 static int stringify_lockname(const char *lockname, int locklen, char *buf,
182                               int len)
183 {
184         int out = 0;
185         __be64 inode_blkno_be;
186
187 #define OCFS2_DENTRY_LOCK_INO_START     18
188         if (*lockname == 'N') {
189                 memcpy((__be64 *)&inode_blkno_be,
190                        (char *)&lockname[OCFS2_DENTRY_LOCK_INO_START],
191                        sizeof(__be64));
192                 out += scnprintf(buf + out, len - out, "%.*s%08x",
193                                 OCFS2_DENTRY_LOCK_INO_START - 1, lockname,
194                                 (unsigned int)be64_to_cpu(inode_blkno_be));
195         } else
196                 out += scnprintf(buf + out, len - out, "%.*s",
197                                 locklen, lockname);
198         return out;
199 }
200
201 static int stringify_nodemap(unsigned long *nodemap, int maxnodes,
202                              char *buf, int len)
203 {
204         int out = 0;
205         int i = -1;
206
207         while ((i = find_next_bit(nodemap, maxnodes, i + 1)) < maxnodes)
208                 out += scnprintf(buf + out, len - out, "%d ", i);
209
210         return out;
211 }
212
213 static int dump_mle(struct dlm_master_list_entry *mle, char *buf, int len)
214 {
215         int out = 0;
216         char *mle_type;
217
218         if (mle->type == DLM_MLE_BLOCK)
219                 mle_type = "BLK";
220         else if (mle->type == DLM_MLE_MASTER)
221                 mle_type = "MAS";
222         else
223                 mle_type = "MIG";
224
225         out += stringify_lockname(mle->mname, mle->mnamelen, buf + out, len - out);
226         out += scnprintf(buf + out, len - out,
227                         "\t%3s\tmas=%3u\tnew=%3u\tevt=%1d\tuse=%1d\tref=%3d\n",
228                         mle_type, mle->master, mle->new_master,
229                         !list_empty(&mle->hb_events),
230                         !!mle->inuse,
231                         kref_read(&mle->mle_refs));
232
233         out += scnprintf(buf + out, len - out, "Maybe=");
234         out += stringify_nodemap(mle->maybe_map, O2NM_MAX_NODES,
235                                  buf + out, len - out);
236         out += scnprintf(buf + out, len - out, "\n");
237
238         out += scnprintf(buf + out, len - out, "Vote=");
239         out += stringify_nodemap(mle->vote_map, O2NM_MAX_NODES,
240                                  buf + out, len - out);
241         out += scnprintf(buf + out, len - out, "\n");
242
243         out += scnprintf(buf + out, len - out, "Response=");
244         out += stringify_nodemap(mle->response_map, O2NM_MAX_NODES,
245                                  buf + out, len - out);
246         out += scnprintf(buf + out, len - out, "\n");
247
248         out += scnprintf(buf + out, len - out, "Node=");
249         out += stringify_nodemap(mle->node_map, O2NM_MAX_NODES,
250                                  buf + out, len - out);
251         out += scnprintf(buf + out, len - out, "\n");
252
253         out += scnprintf(buf + out, len - out, "\n");
254
255         return out;
256 }
257
258 void dlm_print_one_mle(struct dlm_master_list_entry *mle)
259 {
260         char *buf;
261
262         buf = (char *) get_zeroed_page(GFP_ATOMIC);
263         if (buf) {
264                 dump_mle(mle, buf, PAGE_SIZE - 1);
265                 free_page((unsigned long)buf);
266         }
267 }
268
269 #ifdef CONFIG_DEBUG_FS
270
271 static struct dentry *dlm_debugfs_root;
272
273 #define DLM_DEBUGFS_DIR                         "o2dlm"
274 #define DLM_DEBUGFS_DLM_STATE                   "dlm_state"
275 #define DLM_DEBUGFS_LOCKING_STATE               "locking_state"
276 #define DLM_DEBUGFS_MLE_STATE                   "mle_state"
277 #define DLM_DEBUGFS_PURGE_LIST                  "purge_list"
278
279 /* begin - utils funcs */
280 static int debug_release(struct inode *inode, struct file *file)
281 {
282         free_page((unsigned long)file->private_data);
283         return 0;
284 }
285
286 static ssize_t debug_read(struct file *file, char __user *buf,
287                           size_t nbytes, loff_t *ppos)
288 {
289         return simple_read_from_buffer(buf, nbytes, ppos, file->private_data,
290                                        i_size_read(file->f_mapping->host));
291 }
292 /* end - util funcs */
293
294 /* begin - purge list funcs */
295 static int debug_purgelist_print(struct dlm_ctxt *dlm, char *buf, int len)
296 {
297         struct dlm_lock_resource *res;
298         int out = 0;
299         unsigned long total = 0;
300
301         out += scnprintf(buf + out, len - out,
302                         "Dumping Purgelist for Domain: %s\n", dlm->name);
303
304         spin_lock(&dlm->spinlock);
305         list_for_each_entry(res, &dlm->purge_list, purge) {
306                 ++total;
307                 if (len - out < 100)
308                         continue;
309                 spin_lock(&res->spinlock);
310                 out += stringify_lockname(res->lockname.name,
311                                           res->lockname.len,
312                                           buf + out, len - out);
313                 out += scnprintf(buf + out, len - out, "\t%ld\n",
314                                 (jiffies - res->last_used)/HZ);
315                 spin_unlock(&res->spinlock);
316         }
317         spin_unlock(&dlm->spinlock);
318
319         out += scnprintf(buf + out, len - out, "Total on list: %lu\n", total);
320
321         return out;
322 }
323
324 static int debug_purgelist_open(struct inode *inode, struct file *file)
325 {
326         struct dlm_ctxt *dlm = inode->i_private;
327         char *buf = NULL;
328
329         buf = (char *) get_zeroed_page(GFP_NOFS);
330         if (!buf)
331                 goto bail;
332
333         i_size_write(inode, debug_purgelist_print(dlm, buf, PAGE_SIZE - 1));
334
335         file->private_data = buf;
336
337         return 0;
338 bail:
339         return -ENOMEM;
340 }
341
342 static const struct file_operations debug_purgelist_fops = {
343         .open =         debug_purgelist_open,
344         .release =      debug_release,
345         .read =         debug_read,
346         .llseek =       generic_file_llseek,
347 };
348 /* end - purge list funcs */
349
350 /* begin - debug mle funcs */
351 static int debug_mle_print(struct dlm_ctxt *dlm, char *buf, int len)
352 {
353         struct dlm_master_list_entry *mle;
354         struct hlist_head *bucket;
355         int i, out = 0;
356         unsigned long total = 0, longest = 0, bucket_count = 0;
357
358         out += scnprintf(buf + out, len - out,
359                         "Dumping MLEs for Domain: %s\n", dlm->name);
360
361         spin_lock(&dlm->master_lock);
362         for (i = 0; i < DLM_HASH_BUCKETS; i++) {
363                 bucket = dlm_master_hash(dlm, i);
364                 hlist_for_each_entry(mle, bucket, master_hash_node) {
365                         ++total;
366                         ++bucket_count;
367                         if (len - out < 200)
368                                 continue;
369                         out += dump_mle(mle, buf + out, len - out);
370                 }
371                 longest = max(longest, bucket_count);
372                 bucket_count = 0;
373         }
374         spin_unlock(&dlm->master_lock);
375
376         out += scnprintf(buf + out, len - out,
377                         "Total: %lu, Longest: %lu\n", total, longest);
378         return out;
379 }
380
381 static int debug_mle_open(struct inode *inode, struct file *file)
382 {
383         struct dlm_ctxt *dlm = inode->i_private;
384         char *buf = NULL;
385
386         buf = (char *) get_zeroed_page(GFP_NOFS);
387         if (!buf)
388                 goto bail;
389
390         i_size_write(inode, debug_mle_print(dlm, buf, PAGE_SIZE - 1));
391
392         file->private_data = buf;
393
394         return 0;
395 bail:
396         return -ENOMEM;
397 }
398
399 static const struct file_operations debug_mle_fops = {
400         .open =         debug_mle_open,
401         .release =      debug_release,
402         .read =         debug_read,
403         .llseek =       generic_file_llseek,
404 };
405
406 /* end - debug mle funcs */
407
408 /* begin - debug lockres funcs */
409 static int dump_lock(struct dlm_lock *lock, int list_type, char *buf, int len)
410 {
411         int out;
412
413 #define DEBUG_LOCK_VERSION      1
414         spin_lock(&lock->spinlock);
415         out = scnprintf(buf, len, "LOCK:%d,%d,%d,%d,%d,%d:%lld,%d,%d,%d,%d,%d,"
416                        "%d,%d,%d,%d\n",
417                        DEBUG_LOCK_VERSION,
418                        list_type, lock->ml.type, lock->ml.convert_type,
419                        lock->ml.node,
420                        dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
421                        dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
422                        !list_empty(&lock->ast_list),
423                        !list_empty(&lock->bast_list),
424                        lock->ast_pending, lock->bast_pending,
425                        lock->convert_pending, lock->lock_pending,
426                        lock->cancel_pending, lock->unlock_pending,
427                        kref_read(&lock->lock_refs));
428         spin_unlock(&lock->spinlock);
429
430         return out;
431 }
432
433 static int dump_lockres(struct dlm_lock_resource *res, char *buf, int len)
434 {
435         struct dlm_lock *lock;
436         int i;
437         int out = 0;
438
439         out += scnprintf(buf + out, len - out, "NAME:");
440         out += stringify_lockname(res->lockname.name, res->lockname.len,
441                                   buf + out, len - out);
442         out += scnprintf(buf + out, len - out, "\n");
443
444 #define DEBUG_LRES_VERSION      1
445         out += scnprintf(buf + out, len - out,
446                         "LRES:%d,%d,%d,%ld,%d,%d,%d,%d,%d,%d,%d\n",
447                         DEBUG_LRES_VERSION,
448                         res->owner, res->state, res->last_used,
449                         !list_empty(&res->purge),
450                         !list_empty(&res->dirty),
451                         !list_empty(&res->recovering),
452                         res->inflight_locks, res->migration_pending,
453                         atomic_read(&res->asts_reserved),
454                         kref_read(&res->refs));
455
456         /* refmap */
457         out += scnprintf(buf + out, len - out, "RMAP:");
458         out += stringify_nodemap(res->refmap, O2NM_MAX_NODES,
459                                  buf + out, len - out);
460         out += scnprintf(buf + out, len - out, "\n");
461
462         /* lvb */
463         out += scnprintf(buf + out, len - out, "LVBX:");
464         for (i = 0; i < DLM_LVB_LEN; i++)
465                 out += scnprintf(buf + out, len - out,
466                                         "%02x", (unsigned char)res->lvb[i]);
467         out += scnprintf(buf + out, len - out, "\n");
468
469         /* granted */
470         list_for_each_entry(lock, &res->granted, list)
471                 out += dump_lock(lock, 0, buf + out, len - out);
472
473         /* converting */
474         list_for_each_entry(lock, &res->converting, list)
475                 out += dump_lock(lock, 1, buf + out, len - out);
476
477         /* blocked */
478         list_for_each_entry(lock, &res->blocked, list)
479                 out += dump_lock(lock, 2, buf + out, len - out);
480
481         out += scnprintf(buf + out, len - out, "\n");
482
483         return out;
484 }
485
486 static void *lockres_seq_start(struct seq_file *m, loff_t *pos)
487 {
488         struct debug_lockres *dl = m->private;
489         struct dlm_ctxt *dlm = dl->dl_ctxt;
490         struct dlm_lock_resource *oldres = dl->dl_res;
491         struct dlm_lock_resource *res = NULL, *iter;
492         struct list_head *track_list;
493
494         spin_lock(&dlm->track_lock);
495         if (oldres)
496                 track_list = &oldres->tracking;
497         else {
498                 track_list = &dlm->tracking_list;
499                 if (list_empty(track_list)) {
500                         dl = NULL;
501                         spin_unlock(&dlm->track_lock);
502                         goto bail;
503                 }
504         }
505
506         list_for_each_entry(iter, track_list, tracking) {
507                 if (&iter->tracking != &dlm->tracking_list) {
508                         dlm_lockres_get(iter);
509                         res = iter;
510                 }
511                 break;
512         }
513         spin_unlock(&dlm->track_lock);
514
515         if (oldres)
516                 dlm_lockres_put(oldres);
517
518         dl->dl_res = res;
519
520         if (res) {
521                 spin_lock(&res->spinlock);
522                 dump_lockres(res, dl->dl_buf, dl->dl_len - 1);
523                 spin_unlock(&res->spinlock);
524         } else
525                 dl = NULL;
526
527 bail:
528         /* passed to seq_show */
529         return dl;
530 }
531
532 static void lockres_seq_stop(struct seq_file *m, void *v)
533 {
534 }
535
536 static void *lockres_seq_next(struct seq_file *m, void *v, loff_t *pos)
537 {
538         return NULL;
539 }
540
541 static int lockres_seq_show(struct seq_file *s, void *v)
542 {
543         struct debug_lockres *dl = (struct debug_lockres *)v;
544
545         seq_printf(s, "%s", dl->dl_buf);
546
547         return 0;
548 }
549
550 static const struct seq_operations debug_lockres_ops = {
551         .start =        lockres_seq_start,
552         .stop =         lockres_seq_stop,
553         .next =         lockres_seq_next,
554         .show =         lockres_seq_show,
555 };
556
557 static int debug_lockres_open(struct inode *inode, struct file *file)
558 {
559         struct dlm_ctxt *dlm = inode->i_private;
560         struct debug_lockres *dl;
561         void *buf;
562
563         buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
564         if (!buf)
565                 goto bail;
566
567         dl = __seq_open_private(file, &debug_lockres_ops, sizeof(*dl));
568         if (!dl)
569                 goto bailfree;
570
571         dl->dl_len = PAGE_SIZE;
572         dl->dl_buf = buf;
573
574         dlm_grab(dlm);
575         dl->dl_ctxt = dlm;
576
577         return 0;
578
579 bailfree:
580         kfree(buf);
581 bail:
582         mlog_errno(-ENOMEM);
583         return -ENOMEM;
584 }
585
586 static int debug_lockres_release(struct inode *inode, struct file *file)
587 {
588         struct seq_file *seq = file->private_data;
589         struct debug_lockres *dl = (struct debug_lockres *)seq->private;
590
591         if (dl->dl_res)
592                 dlm_lockres_put(dl->dl_res);
593         dlm_put(dl->dl_ctxt);
594         kfree(dl->dl_buf);
595         return seq_release_private(inode, file);
596 }
597
598 static const struct file_operations debug_lockres_fops = {
599         .open =         debug_lockres_open,
600         .release =      debug_lockres_release,
601         .read =         seq_read,
602         .llseek =       seq_lseek,
603 };
604 /* end - debug lockres funcs */
605
606 /* begin - debug state funcs */
607 static int debug_state_print(struct dlm_ctxt *dlm, char *buf, int len)
608 {
609         int out = 0;
610         struct dlm_reco_node_data *node;
611         char *state;
612         int cur_mles = 0, tot_mles = 0;
613         int i;
614
615         spin_lock(&dlm->spinlock);
616
617         switch (dlm->dlm_state) {
618         case DLM_CTXT_NEW:
619                 state = "NEW"; break;
620         case DLM_CTXT_JOINED:
621                 state = "JOINED"; break;
622         case DLM_CTXT_IN_SHUTDOWN:
623                 state = "SHUTDOWN"; break;
624         case DLM_CTXT_LEAVING:
625                 state = "LEAVING"; break;
626         default:
627                 state = "UNKNOWN"; break;
628         }
629
630         /* Domain: xxxxxxxxxx  Key: 0xdfbac769 */
631         out += scnprintf(buf + out, len - out,
632                         "Domain: %s  Key: 0x%08x  Protocol: %d.%d\n",
633                         dlm->name, dlm->key, dlm->dlm_locking_proto.pv_major,
634                         dlm->dlm_locking_proto.pv_minor);
635
636         /* Thread Pid: xxx  Node: xxx  State: xxxxx */
637         out += scnprintf(buf + out, len - out,
638                         "Thread Pid: %d  Node: %d  State: %s\n",
639                         task_pid_nr(dlm->dlm_thread_task), dlm->node_num, state);
640
641         /* Number of Joins: xxx  Joining Node: xxx */
642         out += scnprintf(buf + out, len - out,
643                         "Number of Joins: %d  Joining Node: %d\n",
644                         dlm->num_joins, dlm->joining_node);
645
646         /* Domain Map: xx xx xx */
647         out += scnprintf(buf + out, len - out, "Domain Map: ");
648         out += stringify_nodemap(dlm->domain_map, O2NM_MAX_NODES,
649                                  buf + out, len - out);
650         out += scnprintf(buf + out, len - out, "\n");
651
652         /* Exit Domain Map: xx xx xx */
653         out += scnprintf(buf + out, len - out, "Exit Domain Map: ");
654         out += stringify_nodemap(dlm->exit_domain_map, O2NM_MAX_NODES,
655                                  buf + out, len - out);
656         out += scnprintf(buf + out, len - out, "\n");
657
658         /* Live Map: xx xx xx */
659         out += scnprintf(buf + out, len - out, "Live Map: ");
660         out += stringify_nodemap(dlm->live_nodes_map, O2NM_MAX_NODES,
661                                  buf + out, len - out);
662         out += scnprintf(buf + out, len - out, "\n");
663
664         /* Lock Resources: xxx (xxx) */
665         out += scnprintf(buf + out, len - out,
666                         "Lock Resources: %d (%d)\n",
667                         atomic_read(&dlm->res_cur_count),
668                         atomic_read(&dlm->res_tot_count));
669
670         for (i = 0; i < DLM_MLE_NUM_TYPES; ++i)
671                 tot_mles += atomic_read(&dlm->mle_tot_count[i]);
672
673         for (i = 0; i < DLM_MLE_NUM_TYPES; ++i)
674                 cur_mles += atomic_read(&dlm->mle_cur_count[i]);
675
676         /* MLEs: xxx (xxx) */
677         out += scnprintf(buf + out, len - out,
678                         "MLEs: %d (%d)\n", cur_mles, tot_mles);
679
680         /*  Blocking: xxx (xxx) */
681         out += scnprintf(buf + out, len - out,
682                         "  Blocking: %d (%d)\n",
683                         atomic_read(&dlm->mle_cur_count[DLM_MLE_BLOCK]),
684                         atomic_read(&dlm->mle_tot_count[DLM_MLE_BLOCK]));
685
686         /*  Mastery: xxx (xxx) */
687         out += scnprintf(buf + out, len - out,
688                         "  Mastery: %d (%d)\n",
689                         atomic_read(&dlm->mle_cur_count[DLM_MLE_MASTER]),
690                         atomic_read(&dlm->mle_tot_count[DLM_MLE_MASTER]));
691
692         /*  Migration: xxx (xxx) */
693         out += scnprintf(buf + out, len - out,
694                         "  Migration: %d (%d)\n",
695                         atomic_read(&dlm->mle_cur_count[DLM_MLE_MIGRATION]),
696                         atomic_read(&dlm->mle_tot_count[DLM_MLE_MIGRATION]));
697
698         /* Lists: Dirty=Empty  Purge=InUse  PendingASTs=Empty  ... */
699         out += scnprintf(buf + out, len - out,
700                         "Lists: Dirty=%s  Purge=%s  PendingASTs=%s  "
701                         "PendingBASTs=%s\n",
702                         (list_empty(&dlm->dirty_list) ? "Empty" : "InUse"),
703                         (list_empty(&dlm->purge_list) ? "Empty" : "InUse"),
704                         (list_empty(&dlm->pending_asts) ? "Empty" : "InUse"),
705                         (list_empty(&dlm->pending_basts) ? "Empty" : "InUse"));
706
707         /* Purge Count: xxx  Refs: xxx */
708         out += scnprintf(buf + out, len - out,
709                         "Purge Count: %d  Refs: %d\n", dlm->purge_count,
710                         kref_read(&dlm->dlm_refs));
711
712         /* Dead Node: xxx */
713         out += scnprintf(buf + out, len - out,
714                         "Dead Node: %d\n", dlm->reco.dead_node);
715
716         /* What about DLM_RECO_STATE_FINALIZE? */
717         if (dlm->reco.state == DLM_RECO_STATE_ACTIVE)
718                 state = "ACTIVE";
719         else
720                 state = "INACTIVE";
721
722         /* Recovery Pid: xxxx  Master: xxx  State: xxxx */
723         out += scnprintf(buf + out, len - out,
724                         "Recovery Pid: %d  Master: %d  State: %s\n",
725                         task_pid_nr(dlm->dlm_reco_thread_task),
726                         dlm->reco.new_master, state);
727
728         /* Recovery Map: xx xx */
729         out += scnprintf(buf + out, len - out, "Recovery Map: ");
730         out += stringify_nodemap(dlm->recovery_map, O2NM_MAX_NODES,
731                                  buf + out, len - out);
732         out += scnprintf(buf + out, len - out, "\n");
733
734         /* Recovery Node State: */
735         out += scnprintf(buf + out, len - out, "Recovery Node State:\n");
736         list_for_each_entry(node, &dlm->reco.node_data, list) {
737                 switch (node->state) {
738                 case DLM_RECO_NODE_DATA_INIT:
739                         state = "INIT";
740                         break;
741                 case DLM_RECO_NODE_DATA_REQUESTING:
742                         state = "REQUESTING";
743                         break;
744                 case DLM_RECO_NODE_DATA_DEAD:
745                         state = "DEAD";
746                         break;
747                 case DLM_RECO_NODE_DATA_RECEIVING:
748                         state = "RECEIVING";
749                         break;
750                 case DLM_RECO_NODE_DATA_REQUESTED:
751                         state = "REQUESTED";
752                         break;
753                 case DLM_RECO_NODE_DATA_DONE:
754                         state = "DONE";
755                         break;
756                 case DLM_RECO_NODE_DATA_FINALIZE_SENT:
757                         state = "FINALIZE-SENT";
758                         break;
759                 default:
760                         state = "BAD";
761                         break;
762                 }
763                 out += scnprintf(buf + out, len - out, "\t%u - %s\n",
764                                 node->node_num, state);
765         }
766
767         spin_unlock(&dlm->spinlock);
768
769         return out;
770 }
771
772 static int debug_state_open(struct inode *inode, struct file *file)
773 {
774         struct dlm_ctxt *dlm = inode->i_private;
775         char *buf = NULL;
776
777         buf = (char *) get_zeroed_page(GFP_NOFS);
778         if (!buf)
779                 goto bail;
780
781         i_size_write(inode, debug_state_print(dlm, buf, PAGE_SIZE - 1));
782
783         file->private_data = buf;
784
785         return 0;
786 bail:
787         return -ENOMEM;
788 }
789
790 static const struct file_operations debug_state_fops = {
791         .open =         debug_state_open,
792         .release =      debug_release,
793         .read =         debug_read,
794         .llseek =       generic_file_llseek,
795 };
796 /* end  - debug state funcs */
797
798 /* files in subroot */
799 void dlm_debug_init(struct dlm_ctxt *dlm)
800 {
801         /* for dumping dlm_ctxt */
802         debugfs_create_file(DLM_DEBUGFS_DLM_STATE, S_IFREG|S_IRUSR,
803                             dlm->dlm_debugfs_subroot, dlm, &debug_state_fops);
804
805         /* for dumping lockres */
806         debugfs_create_file(DLM_DEBUGFS_LOCKING_STATE, S_IFREG|S_IRUSR,
807                             dlm->dlm_debugfs_subroot, dlm, &debug_lockres_fops);
808
809         /* for dumping mles */
810         debugfs_create_file(DLM_DEBUGFS_MLE_STATE, S_IFREG|S_IRUSR,
811                             dlm->dlm_debugfs_subroot, dlm, &debug_mle_fops);
812
813         /* for dumping lockres on the purge list */
814         debugfs_create_file(DLM_DEBUGFS_PURGE_LIST, S_IFREG|S_IRUSR,
815                             dlm->dlm_debugfs_subroot, dlm,
816                             &debug_purgelist_fops);
817 }
818
819 /* subroot - domain dir */
820 void dlm_create_debugfs_subroot(struct dlm_ctxt *dlm)
821 {
822         dlm->dlm_debugfs_subroot = debugfs_create_dir(dlm->name,
823                                                       dlm_debugfs_root);
824 }
825
826 void dlm_destroy_debugfs_subroot(struct dlm_ctxt *dlm)
827 {
828         debugfs_remove_recursive(dlm->dlm_debugfs_subroot);
829 }
830
831 /* debugfs root */
832 void dlm_create_debugfs_root(void)
833 {
834         dlm_debugfs_root = debugfs_create_dir(DLM_DEBUGFS_DIR, NULL);
835 }
836
837 void dlm_destroy_debugfs_root(void)
838 {
839         debugfs_remove(dlm_debugfs_root);
840 }
841 #endif  /* CONFIG_DEBUG_FS */
This page took 0.07889 seconds and 4 git commands to generate.