OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [dlm/] [debug_fs.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/******************************************************************************
2
*******************************************************************************
3
**
4
**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
5
**
6
**  This copyrighted material is made available to anyone wishing to use,
7
**  modify, copy, or redistribute it subject to the terms and conditions
8
**  of the GNU General Public License v.2.
9
**
10
*******************************************************************************
11
******************************************************************************/
12
 
13
#include <linux/pagemap.h>
14
#include <linux/seq_file.h>
15
#include <linux/module.h>
16
#include <linux/ctype.h>
17
#include <linux/debugfs.h>
18
 
19
#include "dlm_internal.h"
20
#include "lock.h"
21
 
22
#define DLM_DEBUG_BUF_LEN 4096
23
static char debug_buf[DLM_DEBUG_BUF_LEN];
24
static struct mutex debug_buf_lock;
25
 
26
static struct dentry *dlm_root;
27
 
28
struct rsb_iter {
29
        int entry;
30
        int locks;
31
        int header;
32
        struct dlm_ls *ls;
33
        struct list_head *next;
34
        struct dlm_rsb *rsb;
35
};
36
 
37
/*
38
 * dump all rsb's in the lockspace hash table
39
 */
40
 
41
static char *print_lockmode(int mode)
42
{
43
        switch (mode) {
44
        case DLM_LOCK_IV:
45
                return "--";
46
        case DLM_LOCK_NL:
47
                return "NL";
48
        case DLM_LOCK_CR:
49
                return "CR";
50
        case DLM_LOCK_CW:
51
                return "CW";
52
        case DLM_LOCK_PR:
53
                return "PR";
54
        case DLM_LOCK_PW:
55
                return "PW";
56
        case DLM_LOCK_EX:
57
                return "EX";
58
        default:
59
                return "??";
60
        }
61
}
62
 
63
static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
64
                                struct dlm_rsb *res)
65
{
66
        seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
67
 
68
        if (lkb->lkb_status == DLM_LKSTS_CONVERT
69
            || lkb->lkb_status == DLM_LKSTS_WAITING)
70
                seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
71
 
72
        if (lkb->lkb_nodeid) {
73
                if (lkb->lkb_nodeid != res->res_nodeid)
74
                        seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid,
75
                                   lkb->lkb_remid);
76
                else
77
                        seq_printf(s, " Master:     %08x", lkb->lkb_remid);
78
        }
79
 
80
        if (lkb->lkb_wait_type)
81
                seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
82
 
83
        seq_printf(s, "\n");
84
}
85
 
86
static int print_resource(struct dlm_rsb *res, struct seq_file *s)
87
{
88
        struct dlm_lkb *lkb;
89
        int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
90
 
91
        lock_rsb(res);
92
 
93
        seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
94
        for (i = 0; i < res->res_length; i++) {
95
                if (isprint(res->res_name[i]))
96
                        seq_printf(s, "%c", res->res_name[i]);
97
                else
98
                        seq_printf(s, "%c", '.');
99
        }
100
        if (res->res_nodeid > 0)
101
                seq_printf(s, "\"  \nLocal Copy, Master is node %d\n",
102
                           res->res_nodeid);
103
        else if (res->res_nodeid == 0)
104
                seq_printf(s, "\"  \nMaster Copy\n");
105
        else if (res->res_nodeid == -1)
106
                seq_printf(s, "\"  \nLooking up master (lkid %x)\n",
107
                           res->res_first_lkid);
108
        else
109
                seq_printf(s, "\"  \nInvalid master %d\n", res->res_nodeid);
110
 
111
        /* Print the LVB: */
112
        if (res->res_lvbptr) {
113
                seq_printf(s, "LVB: ");
114
                for (i = 0; i < lvblen; i++) {
115
                        if (i == lvblen / 2)
116
                                seq_printf(s, "\n     ");
117
                        seq_printf(s, "%02x ",
118
                                   (unsigned char) res->res_lvbptr[i]);
119
                }
120
                if (rsb_flag(res, RSB_VALNOTVALID))
121
                        seq_printf(s, " (INVALID)");
122
                seq_printf(s, "\n");
123
        }
124
 
125
        root_list = !list_empty(&res->res_root_list);
126
        recover_list = !list_empty(&res->res_recover_list);
127
 
128
        if (root_list || recover_list) {
129
                seq_printf(s, "Recovery: root %d recover %d flags %lx "
130
                           "count %d\n", root_list, recover_list,
131
                           res->res_flags, res->res_recover_locks_count);
132
        }
133
 
134
        /* Print the locks attached to this resource */
135
        seq_printf(s, "Granted Queue\n");
136
        list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
137
                print_resource_lock(s, lkb, res);
138
 
139
        seq_printf(s, "Conversion Queue\n");
140
        list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
141
                print_resource_lock(s, lkb, res);
142
 
143
        seq_printf(s, "Waiting Queue\n");
144
        list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
145
                print_resource_lock(s, lkb, res);
146
 
147
        if (list_empty(&res->res_lookup))
148
                goto out;
149
 
150
        seq_printf(s, "Lookup Queue\n");
151
        list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
152
                seq_printf(s, "%08x %s", lkb->lkb_id,
153
                           print_lockmode(lkb->lkb_rqmode));
154
                if (lkb->lkb_wait_type)
155
                        seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
156
                seq_printf(s, "\n");
157
        }
