12522fe45SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e7fd4179SDavid Teigland /******************************************************************************
3e7fd4179SDavid Teigland *******************************************************************************
4e7fd4179SDavid Teigland **
5892c4467SDavid Teigland ** Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved.
6e7fd4179SDavid Teigland **
7e7fd4179SDavid Teigland **
8e7fd4179SDavid Teigland *******************************************************************************
9e7fd4179SDavid Teigland ******************************************************************************/
10e7fd4179SDavid Teigland
11e7fd4179SDavid Teigland #include <linux/pagemap.h>
12e7fd4179SDavid Teigland #include <linux/seq_file.h>
137963b8a5SPaul Gortmaker #include <linux/init.h>
14e7fd4179SDavid Teigland #include <linux/ctype.h>
15e7fd4179SDavid Teigland #include <linux/debugfs.h>
165a0e3ad6STejun Heo #include <linux/slab.h>
17e7fd4179SDavid Teigland
18e7fd4179SDavid Teigland #include "dlm_internal.h"
195b2f981fSAlexander Aring #include "midcomms.h"
20916297aaSJosef Bacik #include "lock.h"
21541adb0dSAlexander Aring #include "ast.h"
22e7fd4179SDavid Teigland
235de6319bSDavid Teigland #define DLM_DEBUG_BUF_LEN 4096
245de6319bSDavid Teigland static char debug_buf[DLM_DEBUG_BUF_LEN];
255de6319bSDavid Teigland static struct mutex debug_buf_lock;
26e7fd4179SDavid Teigland
27e7fd4179SDavid Teigland static struct dentry *dlm_root;
285b2f981fSAlexander Aring static struct dentry *dlm_comms;
29e7fd4179SDavid Teigland
print_lockmode(int mode)30e7fd4179SDavid Teigland static char *print_lockmode(int mode)
31e7fd4179SDavid Teigland {
32e7fd4179SDavid Teigland switch (mode) {
33e7fd4179SDavid Teigland case DLM_LOCK_IV:
34e7fd4179SDavid Teigland return "--";
35e7fd4179SDavid Teigland case DLM_LOCK_NL:
36e7fd4179SDavid Teigland return "NL";
37e7fd4179SDavid Teigland case DLM_LOCK_CR:
38e7fd4179SDavid Teigland return "CR";
39e7fd4179SDavid Teigland case DLM_LOCK_CW:
40e7fd4179SDavid Teigland return "CW";
41e7fd4179SDavid Teigland case DLM_LOCK_PR:
42e7fd4179SDavid Teigland return "PR";
43e7fd4179SDavid Teigland case DLM_LOCK_PW:
44e7fd4179SDavid Teigland return "PW";
45e7fd4179SDavid Teigland case DLM_LOCK_EX:
46e7fd4179SDavid Teigland return "EX";
47e7fd4179SDavid Teigland default:
48e7fd4179SDavid Teigland return "??";
49e7fd4179SDavid Teigland }
50e7fd4179SDavid Teigland }
51e7fd4179SDavid Teigland
print_format1_lock(struct seq_file * s,struct dlm_lkb * lkb,struct dlm_rsb * res)52d6d906b2SJoe Perches static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
53e7fd4179SDavid Teigland struct dlm_rsb *res)
54e7fd4179SDavid Teigland {
55e7fd4179SDavid Teigland seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
56e7fd4179SDavid Teigland
57892c4467SDavid Teigland if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
58892c4467SDavid Teigland lkb->lkb_status == DLM_LKSTS_WAITING)
59e7fd4179SDavid Teigland seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
60e7fd4179SDavid Teigland
61e7fd4179SDavid Teigland if (lkb->lkb_nodeid) {
62e7fd4179SDavid Teigland if (lkb->lkb_nodeid != res->res_nodeid)
63e7fd4179SDavid Teigland seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid,
64e7fd4179SDavid Teigland lkb->lkb_remid);
65e7fd4179SDavid Teigland else
66e7fd4179SDavid Teigland seq_printf(s, " Master: %08x", lkb->lkb_remid);
67e7fd4179SDavid Teigland }
68e7fd4179SDavid Teigland
69e7fd4179SDavid Teigland if (lkb->lkb_wait_type)
70e7fd4179SDavid Teigland seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
71e7fd4179SDavid Teigland
72653996caSMarkus Elfring seq_putc(s, '\n');
73e7fd4179SDavid Teigland }
74e7fd4179SDavid Teigland
print_format1(struct dlm_rsb * res,struct seq_file * s)75d6d906b2SJoe Perches static void print_format1(struct dlm_rsb *res, struct seq_file *s)
76e7fd4179SDavid Teigland {
77e7fd4179SDavid Teigland struct dlm_lkb *lkb;
785de6319bSDavid Teigland int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
79e7fd4179SDavid Teigland
809dd592d7SDavid Teigland lock_rsb(res);
819dd592d7SDavid Teigland
82d6d906b2SJoe Perches seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
83892c4467SDavid Teigland
84e7fd4179SDavid Teigland for (i = 0; i < res->res_length; i++) {
85e7fd4179SDavid Teigland if (isprint(res->res_name[i]))
86e7fd4179SDavid Teigland seq_printf(s, "%c", res->res_name[i]);
87e7fd4179SDavid Teigland else
88e7fd4179SDavid Teigland seq_printf(s, "%c", '.');
89e7fd4179SDavid Teigland }
90892c4467SDavid Teigland
91e7fd4179SDavid Teigland if (res->res_nodeid > 0)
92d6d906b2SJoe Perches seq_printf(s, "\"\nLocal Copy, Master is node %d\n",
93e7fd4179SDavid Teigland res->res_nodeid);
94e7fd4179SDavid Teigland else if (res->res_nodeid == 0)
95d6d906b2SJoe Perches seq_puts(s, "\"\nMaster Copy\n");
96e7fd4179SDavid Teigland else if (res->res_nodeid == -1)
97d6d906b2SJoe Perches seq_printf(s, "\"\nLooking up master (lkid %x)\n",
98e7fd4179SDavid Teigland res->res_first_lkid);
99e7fd4179SDavid Teigland else
100d6d906b2SJoe Perches seq_printf(s, "\"\nInvalid master %d\n", res->res_nodeid);
101d6d906b2SJoe Perches if (seq_has_overflowed(s))
102892c4467SDavid Teigland goto out;
103e7fd4179SDavid Teigland
104e7fd4179SDavid Teigland /* Print the LVB: */
105e7fd4179SDavid Teigland if (res->res_lvbptr) {
106c1d4518cSFabian Frederick seq_puts(s, "LVB: ");
107e7fd4179SDavid Teigland for (i = 0; i < lvblen; i++) {
108e7fd4179SDavid Teigland if (i == lvblen / 2)
109c1d4518cSFabian Frederick seq_puts(s, "\n ");
110e7fd4179SDavid Teigland seq_printf(s, "%02x ",
111e7fd4179SDavid Teigland (unsigned char) res->res_lvbptr[i]);
112e7fd4179SDavid Teigland }
113e7fd4179SDavid Teigland if (rsb_flag(res, RSB_VALNOTVALID))
114c1d4518cSFabian Frederick seq_puts(s, " (INVALID)");
115653996caSMarkus Elfring seq_putc(s, '\n');
116d6d906b2SJoe Perches if (seq_has_overflowed(s))
117892c4467SDavid Teigland goto out;
118e7fd4179SDavid Teigland }
119e7fd4179SDavid Teigland
1205de6319bSDavid Teigland root_list = !list_empty(&res->res_root_list);
1215de6319bSDavid Teigland recover_list = !list_empty(&res->res_recover_list);
1225de6319bSDavid Teigland
1235de6319bSDavid Teigland if (root_list || recover_list) {
124d6d906b2SJoe Perches seq_printf(s, "Recovery: root %d recover %d flags %lx count %d\n",
125d6d906b2SJoe Perches root_list, recover_list,
12620abf975SDavid Teigland res->res_flags, res->res_recover_locks_count);
1275de6319bSDavid Teigland }
1285de6319bSDavid Teigland
129e7fd4179SDavid Teigland /* Print the locks attached to this resource */
130c1d4518cSFabian Frederick seq_puts(s, "Granted Queue\n");
131892c4467SDavid Teigland list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
132d6d906b2SJoe Perches print_format1_lock(s, lkb, res);
133d6d906b2SJoe Perches if (seq_has_overflowed(s))
134892c4467SDavid Teigland goto out;
135892c4467SDavid Teigland }
136e7fd4179SDavid Teigland
137c1d4518cSFabian Frederick seq_puts(s, "Conversion Queue\n");
138892c4467SDavid Teigland list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
139d6d906b2SJoe Perches print_format1_lock(s, lkb, res);
140d6d906b2SJoe Perches if (seq_has_overflowed(s))
141892c4467SDavid Teigland goto out;
142892c4467SDavid Teigland }
143e7fd4179SDavid Teigland
144c1d4518cSFabian Frederick seq_puts(s, "Waiting Queue\n");
145892c4467SDavid Teigland list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
146d6d906b2SJoe Perches print_format1_lock(s, lkb, res);
147d6d906b2SJoe Perches if (seq_has_overflowed(s))
148892c4467SDavid Teigland goto out;
149892c4467SDavid Teigland }
150e7fd4179SDavid Teigland
1515de6319bSDavid Teigland if (list_empty(&res->res_lookup))
1525de6319bSDavid Teigland goto out;
1535de6319bSDavid Teigland
154c1d4518cSFabian Frederick seq_puts(s, "Lookup Queue\n");
1555de6319bSDavid Teigland list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
156d6d906b2SJoe Perches seq_printf(s, "%08x %s",
157d6d906b2SJoe Perches lkb->lkb_id, print_lockmode(lkb->lkb_rqmode));
1585de6319bSDavid Teigland if (lkb->lkb_wait_type)
1595de6319bSDavid Teigland seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
160653996caSMarkus Elfring seq_putc(s, '\n');
161d6d906b2SJoe Perches if (seq_has_overflowed(s))
162d6d906b2SJoe Perches goto out;
1635de6319bSDavid Teigland }
1645de6319bSDavid Teigland out:
1659dd592d7SDavid Teigland unlock_rsb(res);
1669dd592d7SDavid Teigland }
1679dd592d7SDavid Teigland
print_format2_lock(struct seq_file * s,struct dlm_lkb * lkb,struct dlm_rsb * r)168d6d906b2SJoe Perches static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
169d022509dSDavid Teigland struct dlm_rsb *r)
1709dd592d7SDavid Teigland {
171eeda418dSDavid Teigland u64 xid = 0;
172eeda418dSDavid Teigland u64 us;
1739dd592d7SDavid Teigland
1748a39dcd9SAlexander Aring if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) {
175d292c0ccSDavid Teigland if (lkb->lkb_ua)
176d292c0ccSDavid Teigland xid = lkb->lkb_ua->xid;
1779dd592d7SDavid Teigland }
1789dd592d7SDavid Teigland
179eeda418dSDavid Teigland /* microseconds since lkb was added to current queue */
180eeda418dSDavid Teigland us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
1819dd592d7SDavid Teigland
182eeda418dSDavid Teigland /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
183ac90a255SDavid Teigland r_nodeid r_len r_name */
1849dd592d7SDavid Teigland
185d6d906b2SJoe Perches seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
1869dd592d7SDavid Teigland lkb->lkb_id,
1879dd592d7SDavid Teigland lkb->lkb_nodeid,
1889dd592d7SDavid Teigland lkb->lkb_remid,
1899dd592d7SDavid Teigland lkb->lkb_ownpid,
1909dd592d7SDavid Teigland (unsigned long long)xid,
1919dd592d7SDavid Teigland lkb->lkb_exflags,
192e1af8728SAlexander Aring dlm_iflags_val(lkb),
1939dd592d7SDavid Teigland lkb->lkb_status,
1949dd592d7SDavid Teigland lkb->lkb_grmode,
1959dd592d7SDavid Teigland lkb->lkb_rqmode,
196eeda418dSDavid Teigland (unsigned long long)us,
197ac90a255SDavid Teigland r->res_nodeid,
1989dd592d7SDavid Teigland r->res_length,
1999dd592d7SDavid Teigland r->res_name);
2009dd592d7SDavid Teigland }
2019dd592d7SDavid Teigland
print_format2(struct dlm_rsb * r,struct seq_file * s)202d6d906b2SJoe Perches static void print_format2(struct dlm_rsb *r, struct seq_file *s)
2039dd592d7SDavid Teigland {
2049dd592d7SDavid Teigland struct dlm_lkb *lkb;
2059dd592d7SDavid Teigland
2069dd592d7SDavid Teigland lock_rsb(r);
2079dd592d7SDavid Teigland
208892c4467SDavid Teigland list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
209d6d906b2SJoe Perches print_format2_lock(s, lkb, r);
210d6d906b2SJoe Perches if (seq_has_overflowed(s))
211892c4467SDavid Teigland goto out;
212d022509dSDavid Teigland }
213d022509dSDavid Teigland
214892c4467SDavid Teigland list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
215d6d906b2SJoe Perches print_format2_lock(s, lkb, r);
216d6d906b2SJoe Perches if (seq_has_overflowed(s))
217892c4467SDavid Teigland goto out;
218892c4467SDavid Teigland }
219892c4467SDavid Teigland
220892c4467SDavid Teigland list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
221d6d906b2SJoe Perches print_format2_lock(s, lkb, r);
222d6d906b2SJoe Perches if (seq_has_overflowed(s))
223892c4467SDavid Teigland goto out;
224892c4467SDavid Teigland }
225892c4467SDavid Teigland out:
226892c4467SDavid Teigland unlock_rsb(r);
227892c4467SDavid Teigland }
228892c4467SDavid Teigland
print_format3_lock(struct seq_file * s,struct dlm_lkb * lkb,int rsb_lookup)229d6d906b2SJoe Perches static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
230d022509dSDavid Teigland int rsb_lookup)
231d022509dSDavid Teigland {
232d022509dSDavid Teigland u64 xid = 0;
233d022509dSDavid Teigland
2348a39dcd9SAlexander Aring if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) {
235d022509dSDavid Teigland if (lkb->lkb_ua)
236d022509dSDavid Teigland xid = lkb->lkb_ua->xid;
237d022509dSDavid Teigland }
238d022509dSDavid Teigland
239d6d906b2SJoe Perches seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
240d022509dSDavid Teigland lkb->lkb_id,
241d022509dSDavid Teigland lkb->lkb_nodeid,
242d022509dSDavid Teigland lkb->lkb_remid,
243d022509dSDavid Teigland lkb->lkb_ownpid,
244d022509dSDavid Teigland (unsigned long long)xid,
245d022509dSDavid Teigland lkb->lkb_exflags,
246e1af8728SAlexander Aring dlm_iflags_val(lkb),
247d022509dSDavid Teigland lkb->lkb_status,
248d022509dSDavid Teigland lkb->lkb_grmode,
249d022509dSDavid Teigland lkb->lkb_rqmode,
25061bed0baSAlexander Aring lkb->lkb_last_bast_mode,
251d022509dSDavid Teigland rsb_lookup,
252d022509dSDavid Teigland lkb->lkb_wait_type,
253d022509dSDavid Teigland lkb->lkb_lvbseq,
254d022509dSDavid Teigland (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
2558304d6f2SDavid Teigland (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time));
256d022509dSDavid Teigland }
257d022509dSDavid Teigland
print_format3(struct dlm_rsb * r,struct seq_file * s)258d6d906b2SJoe Perches static void print_format3(struct dlm_rsb *r, struct seq_file *s)
259d022509dSDavid Teigland {
260d022509dSDavid Teigland struct dlm_lkb *lkb;
261d022509dSDavid Teigland int i, lvblen = r->res_ls->ls_lvblen;
262d022509dSDavid Teigland int print_name = 1;
263d022509dSDavid Teigland
264d022509dSDavid Teigland lock_rsb(r);
265d022509dSDavid Teigland
266d6d906b2SJoe Perches seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
267d022509dSDavid Teigland r,
268d022509dSDavid Teigland r->res_nodeid,
269d022509dSDavid Teigland r->res_first_lkid,
270d022509dSDavid Teigland r->res_flags,
271d022509dSDavid Teigland !list_empty(&r->res_root_list),
272d022509dSDavid Teigland !list_empty(&r->res_recover_list),
273d022509dSDavid Teigland r->res_recover_locks_count,
274d022509dSDavid Teigland r->res_length);
275d6d906b2SJoe Perches if (seq_has_overflowed(s))
276892c4467SDavid Teigland goto out;
277d022509dSDavid Teigland
278d022509dSDavid Teigland for (i = 0; i < r->res_length; i++) {
279d022509dSDavid Teigland if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
280d022509dSDavid Teigland print_name = 0;
281d022509dSDavid Teigland }
282d022509dSDavid Teigland
283f365ef9bSJoe Perches seq_puts(s, print_name ? "str " : "hex");
284d022509dSDavid Teigland
285d022509dSDavid Teigland for (i = 0; i < r->res_length; i++) {
286d022509dSDavid Teigland if (print_name)
287d022509dSDavid Teigland seq_printf(s, "%c", r->res_name[i]);
288d022509dSDavid Teigland else
289d022509dSDavid Teigland seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
290d022509dSDavid Teigland }
291653996caSMarkus Elfring seq_putc(s, '\n');
292d6d906b2SJoe Perches if (seq_has_overflowed(s))
293892c4467SDavid Teigland goto out;
294d022509dSDavid Teigland
295d022509dSDavid Teigland if (!r->res_lvbptr)
296d022509dSDavid Teigland goto do_locks;
297d022509dSDavid Teigland
298d022509dSDavid Teigland seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
299d022509dSDavid Teigland
300d022509dSDavid Teigland for (i = 0; i < lvblen; i++)
301d022509dSDavid Teigland seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
302653996caSMarkus Elfring seq_putc(s, '\n');
303d6d906b2SJoe Perches if (seq_has_overflowed(s))
304892c4467SDavid Teigland goto out;
305d022509dSDavid Teigland
306d022509dSDavid Teigland do_locks:
307892c4467SDavid Teigland list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
308d6d906b2SJoe Perches print_format3_lock(s, lkb, 0);
309d6d906b2SJoe Perches if (seq_has_overflowed(s))
310892c4467SDavid Teigland goto out;
311892c4467SDavid Teigland }
312d022509dSDavid Teigland
313892c4467SDavid Teigland list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
314d6d906b2SJoe Perches print_format3_lock(s, lkb, 0);
315d6d906b2SJoe Perches if (seq_has_overflowed(s))
316892c4467SDavid Teigland goto out;
317892c4467SDavid Teigland }
318d022509dSDavid Teigland
319892c4467SDavid Teigland list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
320d6d906b2SJoe Perches print_format3_lock(s, lkb, 0);
321d6d906b2SJoe Perches if (seq_has_overflowed(s))
322892c4467SDavid Teigland goto out;
323892c4467SDavid Teigland }
324d022509dSDavid Teigland
325892c4467SDavid Teigland list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
326d6d906b2SJoe Perches print_format3_lock(s, lkb, 1);
327d6d906b2SJoe Perches if (seq_has_overflowed(s))
328892c4467SDavid Teigland goto out;
329892c4467SDavid Teigland }
330892c4467SDavid Teigland out:
3319dd592d7SDavid Teigland unlock_rsb(r);
332e7fd4179SDavid Teigland }
333e7fd4179SDavid Teigland
print_format4(struct dlm_rsb * r,struct seq_file * s)334d6d906b2SJoe Perches static void print_format4(struct dlm_rsb *r, struct seq_file *s)
335c04fecb4SDavid Teigland {
336c04fecb4SDavid Teigland int our_nodeid = dlm_our_nodeid();
337c04fecb4SDavid Teigland int print_name = 1;
338d6d906b2SJoe Perches int i;
339c04fecb4SDavid Teigland
340c04fecb4SDavid Teigland lock_rsb(r);
341c04fecb4SDavid Teigland
342d6d906b2SJoe Perches seq_printf(s, "rsb %p %d %d %d %d %lu %lx %d ",
343c04fecb4SDavid Teigland r,
344c04fecb4SDavid Teigland r->res_nodeid,
345c04fecb4SDavid Teigland r->res_master_nodeid,
346c04fecb4SDavid Teigland r->res_dir_nodeid,
347c04fecb4SDavid Teigland our_nodeid,
348c04fecb4SDavid Teigland r->res_toss_time,
349c04fecb4SDavid Teigland r->res_flags,
350c04fecb4SDavid Teigland r->res_length);
351c04fecb4SDavid Teigland
352c04fecb4SDavid Teigland for (i = 0; i < r->res_length; i++) {
353c04fecb4SDavid Teigland if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
354c04fecb4SDavid Teigland print_name = 0;
355c04fecb4SDavid Teigland }
356c04fecb4SDavid Teigland
357f365ef9bSJoe Perches seq_puts(s, print_name ? "str " : "hex");
358c04fecb4SDavid Teigland
359c04fecb4SDavid Teigland for (i = 0; i < r->res_length; i++) {
360c04fecb4SDavid Teigland if (print_name)
361c04fecb4SDavid Teigland seq_printf(s, "%c", r->res_name[i]);
362c04fecb4SDavid Teigland else
363c04fecb4SDavid Teigland seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
364c04fecb4SDavid Teigland }
365653996caSMarkus Elfring seq_putc(s, '\n');
366c04fecb4SDavid Teigland unlock_rsb(r);
367c04fecb4SDavid Teigland }
368c04fecb4SDavid Teigland
print_format5_lock(struct seq_file * s,struct dlm_lkb * lkb)369541adb0dSAlexander Aring static void print_format5_lock(struct seq_file *s, struct dlm_lkb *lkb)
370541adb0dSAlexander Aring {
371541adb0dSAlexander Aring struct dlm_callback *cb;
372541adb0dSAlexander Aring
373541adb0dSAlexander Aring /* lkb_id lkb_flags mode flags sb_status sb_flags */
374541adb0dSAlexander Aring
375541adb0dSAlexander Aring spin_lock(&lkb->lkb_cb_lock);
376541adb0dSAlexander Aring list_for_each_entry(cb, &lkb->lkb_callbacks, list) {
377541adb0dSAlexander Aring seq_printf(s, "%x %x %d %x %d %x\n",
378541adb0dSAlexander Aring lkb->lkb_id,
379541adb0dSAlexander Aring dlm_iflags_val(lkb),
380541adb0dSAlexander Aring cb->mode,
381541adb0dSAlexander Aring cb->flags,
382541adb0dSAlexander Aring cb->sb_status,
383541adb0dSAlexander Aring cb->sb_flags);
384541adb0dSAlexander Aring }
385541adb0dSAlexander Aring spin_unlock(&lkb->lkb_cb_lock);
386541adb0dSAlexander Aring }
387541adb0dSAlexander Aring
print_format5(struct dlm_rsb * r,struct seq_file * s)388541adb0dSAlexander Aring static void print_format5(struct dlm_rsb *r, struct seq_file *s)
389541adb0dSAlexander Aring {
390541adb0dSAlexander Aring struct dlm_lkb *lkb;
391541adb0dSAlexander Aring
392541adb0dSAlexander Aring lock_rsb(r);
393541adb0dSAlexander Aring
394541adb0dSAlexander Aring list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
395541adb0dSAlexander Aring print_format5_lock(s, lkb);
396541adb0dSAlexander Aring if (seq_has_overflowed(s))
397541adb0dSAlexander Aring goto out;
398541adb0dSAlexander Aring }
399541adb0dSAlexander Aring
400541adb0dSAlexander Aring list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
401541adb0dSAlexander Aring print_format5_lock(s, lkb);
402541adb0dSAlexander Aring if (seq_has_overflowed(s))
403541adb0dSAlexander Aring goto out;
404541adb0dSAlexander Aring }
405541adb0dSAlexander Aring
406541adb0dSAlexander Aring list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
407541adb0dSAlexander Aring print_format5_lock(s, lkb);
408541adb0dSAlexander Aring if (seq_has_overflowed(s))
409541adb0dSAlexander Aring goto out;
410541adb0dSAlexander Aring }
411541adb0dSAlexander Aring out:
412541adb0dSAlexander Aring unlock_rsb(r);
413541adb0dSAlexander Aring }
414541adb0dSAlexander Aring
415892c4467SDavid Teigland struct rsbtbl_iter {
416892c4467SDavid Teigland struct dlm_rsb *rsb;
417892c4467SDavid Teigland unsigned bucket;
418892c4467SDavid Teigland int format;
419892c4467SDavid Teigland int header;
420892c4467SDavid Teigland };
421892c4467SDavid Teigland
422d6d906b2SJoe Perches /*
423d6d906b2SJoe Perches * If the buffer is full, seq_printf can be called again, but it
424d6d906b2SJoe Perches * does nothing. So, the these printing routines periodically check
425d6d906b2SJoe Perches * seq_has_overflowed to avoid wasting too much time trying to print to
426d6d906b2SJoe Perches * a full buffer.
427d6d906b2SJoe Perches */
428892c4467SDavid Teigland
table_seq_show(struct seq_file * seq,void * iter_ptr)429892c4467SDavid Teigland static int table_seq_show(struct seq_file *seq, void *iter_ptr)
430e7fd4179SDavid Teigland {
431892c4467SDavid Teigland struct rsbtbl_iter *ri = iter_ptr;
432e7fd4179SDavid Teigland
433d022509dSDavid Teigland switch (ri->format) {
434d022509dSDavid Teigland case 1:
435d6d906b2SJoe Perches print_format1(ri->rsb, seq);
436d022509dSDavid Teigland break;
437d022509dSDavid Teigland case 2:
4389dd592d7SDavid Teigland if (ri->header) {
439f365ef9bSJoe Perches seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
4409dd592d7SDavid Teigland ri->header = 0;
4419dd592d7SDavid Teigland }
442d6d906b2SJoe Perches print_format2(ri->rsb, seq);
443d022509dSDavid Teigland break;
444d022509dSDavid Teigland case 3:
445d022509dSDavid Teigland if (ri->header) {
446f365ef9bSJoe Perches seq_puts(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
447d022509dSDavid Teigland ri->header = 0;
448d022509dSDavid Teigland }
449d6d906b2SJoe Perches print_format3(ri->rsb, seq);
450d022509dSDavid Teigland break;
451c04fecb4SDavid Teigland case 4:
452c04fecb4SDavid Teigland if (ri->header) {
453f365ef9bSJoe Perches seq_puts(seq, "version 4 rsb 2\n");
454c04fecb4SDavid Teigland ri->header = 0;
455c04fecb4SDavid Teigland }
456d6d906b2SJoe Perches print_format4(ri->rsb, seq);
457c04fecb4SDavid Teigland break;
458541adb0dSAlexander Aring case 5:
459541adb0dSAlexander Aring if (ri->header) {
460541adb0dSAlexander Aring seq_puts(seq, "lkb_id lkb_flags mode flags sb_status sb_flags\n");
461541adb0dSAlexander Aring ri->header = 0;
462541adb0dSAlexander Aring }
463541adb0dSAlexander Aring print_format5(ri->rsb, seq);
464541adb0dSAlexander Aring break;
4659dd592d7SDavid Teigland }
466e7fd4179SDavid Teigland
467d6d906b2SJoe Perches return 0;
468e7fd4179SDavid Teigland }
469e7fd4179SDavid Teigland
47088e9d34cSJames Morris static const struct seq_operations format1_seq_ops;
47188e9d34cSJames Morris static const struct seq_operations format2_seq_ops;
47288e9d34cSJames Morris static const struct seq_operations format3_seq_ops;
473c04fecb4SDavid Teigland static const struct seq_operations format4_seq_ops;
474541adb0dSAlexander Aring static const struct seq_operations format5_seq_ops;
475e7fd4179SDavid Teigland
table_seq_start(struct seq_file * seq,loff_t * pos)476892c4467SDavid Teigland static void *table_seq_start(struct seq_file *seq, loff_t *pos)
477e7fd4179SDavid Teigland {
478c04fecb4SDavid Teigland struct rb_root *tree;
4799beb3bf5SBob Peterson struct rb_node *node;
480892c4467SDavid Teigland struct dlm_ls *ls = seq->private;
481892c4467SDavid Teigland struct rsbtbl_iter *ri;
482892c4467SDavid Teigland struct dlm_rsb *r;
4839dd592d7SDavid Teigland loff_t n = *pos;
484892c4467SDavid Teigland unsigned bucket, entry;
485c04fecb4SDavid Teigland int toss = (seq->op == &format4_seq_ops);
4869dd592d7SDavid Teigland
487892c4467SDavid Teigland bucket = n >> 32;
488892c4467SDavid Teigland entry = n & ((1LL << 32) - 1);
489892c4467SDavid Teigland
490892c4467SDavid Teigland if (bucket >= ls->ls_rsbtbl_size)
491892c4467SDavid Teigland return NULL;
492892c4467SDavid Teigland
4932c257e96SMarkus Elfring ri = kzalloc(sizeof(*ri), GFP_NOFS);
4949dd592d7SDavid Teigland if (!ri)
4959dd592d7SDavid Teigland return NULL;
496892c4467SDavid Teigland if (n == 0)
497892c4467SDavid Teigland ri->header = 1;
498892c4467SDavid Teigland if (seq->op == &format1_seq_ops)
499892c4467SDavid Teigland ri->format = 1;
500892c4467SDavid Teigland if (seq->op == &format2_seq_ops)
501892c4467SDavid Teigland ri->format = 2;
502892c4467SDavid Teigland if (seq->op == &format3_seq_ops)
503d022509dSDavid Teigland ri->format = 3;
504c04fecb4SDavid Teigland if (seq->op == &format4_seq_ops)
505c04fecb4SDavid Teigland ri->format = 4;
506541adb0dSAlexander Aring if (seq->op == &format5_seq_ops)
507541adb0dSAlexander Aring ri->format = 5;
508c04fecb4SDavid Teigland
509c04fecb4SDavid Teigland tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
510d022509dSDavid Teigland
511c7be761aSDavid Teigland spin_lock(&ls->ls_rsbtbl[bucket].lock);
512c04fecb4SDavid Teigland if (!RB_EMPTY_ROOT(tree)) {
513c04fecb4SDavid Teigland for (node = rb_first(tree); node; node = rb_next(node)) {
5149beb3bf5SBob Peterson r = rb_entry(node, struct dlm_rsb, res_hashnode);
515892c4467SDavid Teigland if (!entry--) {
516892c4467SDavid Teigland dlm_hold_rsb(r);
517892c4467SDavid Teigland ri->rsb = r;
518892c4467SDavid Teigland ri->bucket = bucket;
519c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[bucket].lock);
520892c4467SDavid Teigland return ri;
521892c4467SDavid Teigland }
522892c4467SDavid Teigland }
523892c4467SDavid Teigland }
524c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[bucket].lock);
525d022509dSDavid Teigland
526892c4467SDavid Teigland /*
527892c4467SDavid Teigland * move to the first rsb in the next non-empty bucket
528892c4467SDavid Teigland */
529892c4467SDavid Teigland
530892c4467SDavid Teigland /* zero the entry */
531892c4467SDavid Teigland n &= ~((1LL << 32) - 1);
532892c4467SDavid Teigland
533892c4467SDavid Teigland while (1) {
534892c4467SDavid Teigland bucket++;
535892c4467SDavid Teigland n += 1LL << 32;
536892c4467SDavid Teigland
537892c4467SDavid Teigland if (bucket >= ls->ls_rsbtbl_size) {
538892c4467SDavid Teigland kfree(ri);
539d022509dSDavid Teigland return NULL;
540d022509dSDavid Teigland }
541c04fecb4SDavid Teigland tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
542d022509dSDavid Teigland
543c7be761aSDavid Teigland spin_lock(&ls->ls_rsbtbl[bucket].lock);
544c04fecb4SDavid Teigland if (!RB_EMPTY_ROOT(tree)) {
545c04fecb4SDavid Teigland node = rb_first(tree);
5469beb3bf5SBob Peterson r = rb_entry(node, struct dlm_rsb, res_hashnode);
547892c4467SDavid Teigland dlm_hold_rsb(r);
548892c4467SDavid Teigland ri->rsb = r;
549892c4467SDavid Teigland ri->bucket = bucket;
550c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[bucket].lock);
551892c4467SDavid Teigland *pos = n;
552d022509dSDavid Teigland return ri;
553d022509dSDavid Teigland }
554c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[bucket].lock);
555892c4467SDavid Teigland }
556892c4467SDavid Teigland }
557d022509dSDavid Teigland
table_seq_next(struct seq_file * seq,void * iter_ptr,loff_t * pos)558892c4467SDavid Teigland static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
559d022509dSDavid Teigland {
560892c4467SDavid Teigland struct dlm_ls *ls = seq->private;
561892c4467SDavid Teigland struct rsbtbl_iter *ri = iter_ptr;
562c04fecb4SDavid Teigland struct rb_root *tree;
5639beb3bf5SBob Peterson struct rb_node *next;
564892c4467SDavid Teigland struct dlm_rsb *r, *rp;
565d022509dSDavid Teigland loff_t n = *pos;
566892c4467SDavid Teigland unsigned bucket;
567c04fecb4SDavid Teigland int toss = (seq->op == &format4_seq_ops);
568d022509dSDavid Teigland
569892c4467SDavid Teigland bucket = n >> 32;
570d022509dSDavid Teigland
571892c4467SDavid Teigland /*
572892c4467SDavid Teigland * move to the next rsb in the same bucket
573892c4467SDavid Teigland */
574d022509dSDavid Teigland
575c7be761aSDavid Teigland spin_lock(&ls->ls_rsbtbl[bucket].lock);
576892c4467SDavid Teigland rp = ri->rsb;
5779beb3bf5SBob Peterson next = rb_next(&rp->res_hashnode);
578892c4467SDavid Teigland
5799beb3bf5SBob Peterson if (next) {
5809beb3bf5SBob Peterson r = rb_entry(next, struct dlm_rsb, res_hashnode);
581892c4467SDavid Teigland dlm_hold_rsb(r);
582892c4467SDavid Teigland ri->rsb = r;
583c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[bucket].lock);
584892c4467SDavid Teigland dlm_put_rsb(rp);
585892c4467SDavid Teigland ++*pos;
586d022509dSDavid Teigland return ri;
587d022509dSDavid Teigland }
588c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[bucket].lock);
589892c4467SDavid Teigland dlm_put_rsb(rp);
590d022509dSDavid Teigland
591892c4467SDavid Teigland /*
592892c4467SDavid Teigland * move to the first rsb in the next non-empty bucket
593892c4467SDavid Teigland */
594892c4467SDavid Teigland
595892c4467SDavid Teigland /* zero the entry */
596892c4467SDavid Teigland n &= ~((1LL << 32) - 1);
597892c4467SDavid Teigland
598892c4467SDavid Teigland while (1) {
599892c4467SDavid Teigland bucket++;
600892c4467SDavid Teigland n += 1LL << 32;
601892c4467SDavid Teigland
602892c4467SDavid Teigland if (bucket >= ls->ls_rsbtbl_size) {
603892c4467SDavid Teigland kfree(ri);
60492c48950SAlexander Aring ++*pos;
605892c4467SDavid Teigland return NULL;
606892c4467SDavid Teigland }
607c04fecb4SDavid Teigland tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
608892c4467SDavid Teigland
609c7be761aSDavid Teigland spin_lock(&ls->ls_rsbtbl[bucket].lock);
610c04fecb4SDavid Teigland if (!RB_EMPTY_ROOT(tree)) {
611c04fecb4SDavid Teigland next = rb_first(tree);
6129beb3bf5SBob Peterson r = rb_entry(next, struct dlm_rsb, res_hashnode);
613892c4467SDavid Teigland dlm_hold_rsb(r);
614892c4467SDavid Teigland ri->rsb = r;
615892c4467SDavid Teigland ri->bucket = bucket;
616c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[bucket].lock);
617892c4467SDavid Teigland *pos = n;
618892c4467SDavid Teigland return ri;
619892c4467SDavid Teigland }
620c7be761aSDavid Teigland spin_unlock(&ls->ls_rsbtbl[bucket].lock);
621892c4467SDavid Teigland }
622892c4467SDavid Teigland }
623892c4467SDavid Teigland
table_seq_stop(struct seq_file * seq,void * iter_ptr)624892c4467SDavid Teigland static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
625892c4467SDavid Teigland {
626892c4467SDavid Teigland struct rsbtbl_iter *ri = iter_ptr;
627892c4467SDavid Teigland
628892c4467SDavid Teigland if (ri) {
629892c4467SDavid Teigland dlm_put_rsb(ri->rsb);
630892c4467SDavid Teigland kfree(ri);
631892c4467SDavid Teigland }
632892c4467SDavid Teigland }
633892c4467SDavid Teigland
63488e9d34cSJames Morris static const struct seq_operations format1_seq_ops = {
635892c4467SDavid Teigland .start = table_seq_start,
636892c4467SDavid Teigland .next = table_seq_next,
637892c4467SDavid Teigland .stop = table_seq_stop,
638892c4467SDavid Teigland .show = table_seq_show,
639d022509dSDavid Teigland };
640d022509dSDavid Teigland
64188e9d34cSJames Morris static const struct seq_operations format2_seq_ops = {
642892c4467SDavid Teigland .start = table_seq_start,
643892c4467SDavid Teigland .next = table_seq_next,
644892c4467SDavid Teigland .stop = table_seq_stop,
645892c4467SDavid Teigland .show = table_seq_show,
646892c4467SDavid Teigland };
647892c4467SDavid Teigland
64888e9d34cSJames Morris static const struct seq_operations format3_seq_ops = {
649892c4467SDavid Teigland .start = table_seq_start,
650892c4467SDavid Teigland .next = table_seq_next,
651892c4467SDavid Teigland .stop = table_seq_stop,
652892c4467SDavid Teigland .show = table_seq_show,
653892c4467SDavid Teigland };
654892c4467SDavid Teigland
655c04fecb4SDavid Teigland static const struct seq_operations format4_seq_ops = {
656c04fecb4SDavid Teigland .start = table_seq_start,
657c04fecb4SDavid Teigland .next = table_seq_next,
658c04fecb4SDavid Teigland .stop = table_seq_stop,
659c04fecb4SDavid Teigland .show = table_seq_show,
660c04fecb4SDavid Teigland };
661c04fecb4SDavid Teigland
662541adb0dSAlexander Aring static const struct seq_operations format5_seq_ops = {
663541adb0dSAlexander Aring .start = table_seq_start,
664541adb0dSAlexander Aring .next = table_seq_next,
665541adb0dSAlexander Aring .stop = table_seq_stop,
666541adb0dSAlexander Aring .show = table_seq_show,
667541adb0dSAlexander Aring };
668541adb0dSAlexander Aring
669892c4467SDavid Teigland static const struct file_operations format1_fops;
670892c4467SDavid Teigland static const struct file_operations format2_fops;
671892c4467SDavid Teigland static const struct file_operations format3_fops;
672c04fecb4SDavid Teigland static const struct file_operations format4_fops;
673541adb0dSAlexander Aring static const struct file_operations format5_fops;
674892c4467SDavid Teigland
table_open1(struct inode * inode,struct file * file)675079d37dfSEric Ren static int table_open1(struct inode *inode, struct file *file)
676d022509dSDavid Teigland {
677d022509dSDavid Teigland struct seq_file *seq;
678079d37dfSEric Ren int ret;
679d022509dSDavid Teigland
680892c4467SDavid Teigland ret = seq_open(file, &format1_seq_ops);
681079d37dfSEric Ren if (ret)
682079d37dfSEric Ren return ret;
683892c4467SDavid Teigland
684079d37dfSEric Ren seq = file->private_data;
685079d37dfSEric Ren seq->private = inode->i_private; /* the dlm_ls */
686079d37dfSEric Ren return 0;
687079d37dfSEric Ren }
688079d37dfSEric Ren
table_open2(struct inode * inode,struct file * file)689079d37dfSEric Ren static int table_open2(struct inode *inode, struct file *file)
690079d37dfSEric Ren {
691079d37dfSEric Ren struct seq_file *seq;
692079d37dfSEric Ren int ret;
693079d37dfSEric Ren
694079d37dfSEric Ren ret = seq_open(file, &format2_seq_ops);
695079d37dfSEric Ren if (ret)
696079d37dfSEric Ren return ret;
697079d37dfSEric Ren
698079d37dfSEric Ren seq = file->private_data;
699079d37dfSEric Ren seq->private = inode->i_private; /* the dlm_ls */
700079d37dfSEric Ren return 0;
701079d37dfSEric Ren }
702079d37dfSEric Ren
table_write2(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)7035054e79dSAlexander Aring static ssize_t table_write2(struct file *file, const char __user *user_buf,
7045054e79dSAlexander Aring size_t count, loff_t *ppos)
7055054e79dSAlexander Aring {
7065054e79dSAlexander Aring struct seq_file *seq = file->private_data;
7075054e79dSAlexander Aring int n, len, lkb_nodeid, lkb_status, error;
7086a628fa4SAlexander Aring char name[DLM_RESNAME_MAXLEN + 1] = {};
7095054e79dSAlexander Aring struct dlm_ls *ls = seq->private;
7105054e79dSAlexander Aring unsigned int lkb_flags;
7115054e79dSAlexander Aring char buf[256] = {};
7125054e79dSAlexander Aring uint32_t lkb_id;
7135054e79dSAlexander Aring
7145054e79dSAlexander Aring if (copy_from_user(buf, user_buf,
7155054e79dSAlexander Aring min_t(size_t, sizeof(buf) - 1, count)))
7165054e79dSAlexander Aring return -EFAULT;
7175054e79dSAlexander Aring
7185054e79dSAlexander Aring n = sscanf(buf, "%x %" __stringify(DLM_RESNAME_MAXLEN) "s %x %d %d",
7195054e79dSAlexander Aring &lkb_id, name, &lkb_flags, &lkb_nodeid, &lkb_status);
7205054e79dSAlexander Aring if (n != 5)
7215054e79dSAlexander Aring return -EINVAL;
7225054e79dSAlexander Aring
7235054e79dSAlexander Aring len = strnlen(name, DLM_RESNAME_MAXLEN);
7245054e79dSAlexander Aring error = dlm_debug_add_lkb(ls, lkb_id, name, len, lkb_flags,
7255054e79dSAlexander Aring lkb_nodeid, lkb_status);
7265054e79dSAlexander Aring if (error)
7275054e79dSAlexander Aring return error;
7285054e79dSAlexander Aring
7295054e79dSAlexander Aring return count;
7305054e79dSAlexander Aring }
7315054e79dSAlexander Aring
table_open3(struct inode * inode,struct file * file)732079d37dfSEric Ren static int table_open3(struct inode *inode, struct file *file)
733079d37dfSEric Ren {
734079d37dfSEric Ren struct seq_file *seq;
735079d37dfSEric Ren int ret;
736079d37dfSEric Ren
737079d37dfSEric Ren ret = seq_open(file, &format3_seq_ops);
738079d37dfSEric Ren if (ret)
739079d37dfSEric Ren return ret;
740079d37dfSEric Ren
741079d37dfSEric Ren seq = file->private_data;
742079d37dfSEric Ren seq->private = inode->i_private; /* the dlm_ls */
743079d37dfSEric Ren return 0;
744079d37dfSEric Ren }
745079d37dfSEric Ren
table_open4(struct inode * inode,struct file * file)746079d37dfSEric Ren static int table_open4(struct inode *inode, struct file *file)
747079d37dfSEric Ren {
748079d37dfSEric Ren struct seq_file *seq;
749079d37dfSEric Ren int ret;
750079d37dfSEric Ren
751*528a422bSAlexander Aring ret = seq_open(file, &format4_seq_ops);
752541adb0dSAlexander Aring if (ret)
753541adb0dSAlexander Aring return ret;
754541adb0dSAlexander Aring
755541adb0dSAlexander Aring seq = file->private_data;
756541adb0dSAlexander Aring seq->private = inode->i_private; /* the dlm_ls */
757541adb0dSAlexander Aring return 0;
758541adb0dSAlexander Aring }
759541adb0dSAlexander Aring
table_open5(struct inode * inode,struct file * file)760541adb0dSAlexander Aring static int table_open5(struct inode *inode, struct file *file)
761541adb0dSAlexander Aring {
762541adb0dSAlexander Aring struct seq_file *seq;
763541adb0dSAlexander Aring int ret;
764541adb0dSAlexander Aring
765541adb0dSAlexander Aring ret = seq_open(file, &format5_seq_ops);
766d022509dSDavid Teigland if (ret)
767d022509dSDavid Teigland return ret;
768d022509dSDavid Teigland
769d022509dSDavid Teigland seq = file->private_data;
770892c4467SDavid Teigland seq->private = inode->i_private; /* the dlm_ls */
771d022509dSDavid Teigland return 0;
772d022509dSDavid Teigland }
773d022509dSDavid Teigland
774892c4467SDavid Teigland static const struct file_operations format1_fops = {
775d022509dSDavid Teigland .owner = THIS_MODULE,
776079d37dfSEric Ren .open = table_open1,
777892c4467SDavid Teigland .read = seq_read,
778892c4467SDavid Teigland .llseek = seq_lseek,
779892c4467SDavid Teigland .release = seq_release
780892c4467SDavid Teigland };
781892c4467SDavid Teigland
782892c4467SDavid Teigland static const struct file_operations format2_fops = {
783892c4467SDavid Teigland .owner = THIS_MODULE,
784079d37dfSEric Ren .open = table_open2,
785892c4467SDavid Teigland .read = seq_read,
7865054e79dSAlexander Aring .write = table_write2,
787892c4467SDavid Teigland .llseek = seq_lseek,
788892c4467SDavid Teigland .release = seq_release
789892c4467SDavid Teigland };
790892c4467SDavid Teigland
791892c4467SDavid Teigland static const struct file_operations format3_fops = {
792892c4467SDavid Teigland .owner = THIS_MODULE,
793079d37dfSEric Ren .open = table_open3,
794d022509dSDavid Teigland .read = seq_read,
795d022509dSDavid Teigland .llseek = seq_lseek,
796d022509dSDavid Teigland .release = seq_release
797d022509dSDavid Teigland };
798d022509dSDavid Teigland
799c04fecb4SDavid Teigland static const struct file_operations format4_fops = {
800c04fecb4SDavid Teigland .owner = THIS_MODULE,
801079d37dfSEric Ren .open = table_open4,
802c04fecb4SDavid Teigland .read = seq_read,
803c04fecb4SDavid Teigland .llseek = seq_lseek,
804c04fecb4SDavid Teigland .release = seq_release
805c04fecb4SDavid Teigland };
806c04fecb4SDavid Teigland
807541adb0dSAlexander Aring static const struct file_operations format5_fops = {
808541adb0dSAlexander Aring .owner = THIS_MODULE,
809541adb0dSAlexander Aring .open = table_open5,
810541adb0dSAlexander Aring .read = seq_read,
811541adb0dSAlexander Aring .llseek = seq_lseek,
812541adb0dSAlexander Aring .release = seq_release
813541adb0dSAlexander Aring };
814541adb0dSAlexander Aring
815d022509dSDavid Teigland /*
8165de6319bSDavid Teigland * dump lkb's on the ls_waiters list
8175de6319bSDavid Teigland */
waiters_read(struct file * file,char __user * userbuf,size_t count,loff_t * ppos)8185de6319bSDavid Teigland static ssize_t waiters_read(struct file *file, char __user *userbuf,
8195de6319bSDavid Teigland size_t count, loff_t *ppos)
8205de6319bSDavid Teigland {
8215de6319bSDavid Teigland struct dlm_ls *ls = file->private_data;
8225de6319bSDavid Teigland struct dlm_lkb *lkb;
82306442440SDavid Teigland size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
8245de6319bSDavid Teigland
8255de6319bSDavid Teigland mutex_lock(&debug_buf_lock);
8265de6319bSDavid Teigland mutex_lock(&ls->ls_waiters_mutex);
8275de6319bSDavid Teigland memset(debug_buf, 0, sizeof(debug_buf));
8285de6319bSDavid Teigland
8295de6319bSDavid Teigland list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
83006442440SDavid Teigland ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
8315de6319bSDavid Teigland lkb->lkb_id, lkb->lkb_wait_type,
8325de6319bSDavid Teigland lkb->lkb_nodeid, lkb->lkb_resource->res_name);
83306442440SDavid Teigland if (ret >= len - pos)
83406442440SDavid Teigland break;
83506442440SDavid Teigland pos += ret;
8365de6319bSDavid Teigland }
8375de6319bSDavid Teigland mutex_unlock(&ls->ls_waiters_mutex);
8385de6319bSDavid Teigland
8395de6319bSDavid Teigland rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
8405de6319bSDavid Teigland mutex_unlock(&debug_buf_lock);
8415de6319bSDavid Teigland return rv;
8425de6319bSDavid Teigland }
8435de6319bSDavid Teigland
waiters_write(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)84463eab2b0SAlexander Aring static ssize_t waiters_write(struct file *file, const char __user *user_buf,
84563eab2b0SAlexander Aring size_t count, loff_t *ppos)
84663eab2b0SAlexander Aring {
84763eab2b0SAlexander Aring struct dlm_ls *ls = file->private_data;
84863eab2b0SAlexander Aring int mstype, to_nodeid;
84963eab2b0SAlexander Aring char buf[128] = {};
85063eab2b0SAlexander Aring uint32_t lkb_id;
85163eab2b0SAlexander Aring int n, error;
85263eab2b0SAlexander Aring
85363eab2b0SAlexander Aring if (copy_from_user(buf, user_buf,
85463eab2b0SAlexander Aring min_t(size_t, sizeof(buf) - 1, count)))
85563eab2b0SAlexander Aring return -EFAULT;
85663eab2b0SAlexander Aring
85763eab2b0SAlexander Aring n = sscanf(buf, "%x %d %d", &lkb_id, &mstype, &to_nodeid);
85863eab2b0SAlexander Aring if (n != 3)
85963eab2b0SAlexander Aring return -EINVAL;
86063eab2b0SAlexander Aring
86163eab2b0SAlexander Aring error = dlm_debug_add_lkb_to_waiters(ls, lkb_id, mstype, to_nodeid);
86263eab2b0SAlexander Aring if (error)
86363eab2b0SAlexander Aring return error;
86463eab2b0SAlexander Aring
86563eab2b0SAlexander Aring return count;
86663eab2b0SAlexander Aring }
86763eab2b0SAlexander Aring
86800977a59SArjan van de Ven static const struct file_operations waiters_fops = {
8695de6319bSDavid Teigland .owner = THIS_MODULE,
870234e3405SStephen Boyd .open = simple_open,
8716038f373SArnd Bergmann .read = waiters_read,
87263eab2b0SAlexander Aring .write = waiters_write,
8736038f373SArnd Bergmann .llseek = default_llseek,
8745de6319bSDavid Teigland };
8755de6319bSDavid Teigland
dlm_delete_debug_file(struct dlm_ls * ls)876d022509dSDavid Teigland void dlm_delete_debug_file(struct dlm_ls *ls)
877d022509dSDavid Teigland {
878d022509dSDavid Teigland debugfs_remove(ls->ls_debug_rsb_dentry);
879d022509dSDavid Teigland debugfs_remove(ls->ls_debug_waiters_dentry);
880d022509dSDavid Teigland debugfs_remove(ls->ls_debug_locks_dentry);
881d022509dSDavid Teigland debugfs_remove(ls->ls_debug_all_dentry);
882c04fecb4SDavid Teigland debugfs_remove(ls->ls_debug_toss_dentry);
883541adb0dSAlexander Aring debugfs_remove(ls->ls_debug_queued_asts_dentry);
884d022509dSDavid Teigland }
885d022509dSDavid Teigland
dlm_state_show(struct seq_file * file,void * offset)8865b2f981fSAlexander Aring static int dlm_state_show(struct seq_file *file, void *offset)
8875b2f981fSAlexander Aring {
8885b2f981fSAlexander Aring seq_printf(file, "%s\n", dlm_midcomms_state(file->private));
8895b2f981fSAlexander Aring return 0;
8905b2f981fSAlexander Aring }
8915b2f981fSAlexander Aring DEFINE_SHOW_ATTRIBUTE(dlm_state);
8925b2f981fSAlexander Aring
dlm_flags_show(struct seq_file * file,void * offset)8935b2f981fSAlexander Aring static int dlm_flags_show(struct seq_file *file, void *offset)
8945b2f981fSAlexander Aring {
8955b2f981fSAlexander Aring seq_printf(file, "%lu\n", dlm_midcomms_flags(file->private));
8965b2f981fSAlexander Aring return 0;
8975b2f981fSAlexander Aring }
8985b2f981fSAlexander Aring DEFINE_SHOW_ATTRIBUTE(dlm_flags);
8995b2f981fSAlexander Aring
dlm_send_queue_cnt_show(struct seq_file * file,void * offset)9005b2f981fSAlexander Aring static int dlm_send_queue_cnt_show(struct seq_file *file, void *offset)
9015b2f981fSAlexander Aring {
9025b2f981fSAlexander Aring seq_printf(file, "%d\n", dlm_midcomms_send_queue_cnt(file->private));
9035b2f981fSAlexander Aring return 0;
9045b2f981fSAlexander Aring }
9055b2f981fSAlexander Aring DEFINE_SHOW_ATTRIBUTE(dlm_send_queue_cnt);
9065b2f981fSAlexander Aring
dlm_version_show(struct seq_file * file,void * offset)9075b2f981fSAlexander Aring static int dlm_version_show(struct seq_file *file, void *offset)
9085b2f981fSAlexander Aring {
9095b2f981fSAlexander Aring seq_printf(file, "0x%08x\n", dlm_midcomms_version(file->private));
9105b2f981fSAlexander Aring return 0;
9115b2f981fSAlexander Aring }
9125b2f981fSAlexander Aring DEFINE_SHOW_ATTRIBUTE(dlm_version);
9135b2f981fSAlexander Aring
dlm_rawmsg_write(struct file * fp,const char __user * user_buf,size_t count,loff_t * ppos)9149af5b8f0SAlexander Aring static ssize_t dlm_rawmsg_write(struct file *fp, const char __user *user_buf,
9159af5b8f0SAlexander Aring size_t count, loff_t *ppos)
9169af5b8f0SAlexander Aring {
9179af5b8f0SAlexander Aring void *buf;
9189af5b8f0SAlexander Aring int ret;
9199af5b8f0SAlexander Aring
9209af5b8f0SAlexander Aring if (count > PAGE_SIZE || count < sizeof(struct dlm_header))
9219af5b8f0SAlexander Aring return -EINVAL;
9229af5b8f0SAlexander Aring
9239af5b8f0SAlexander Aring buf = kmalloc(PAGE_SIZE, GFP_NOFS);
9249af5b8f0SAlexander Aring if (!buf)
9259af5b8f0SAlexander Aring return -ENOMEM;
9269af5b8f0SAlexander Aring
9279af5b8f0SAlexander Aring if (copy_from_user(buf, user_buf, count)) {
9289af5b8f0SAlexander Aring ret = -EFAULT;
9299af5b8f0SAlexander Aring goto out;
9309af5b8f0SAlexander Aring }
9319af5b8f0SAlexander Aring
9329af5b8f0SAlexander Aring ret = dlm_midcomms_rawmsg_send(fp->private_data, buf, count);
9339af5b8f0SAlexander Aring if (ret)
9349af5b8f0SAlexander Aring goto out;
9359af5b8f0SAlexander Aring
9369af5b8f0SAlexander Aring kfree(buf);
9379af5b8f0SAlexander Aring return count;
9389af5b8f0SAlexander Aring
9399af5b8f0SAlexander Aring out:
9409af5b8f0SAlexander Aring kfree(buf);
9419af5b8f0SAlexander Aring return ret;
9429af5b8f0SAlexander Aring }
9439af5b8f0SAlexander Aring
9449af5b8f0SAlexander Aring static const struct file_operations dlm_rawmsg_fops = {
9459af5b8f0SAlexander Aring .open = simple_open,
9469af5b8f0SAlexander Aring .write = dlm_rawmsg_write,
9479af5b8f0SAlexander Aring .llseek = no_llseek,
9489af5b8f0SAlexander Aring };
9499af5b8f0SAlexander Aring
dlm_create_debug_comms_file(int nodeid,void * data)9505b2f981fSAlexander Aring void *dlm_create_debug_comms_file(int nodeid, void *data)
9515b2f981fSAlexander Aring {
9525b2f981fSAlexander Aring struct dentry *d_node;
9535b2f981fSAlexander Aring char name[256];
9545b2f981fSAlexander Aring
9555b2f981fSAlexander Aring memset(name, 0, sizeof(name));
9565b2f981fSAlexander Aring snprintf(name, 256, "%d", nodeid);
9575b2f981fSAlexander Aring
9585b2f981fSAlexander Aring d_node = debugfs_create_dir(name, dlm_comms);
9595b2f981fSAlexander Aring debugfs_create_file("state", 0444, d_node, data, &dlm_state_fops);
9605b2f981fSAlexander Aring debugfs_create_file("flags", 0444, d_node, data, &dlm_flags_fops);
9615b2f981fSAlexander Aring debugfs_create_file("send_queue_count", 0444, d_node, data,
9625b2f981fSAlexander Aring &dlm_send_queue_cnt_fops);
9635b2f981fSAlexander Aring debugfs_create_file("version", 0444, d_node, data, &dlm_version_fops);
9649af5b8f0SAlexander Aring debugfs_create_file("rawmsg", 0200, d_node, data, &dlm_rawmsg_fops);
9655b2f981fSAlexander Aring
9665b2f981fSAlexander Aring return d_node;
9675b2f981fSAlexander Aring }
9685b2f981fSAlexander Aring
dlm_delete_debug_comms_file(void * ctx)9695b2f981fSAlexander Aring void dlm_delete_debug_comms_file(void *ctx)
9705b2f981fSAlexander Aring {
9715b2f981fSAlexander Aring debugfs_remove(ctx);
9725b2f981fSAlexander Aring }
9735b2f981fSAlexander Aring
dlm_create_debug_file(struct dlm_ls * ls)974a48f9721SGreg Kroah-Hartman void dlm_create_debug_file(struct dlm_ls *ls)
975e7fd4179SDavid Teigland {
9764a31e3c8SChristophe JAILLET /* Reserve enough space for the longest file name */
9774a31e3c8SChristophe JAILLET char name[DLM_LOCKSPACE_LEN + sizeof("_queued_asts")];
9785de6319bSDavid Teigland
979d022509dSDavid Teigland /* format 1 */
980d022509dSDavid Teigland
9815de6319bSDavid Teigland ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
982e7fd4179SDavid Teigland S_IFREG | S_IRUGO,
983e7fd4179SDavid Teigland dlm_root,
984e7fd4179SDavid Teigland ls,
985892c4467SDavid Teigland &format1_fops);
9865de6319bSDavid Teigland
987d022509dSDavid Teigland /* format 2 */
9885de6319bSDavid Teigland
9899dd592d7SDavid Teigland memset(name, 0, sizeof(name));
9904bc46c04SChristophe JAILLET snprintf(name, sizeof(name), "%s_locks", ls->ls_name);
9919dd592d7SDavid Teigland
992ac90a255SDavid Teigland ls->ls_debug_locks_dentry = debugfs_create_file(name,
9935054e79dSAlexander Aring 0644,
9949dd592d7SDavid Teigland dlm_root,
9959dd592d7SDavid Teigland ls,
996892c4467SDavid Teigland &format2_fops);
997d022509dSDavid Teigland
998d022509dSDavid Teigland /* format 3 */
999d022509dSDavid Teigland
1000d022509dSDavid Teigland memset(name, 0, sizeof(name));
10014bc46c04SChristophe JAILLET snprintf(name, sizeof(name), "%s_all", ls->ls_name);
1002d022509dSDavid Teigland
1003d022509dSDavid Teigland ls->ls_debug_all_dentry = debugfs_create_file(name,
1004d022509dSDavid Teigland S_IFREG | S_IRUGO,
1005d022509dSDavid Teigland dlm_root,
1006d022509dSDavid Teigland ls,
1007892c4467SDavid Teigland &format3_fops);
1008d022509dSDavid Teigland
1009c04fecb4SDavid Teigland /* format 4 */
1010c04fecb4SDavid Teigland
1011c04fecb4SDavid Teigland memset(name, 0, sizeof(name));
10124bc46c04SChristophe JAILLET snprintf(name, sizeof(name), "%s_toss", ls->ls_name);
1013c04fecb4SDavid Teigland
1014c04fecb4SDavid Teigland ls->ls_debug_toss_dentry = debugfs_create_file(name,
1015c04fecb4SDavid Teigland S_IFREG | S_IRUGO,
1016c04fecb4SDavid Teigland dlm_root,
1017c04fecb4SDavid Teigland ls,
1018c04fecb4SDavid Teigland &format4_fops);
1019c04fecb4SDavid Teigland
1020d022509dSDavid Teigland memset(name, 0, sizeof(name));
10214bc46c04SChristophe JAILLET snprintf(name, sizeof(name), "%s_waiters", ls->ls_name);
1022d022509dSDavid Teigland
1023d022509dSDavid Teigland ls->ls_debug_waiters_dentry = debugfs_create_file(name,
102463eab2b0SAlexander Aring 0644,
1025d022509dSDavid Teigland dlm_root,
1026d022509dSDavid Teigland ls,
1027d022509dSDavid Teigland &waiters_fops);
1028541adb0dSAlexander Aring
1029541adb0dSAlexander Aring /* format 5 */
1030541adb0dSAlexander Aring
1031541adb0dSAlexander Aring memset(name, 0, sizeof(name));
10324bc46c04SChristophe JAILLET snprintf(name, sizeof(name), "%s_queued_asts", ls->ls_name);
1033541adb0dSAlexander Aring
1034541adb0dSAlexander Aring ls->ls_debug_queued_asts_dentry = debugfs_create_file(name,
1035541adb0dSAlexander Aring 0644,
1036541adb0dSAlexander Aring dlm_root,
1037541adb0dSAlexander Aring ls,
1038541adb0dSAlexander Aring &format5_fops);
1039e7fd4179SDavid Teigland }
1040e7fd4179SDavid Teigland
dlm_register_debugfs(void)1041a48f9721SGreg Kroah-Hartman void __init dlm_register_debugfs(void)
1042e7fd4179SDavid Teigland {
10435de6319bSDavid Teigland mutex_init(&debug_buf_lock);
1044e7fd4179SDavid Teigland dlm_root = debugfs_create_dir("dlm", NULL);
10455b2f981fSAlexander Aring dlm_comms = debugfs_create_dir("comms", dlm_root);
1046e7fd4179SDavid Teigland }
1047e7fd4179SDavid Teigland
dlm_unregister_debugfs(void)1048e7fd4179SDavid Teigland void dlm_unregister_debugfs(void)
1049e7fd4179SDavid Teigland {
1050e7fd4179SDavid Teigland debugfs_remove(dlm_root);
1051e7fd4179SDavid Teigland }
1052e7fd4179SDavid Teigland
1053