158
 out:
159
        unlock_rsb(res);
160
        return 0;
161
}
162
 
163
static 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
 
198
static 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);
214
        return 0;
215
}
216
 
217
static int rsb_iter_next(struct rsb_iter *ri)
218
{
219
        struct dlm_ls *ls = ri->ls;
220
        int i;
221
 
222
        if (!ri->next) {
223
 top:
224
                /* Find the next non-empty hash bucket */
225
                for (i = ri->entry; i < ls->ls_rsbtbl_size; i++) {
226
                        read_lock(&ls->ls_rsbtbl[i].lock);
227
                        if (!list_empty(&ls->ls_rsbtbl[i].list)) {
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);
232
                                read_unlock(&ls->ls_rsbtbl[i].lock);
233
                                break;
234
                        }
235
                        read_unlock(&ls->ls_rsbtbl[i].lock);
236
                }
237
                ri->entry = i;
238
 
239
                if (ri->entry >= ls->ls_rsbtbl_size)
240
                        return 1;
241
        } else {
242
                struct dlm_rsb *old = ri->rsb;
243
                i = ri->entry;
244
                read_lock(&ls->ls_rsbtbl[i].lock);
245
                ri->next = ri->next->next;
246
                if (ri->next->next == ls->ls_rsbtbl[i].list.next) {
247
                        /* End of list - move to next bucket */
248
                        ri->next = NULL;
249
                        ri->entry++;
250
                        read_unlock(&ls->ls_rsbtbl[i].lock);
251
                        dlm_put_rsb(old);
252
                        goto top;
253
                }
254
                ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
255
                dlm_hold_rsb(ri->rsb);
256
                read_unlock(&ls->ls_rsbtbl[i].lock);
257
                dlm_put_rsb(old);
258
        }
259
 
260
        return 0;
261
}
262
 
263
static void rsb_iter_free(struct rsb_iter *ri)
264
{
265
        kfree(ri);
266
}
267
 
268
static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
269
{
270
        struct rsb_iter *ri;
271
 
272
        ri = kzalloc(sizeof *ri, GFP_KERNEL);
273
        if (!ri)
274
                return NULL;
275
 
276
        ri->ls = ls;
277
        ri->entry = 0;
278
        ri->next = NULL;
279
 
280
        if (rsb_iter_next(ri)) {
281
                rsb_iter_free(ri);
282
                return NULL;
283
        }
284
 
285
        return ri;
286
}
287
 
288
static void *rsb_seq_start(struct seq_file *file, loff_t *pos)
289
{
290
        struct rsb_iter *ri;
291
        loff_t n = *pos;
292
 
293
        ri = rsb_iter_init(file->private);
294
        if (!ri)
295
                return NULL;
296
 
297
        while (n--) {
298
                if (rsb_iter_next(ri)) {
299
                        rsb_iter_free(ri);
300
                        return NULL;
301
                }
302
        }
303
 
304
        return ri;
305
}
306
 
307
static void *rsb_seq_next(struct seq_file *file, void *iter_ptr, loff_t *pos)
308
{
309
        struct rsb_iter *ri = iter_ptr;
310
 
311
        (*pos)++;
312
 
313
        if (rsb_iter_next(ri)) {
314
                rsb_iter_free(ri);
315
                return NULL;
316
        }
317
 
318
        return ri;
319
}
320
 
321
static void rsb_seq_stop(struct seq_file *file, void *iter_ptr)
322
{
323
        /* nothing for now */
324
}
325
 
326
static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
327
{
328
        struct rsb_iter *ri = iter_ptr;
329
 
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
        }
341
 
342
        return 0;
343
}
344
 
345
static struct seq_operations rsb_seq_ops = {
346
        .start = rsb_seq_start,
347
        .next  = rsb_seq_next,
348
        .stop  = rsb_seq_stop,
349
        .show  = rsb_seq_show,
350
};
351
 
352
static int rsb_open(struct inode *inode, struct file *file)
353
{
354
        struct seq_file *seq;
355
        int ret;
356
 
357
        ret = seq_open(file, &rsb_seq_ops);
358
        if (ret)
359
                return ret;
360
 
361
        seq = file->private_data;
362
        seq->private = inode->i_private;
363
 
364
        return 0;
365
}
366
 
367
static const struct file_operations rsb_fops = {
368
        .owner   = THIS_MODULE,
369
        .open    = rsb_open,
370
        .read    = seq_read,
371
        .llseek  = seq_lseek,
372
        .release = seq_release
373
};
374
 
375
/*
376
 * Dump state in compact per-lock listing
377
 */
378
 
379
static 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
 
403
static 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
 
422
static 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
 
429
static 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
 
444
static 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
/*
453
 * dump lkb's on the ls_waiters list
454
 */
455
 
456
static int waiters_open(struct inode *inode, struct file *file)
457
{
458
        file->private_data = inode->i_private;
459
        return 0;
460
}
461
 
462
static ssize_t waiters_read(struct file *file, char __user *userbuf,
463
                            size_t count, loff_t *ppos)
464
{
465
        struct dlm_ls *ls = file->private_data;
466
        struct dlm_lkb *lkb;
467
        size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
468
 
469
        mutex_lock(&debug_buf_lock);
470
        mutex_lock(&ls->ls_waiters_mutex);
471
        memset(debug_buf, 0, sizeof(debug_buf));
472
 
473
        list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
474
                ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
475
                               lkb->lkb_id, lkb->lkb_wait_type,
476
                               lkb->lkb_nodeid, lkb->lkb_resource->res_name);
477
                if (ret >= len - pos)
478
                        break;
479
                pos += ret;
480
        }
481
        mutex_unlock(&ls->ls_waiters_mutex);
482
 
483
        rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
484
        mutex_unlock(&debug_buf_lock);
485
        return rv;
486
}
487
 
488
static const struct file_operations waiters_fops = {
489
        .owner   = THIS_MODULE,
490
        .open    = waiters_open,
491
        .read    = waiters_read
492
};
493
 
494
int dlm_create_debug_file(struct dlm_ls *ls)
495
{
496
        char name[DLM_LOCKSPACE_LEN+8];
497
 
498
        ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
499
                                                      S_IFREG | S_IRUGO,
500
                                                      dlm_root,
501
                                                      ls,
502
                                                      &rsb_fops);
503
        if (!ls->ls_debug_rsb_dentry)
504
                return -ENOMEM;
505
 
506
        memset(name, 0, sizeof(name));
507
        snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_waiters", ls->ls_name);
508
 
509
        ls->ls_debug_waiters_dentry = debugfs_create_file(name,
510
                                                          S_IFREG | S_IRUGO,
511
                                                          dlm_root,
512
                                                          ls,
513
                                                          &waiters_fops);
514
        if (!ls->ls_debug_waiters_dentry) {
515
                debugfs_remove(ls->ls_debug_rsb_dentry);
516
                return -ENOMEM;
517
        }
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
 
533
        return 0;
534
}
535
 
536
void dlm_delete_debug_file(struct dlm_ls *ls)
537
{
538
        if (ls->ls_debug_rsb_dentry)
539
                debugfs_remove(ls->ls_debug_rsb_dentry);
540
        if (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);
544
}
545
 
546
int dlm_register_debugfs(void)
547
{
548
        mutex_init(&debug_buf_lock);
549
        dlm_root = debugfs_create_dir("dlm", NULL);
550
        return dlm_root ? 0 : -ENOMEM;
551
}
552
 
553
void dlm_unregister_debugfs(void)
554
{
555
        debugfs_remove(dlm_root);
556
}
557
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.