18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/******************************************************************************
38c2ecf20Sopenharmony_ci*******************************************************************************
48c2ecf20Sopenharmony_ci**
58c2ecf20Sopenharmony_ci**  Copyright (C) 2005-2009 Red Hat, Inc.  All rights reserved.
68c2ecf20Sopenharmony_ci**
78c2ecf20Sopenharmony_ci**
88c2ecf20Sopenharmony_ci*******************************************************************************
98c2ecf20Sopenharmony_ci******************************************************************************/
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
128c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
138c2ecf20Sopenharmony_ci#include <linux/init.h>
148c2ecf20Sopenharmony_ci#include <linux/ctype.h>
158c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
168c2ecf20Sopenharmony_ci#include <linux/slab.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "dlm_internal.h"
198c2ecf20Sopenharmony_ci#include "lock.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define DLM_DEBUG_BUF_LEN 4096
228c2ecf20Sopenharmony_cistatic char debug_buf[DLM_DEBUG_BUF_LEN];
238c2ecf20Sopenharmony_cistatic struct mutex debug_buf_lock;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic struct dentry *dlm_root;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic char *print_lockmode(int mode)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	switch (mode) {
308c2ecf20Sopenharmony_ci	case DLM_LOCK_IV:
318c2ecf20Sopenharmony_ci		return "--";
328c2ecf20Sopenharmony_ci	case DLM_LOCK_NL:
338c2ecf20Sopenharmony_ci		return "NL";
348c2ecf20Sopenharmony_ci	case DLM_LOCK_CR:
358c2ecf20Sopenharmony_ci		return "CR";
368c2ecf20Sopenharmony_ci	case DLM_LOCK_CW:
378c2ecf20Sopenharmony_ci		return "CW";
388c2ecf20Sopenharmony_ci	case DLM_LOCK_PR:
398c2ecf20Sopenharmony_ci		return "PR";
408c2ecf20Sopenharmony_ci	case DLM_LOCK_PW:
418c2ecf20Sopenharmony_ci		return "PW";
428c2ecf20Sopenharmony_ci	case DLM_LOCK_EX:
438c2ecf20Sopenharmony_ci		return "EX";
448c2ecf20Sopenharmony_ci	default:
458c2ecf20Sopenharmony_ci		return "??";
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
508c2ecf20Sopenharmony_ci			       struct dlm_rsb *res)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
558c2ecf20Sopenharmony_ci	    lkb->lkb_status == DLM_LKSTS_WAITING)
568c2ecf20Sopenharmony_ci		seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	if (lkb->lkb_nodeid) {
598c2ecf20Sopenharmony_ci		if (lkb->lkb_nodeid != res->res_nodeid)
608c2ecf20Sopenharmony_ci			seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid,
618c2ecf20Sopenharmony_ci				   lkb->lkb_remid);
628c2ecf20Sopenharmony_ci		else
638c2ecf20Sopenharmony_ci			seq_printf(s, " Master:     %08x", lkb->lkb_remid);
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (lkb->lkb_wait_type)
678c2ecf20Sopenharmony_ci		seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	seq_putc(s, '\n');
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic void print_format1(struct dlm_rsb *res, struct seq_file *s)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct dlm_lkb *lkb;
758c2ecf20Sopenharmony_ci	int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	lock_rsb(res);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	for (i = 0; i < res->res_length; i++) {
828c2ecf20Sopenharmony_ci		if (isprint(res->res_name[i]))
838c2ecf20Sopenharmony_ci			seq_printf(s, "%c", res->res_name[i]);
848c2ecf20Sopenharmony_ci		else
858c2ecf20Sopenharmony_ci			seq_printf(s, "%c", '.');
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	if (res->res_nodeid > 0)
898c2ecf20Sopenharmony_ci		seq_printf(s, "\"\nLocal Copy, Master is node %d\n",
908c2ecf20Sopenharmony_ci			   res->res_nodeid);
918c2ecf20Sopenharmony_ci	else if (res->res_nodeid == 0)
928c2ecf20Sopenharmony_ci		seq_puts(s, "\"\nMaster Copy\n");
938c2ecf20Sopenharmony_ci	else if (res->res_nodeid == -1)
948c2ecf20Sopenharmony_ci		seq_printf(s, "\"\nLooking up master (lkid %x)\n",
958c2ecf20Sopenharmony_ci			   res->res_first_lkid);
968c2ecf20Sopenharmony_ci	else
978c2ecf20Sopenharmony_ci		seq_printf(s, "\"\nInvalid master %d\n", res->res_nodeid);
988c2ecf20Sopenharmony_ci	if (seq_has_overflowed(s))
998c2ecf20Sopenharmony_ci		goto out;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	/* Print the LVB: */
1028c2ecf20Sopenharmony_ci	if (res->res_lvbptr) {
1038c2ecf20Sopenharmony_ci		seq_puts(s, "LVB: ");
1048c2ecf20Sopenharmony_ci		for (i = 0; i < lvblen; i++) {
1058c2ecf20Sopenharmony_ci			if (i == lvblen / 2)
1068c2ecf20Sopenharmony_ci				seq_puts(s, "\n     ");
1078c2ecf20Sopenharmony_ci			seq_printf(s, "%02x ",
1088c2ecf20Sopenharmony_ci				   (unsigned char) res->res_lvbptr[i]);
1098c2ecf20Sopenharmony_ci		}
1108c2ecf20Sopenharmony_ci		if (rsb_flag(res, RSB_VALNOTVALID))
1118c2ecf20Sopenharmony_ci			seq_puts(s, " (INVALID)");
1128c2ecf20Sopenharmony_ci		seq_putc(s, '\n');
1138c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
1148c2ecf20Sopenharmony_ci			goto out;
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	root_list = !list_empty(&res->res_root_list);
1188c2ecf20Sopenharmony_ci	recover_list = !list_empty(&res->res_recover_list);
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	if (root_list || recover_list) {
1218c2ecf20Sopenharmony_ci		seq_printf(s, "Recovery: root %d recover %d flags %lx count %d\n",
1228c2ecf20Sopenharmony_ci			   root_list, recover_list,
1238c2ecf20Sopenharmony_ci			   res->res_flags, res->res_recover_locks_count);
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	/* Print the locks attached to this resource */
1278c2ecf20Sopenharmony_ci	seq_puts(s, "Granted Queue\n");
1288c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
1298c2ecf20Sopenharmony_ci		print_format1_lock(s, lkb, res);
1308c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
1318c2ecf20Sopenharmony_ci			goto out;
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	seq_puts(s, "Conversion Queue\n");
1358c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
1368c2ecf20Sopenharmony_ci		print_format1_lock(s, lkb, res);
1378c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
1388c2ecf20Sopenharmony_ci			goto out;
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	seq_puts(s, "Waiting Queue\n");
1428c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
1438c2ecf20Sopenharmony_ci		print_format1_lock(s, lkb, res);
1448c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
1458c2ecf20Sopenharmony_ci			goto out;
1468c2ecf20Sopenharmony_ci	}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	if (list_empty(&res->res_lookup))
1498c2ecf20Sopenharmony_ci		goto out;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	seq_puts(s, "Lookup Queue\n");
1528c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
1538c2ecf20Sopenharmony_ci		seq_printf(s, "%08x %s",
1548c2ecf20Sopenharmony_ci			   lkb->lkb_id, print_lockmode(lkb->lkb_rqmode));
1558c2ecf20Sopenharmony_ci		if (lkb->lkb_wait_type)
1568c2ecf20Sopenharmony_ci			seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
1578c2ecf20Sopenharmony_ci		seq_putc(s, '\n');
1588c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
1598c2ecf20Sopenharmony_ci			goto out;
1608c2ecf20Sopenharmony_ci	}
1618c2ecf20Sopenharmony_ci out:
1628c2ecf20Sopenharmony_ci	unlock_rsb(res);
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
1668c2ecf20Sopenharmony_ci			       struct dlm_rsb *r)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	u64 xid = 0;
1698c2ecf20Sopenharmony_ci	u64 us;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (lkb->lkb_flags & DLM_IFL_USER) {
1728c2ecf20Sopenharmony_ci		if (lkb->lkb_ua)
1738c2ecf20Sopenharmony_ci			xid = lkb->lkb_ua->xid;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	/* microseconds since lkb was added to current queue */
1778c2ecf20Sopenharmony_ci	us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	/* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
1808c2ecf20Sopenharmony_ci	   r_nodeid r_len r_name */
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
1838c2ecf20Sopenharmony_ci		   lkb->lkb_id,
1848c2ecf20Sopenharmony_ci		   lkb->lkb_nodeid,
1858c2ecf20Sopenharmony_ci		   lkb->lkb_remid,
1868c2ecf20Sopenharmony_ci		   lkb->lkb_ownpid,
1878c2ecf20Sopenharmony_ci		   (unsigned long long)xid,
1888c2ecf20Sopenharmony_ci		   lkb->lkb_exflags,
1898c2ecf20Sopenharmony_ci		   lkb->lkb_flags,
1908c2ecf20Sopenharmony_ci		   lkb->lkb_status,
1918c2ecf20Sopenharmony_ci		   lkb->lkb_grmode,
1928c2ecf20Sopenharmony_ci		   lkb->lkb_rqmode,
1938c2ecf20Sopenharmony_ci		   (unsigned long long)us,
1948c2ecf20Sopenharmony_ci		   r->res_nodeid,
1958c2ecf20Sopenharmony_ci		   r->res_length,
1968c2ecf20Sopenharmony_ci		   r->res_name);
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic void print_format2(struct dlm_rsb *r, struct seq_file *s)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	struct dlm_lkb *lkb;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	lock_rsb(r);
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
2068c2ecf20Sopenharmony_ci		print_format2_lock(s, lkb, r);
2078c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
2088c2ecf20Sopenharmony_ci			goto out;
2098c2ecf20Sopenharmony_ci	}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
2128c2ecf20Sopenharmony_ci		print_format2_lock(s, lkb, r);
2138c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
2148c2ecf20Sopenharmony_ci			goto out;
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
2188c2ecf20Sopenharmony_ci		print_format2_lock(s, lkb, r);
2198c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
2208c2ecf20Sopenharmony_ci			goto out;
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci out:
2238c2ecf20Sopenharmony_ci	unlock_rsb(r);
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
2278c2ecf20Sopenharmony_ci			      int rsb_lookup)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	u64 xid = 0;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (lkb->lkb_flags & DLM_IFL_USER) {
2328c2ecf20Sopenharmony_ci		if (lkb->lkb_ua)
2338c2ecf20Sopenharmony_ci			xid = lkb->lkb_ua->xid;
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
2378c2ecf20Sopenharmony_ci		   lkb->lkb_id,
2388c2ecf20Sopenharmony_ci		   lkb->lkb_nodeid,
2398c2ecf20Sopenharmony_ci		   lkb->lkb_remid,
2408c2ecf20Sopenharmony_ci		   lkb->lkb_ownpid,
2418c2ecf20Sopenharmony_ci		   (unsigned long long)xid,
2428c2ecf20Sopenharmony_ci		   lkb->lkb_exflags,
2438c2ecf20Sopenharmony_ci		   lkb->lkb_flags,
2448c2ecf20Sopenharmony_ci		   lkb->lkb_status,
2458c2ecf20Sopenharmony_ci		   lkb->lkb_grmode,
2468c2ecf20Sopenharmony_ci		   lkb->lkb_rqmode,
2478c2ecf20Sopenharmony_ci		   lkb->lkb_last_bast.mode,
2488c2ecf20Sopenharmony_ci		   rsb_lookup,
2498c2ecf20Sopenharmony_ci		   lkb->lkb_wait_type,
2508c2ecf20Sopenharmony_ci		   lkb->lkb_lvbseq,
2518c2ecf20Sopenharmony_ci		   (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
2528c2ecf20Sopenharmony_ci		   (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time));
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic void print_format3(struct dlm_rsb *r, struct seq_file *s)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	struct dlm_lkb *lkb;
2588c2ecf20Sopenharmony_ci	int i, lvblen = r->res_ls->ls_lvblen;
2598c2ecf20Sopenharmony_ci	int print_name = 1;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	lock_rsb(r);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
2648c2ecf20Sopenharmony_ci		   r,
2658c2ecf20Sopenharmony_ci		   r->res_nodeid,
2668c2ecf20Sopenharmony_ci		   r->res_first_lkid,
2678c2ecf20Sopenharmony_ci		   r->res_flags,
2688c2ecf20Sopenharmony_ci		   !list_empty(&r->res_root_list),
2698c2ecf20Sopenharmony_ci		   !list_empty(&r->res_recover_list),
2708c2ecf20Sopenharmony_ci		   r->res_recover_locks_count,
2718c2ecf20Sopenharmony_ci		   r->res_length);
2728c2ecf20Sopenharmony_ci	if (seq_has_overflowed(s))
2738c2ecf20Sopenharmony_ci		goto out;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	for (i = 0; i < r->res_length; i++) {
2768c2ecf20Sopenharmony_ci		if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
2778c2ecf20Sopenharmony_ci			print_name = 0;
2788c2ecf20Sopenharmony_ci	}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	seq_puts(s, print_name ? "str " : "hex");
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	for (i = 0; i < r->res_length; i++) {
2838c2ecf20Sopenharmony_ci		if (print_name)
2848c2ecf20Sopenharmony_ci			seq_printf(s, "%c", r->res_name[i]);
2858c2ecf20Sopenharmony_ci		else
2868c2ecf20Sopenharmony_ci			seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci	seq_putc(s, '\n');
2898c2ecf20Sopenharmony_ci	if (seq_has_overflowed(s))
2908c2ecf20Sopenharmony_ci		goto out;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (!r->res_lvbptr)
2938c2ecf20Sopenharmony_ci		goto do_locks;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	for (i = 0; i < lvblen; i++)
2988c2ecf20Sopenharmony_ci		seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
2998c2ecf20Sopenharmony_ci	seq_putc(s, '\n');
3008c2ecf20Sopenharmony_ci	if (seq_has_overflowed(s))
3018c2ecf20Sopenharmony_ci		goto out;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci do_locks:
3048c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
3058c2ecf20Sopenharmony_ci		print_format3_lock(s, lkb, 0);
3068c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
3078c2ecf20Sopenharmony_ci			goto out;
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
3118c2ecf20Sopenharmony_ci		print_format3_lock(s, lkb, 0);
3128c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
3138c2ecf20Sopenharmony_ci			goto out;
3148c2ecf20Sopenharmony_ci	}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
3178c2ecf20Sopenharmony_ci		print_format3_lock(s, lkb, 0);
3188c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
3198c2ecf20Sopenharmony_ci			goto out;
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
3238c2ecf20Sopenharmony_ci		print_format3_lock(s, lkb, 1);
3248c2ecf20Sopenharmony_ci		if (seq_has_overflowed(s))
3258c2ecf20Sopenharmony_ci			goto out;
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci out:
3288c2ecf20Sopenharmony_ci	unlock_rsb(r);
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_cistatic void print_format4(struct dlm_rsb *r, struct seq_file *s)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	int our_nodeid = dlm_our_nodeid();
3348c2ecf20Sopenharmony_ci	int print_name = 1;
3358c2ecf20Sopenharmony_ci	int i;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	lock_rsb(r);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	seq_printf(s, "rsb %p %d %d %d %d %lu %lx %d ",
3408c2ecf20Sopenharmony_ci		   r,
3418c2ecf20Sopenharmony_ci		   r->res_nodeid,
3428c2ecf20Sopenharmony_ci		   r->res_master_nodeid,
3438c2ecf20Sopenharmony_ci		   r->res_dir_nodeid,
3448c2ecf20Sopenharmony_ci		   our_nodeid,
3458c2ecf20Sopenharmony_ci		   r->res_toss_time,
3468c2ecf20Sopenharmony_ci		   r->res_flags,
3478c2ecf20Sopenharmony_ci		   r->res_length);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	for (i = 0; i < r->res_length; i++) {
3508c2ecf20Sopenharmony_ci		if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
3518c2ecf20Sopenharmony_ci			print_name = 0;
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	seq_puts(s, print_name ? "str " : "hex");
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	for (i = 0; i < r->res_length; i++) {
3578c2ecf20Sopenharmony_ci		if (print_name)
3588c2ecf20Sopenharmony_ci			seq_printf(s, "%c", r->res_name[i]);
3598c2ecf20Sopenharmony_ci		else
3608c2ecf20Sopenharmony_ci			seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
3618c2ecf20Sopenharmony_ci	}
3628c2ecf20Sopenharmony_ci	seq_putc(s, '\n');
3638c2ecf20Sopenharmony_ci	unlock_rsb(r);
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_cistruct rsbtbl_iter {
3678c2ecf20Sopenharmony_ci	struct dlm_rsb *rsb;
3688c2ecf20Sopenharmony_ci	unsigned bucket;
3698c2ecf20Sopenharmony_ci	int format;
3708c2ecf20Sopenharmony_ci	int header;
3718c2ecf20Sopenharmony_ci};
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci/*
3748c2ecf20Sopenharmony_ci * If the buffer is full, seq_printf can be called again, but it
3758c2ecf20Sopenharmony_ci * does nothing.  So, the these printing routines periodically check
3768c2ecf20Sopenharmony_ci * seq_has_overflowed to avoid wasting too much time trying to print to
3778c2ecf20Sopenharmony_ci * a full buffer.
3788c2ecf20Sopenharmony_ci */
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_cistatic int table_seq_show(struct seq_file *seq, void *iter_ptr)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	struct rsbtbl_iter *ri = iter_ptr;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	switch (ri->format) {
3858c2ecf20Sopenharmony_ci	case 1:
3868c2ecf20Sopenharmony_ci		print_format1(ri->rsb, seq);
3878c2ecf20Sopenharmony_ci		break;
3888c2ecf20Sopenharmony_ci	case 2:
3898c2ecf20Sopenharmony_ci		if (ri->header) {
3908c2ecf20Sopenharmony_ci			seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
3918c2ecf20Sopenharmony_ci			ri->header = 0;
3928c2ecf20Sopenharmony_ci		}
3938c2ecf20Sopenharmony_ci		print_format2(ri->rsb, seq);
3948c2ecf20Sopenharmony_ci		break;
3958c2ecf20Sopenharmony_ci	case 3:
3968c2ecf20Sopenharmony_ci		if (ri->header) {
3978c2ecf20Sopenharmony_ci			seq_puts(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
3988c2ecf20Sopenharmony_ci			ri->header = 0;
3998c2ecf20Sopenharmony_ci		}
4008c2ecf20Sopenharmony_ci		print_format3(ri->rsb, seq);
4018c2ecf20Sopenharmony_ci		break;
4028c2ecf20Sopenharmony_ci	case 4:
4038c2ecf20Sopenharmony_ci		if (ri->header) {
4048c2ecf20Sopenharmony_ci			seq_puts(seq, "version 4 rsb 2\n");
4058c2ecf20Sopenharmony_ci			ri->header = 0;
4068c2ecf20Sopenharmony_ci		}
4078c2ecf20Sopenharmony_ci		print_format4(ri->rsb, seq);
4088c2ecf20Sopenharmony_ci		break;
4098c2ecf20Sopenharmony_ci	}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	return 0;
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic const struct seq_operations format1_seq_ops;
4158c2ecf20Sopenharmony_cistatic const struct seq_operations format2_seq_ops;
4168c2ecf20Sopenharmony_cistatic const struct seq_operations format3_seq_ops;
4178c2ecf20Sopenharmony_cistatic const struct seq_operations format4_seq_ops;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_cistatic void *table_seq_start(struct seq_file *seq, loff_t *pos)
4208c2ecf20Sopenharmony_ci{
4218c2ecf20Sopenharmony_ci	struct rb_root *tree;
4228c2ecf20Sopenharmony_ci	struct rb_node *node;
4238c2ecf20Sopenharmony_ci	struct dlm_ls *ls = seq->private;
4248c2ecf20Sopenharmony_ci	struct rsbtbl_iter *ri;
4258c2ecf20Sopenharmony_ci	struct dlm_rsb *r;
4268c2ecf20Sopenharmony_ci	loff_t n = *pos;
4278c2ecf20Sopenharmony_ci	unsigned bucket, entry;
4288c2ecf20Sopenharmony_ci	int toss = (seq->op == &format4_seq_ops);
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	bucket = n >> 32;
4318c2ecf20Sopenharmony_ci	entry = n & ((1LL << 32) - 1);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	if (bucket >= ls->ls_rsbtbl_size)
4348c2ecf20Sopenharmony_ci		return NULL;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	ri = kzalloc(sizeof(*ri), GFP_NOFS);
4378c2ecf20Sopenharmony_ci	if (!ri)
4388c2ecf20Sopenharmony_ci		return NULL;
4398c2ecf20Sopenharmony_ci	if (n == 0)
4408c2ecf20Sopenharmony_ci		ri->header = 1;
4418c2ecf20Sopenharmony_ci	if (seq->op == &format1_seq_ops)
4428c2ecf20Sopenharmony_ci		ri->format = 1;
4438c2ecf20Sopenharmony_ci	if (seq->op == &format2_seq_ops)
4448c2ecf20Sopenharmony_ci		ri->format = 2;
4458c2ecf20Sopenharmony_ci	if (seq->op == &format3_seq_ops)
4468c2ecf20Sopenharmony_ci		ri->format = 3;
4478c2ecf20Sopenharmony_ci	if (seq->op == &format4_seq_ops)
4488c2ecf20Sopenharmony_ci		ri->format = 4;
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	spin_lock(&ls->ls_rsbtbl[bucket].lock);
4538c2ecf20Sopenharmony_ci	if (!RB_EMPTY_ROOT(tree)) {
4548c2ecf20Sopenharmony_ci		for (node = rb_first(tree); node; node = rb_next(node)) {
4558c2ecf20Sopenharmony_ci			r = rb_entry(node, struct dlm_rsb, res_hashnode);
4568c2ecf20Sopenharmony_ci			if (!entry--) {
4578c2ecf20Sopenharmony_ci				dlm_hold_rsb(r);
4588c2ecf20Sopenharmony_ci				ri->rsb = r;
4598c2ecf20Sopenharmony_ci				ri->bucket = bucket;
4608c2ecf20Sopenharmony_ci				spin_unlock(&ls->ls_rsbtbl[bucket].lock);
4618c2ecf20Sopenharmony_ci				return ri;
4628c2ecf20Sopenharmony_ci			}
4638c2ecf20Sopenharmony_ci		}
4648c2ecf20Sopenharmony_ci	}
4658c2ecf20Sopenharmony_ci	spin_unlock(&ls->ls_rsbtbl[bucket].lock);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	/*
4688c2ecf20Sopenharmony_ci	 * move to the first rsb in the next non-empty bucket
4698c2ecf20Sopenharmony_ci	 */
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	/* zero the entry */
4728c2ecf20Sopenharmony_ci	n &= ~((1LL << 32) - 1);
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	while (1) {
4758c2ecf20Sopenharmony_ci		bucket++;
4768c2ecf20Sopenharmony_ci		n += 1LL << 32;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci		if (bucket >= ls->ls_rsbtbl_size) {
4798c2ecf20Sopenharmony_ci			kfree(ri);
4808c2ecf20Sopenharmony_ci			return NULL;
4818c2ecf20Sopenharmony_ci		}
4828c2ecf20Sopenharmony_ci		tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci		spin_lock(&ls->ls_rsbtbl[bucket].lock);
4858c2ecf20Sopenharmony_ci		if (!RB_EMPTY_ROOT(tree)) {
4868c2ecf20Sopenharmony_ci			node = rb_first(tree);
4878c2ecf20Sopenharmony_ci			r = rb_entry(node, struct dlm_rsb, res_hashnode);
4888c2ecf20Sopenharmony_ci			dlm_hold_rsb(r);
4898c2ecf20Sopenharmony_ci			ri->rsb = r;
4908c2ecf20Sopenharmony_ci			ri->bucket = bucket;
4918c2ecf20Sopenharmony_ci			spin_unlock(&ls->ls_rsbtbl[bucket].lock);
4928c2ecf20Sopenharmony_ci			*pos = n;
4938c2ecf20Sopenharmony_ci			return ri;
4948c2ecf20Sopenharmony_ci		}
4958c2ecf20Sopenharmony_ci		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
4968c2ecf20Sopenharmony_ci	}
4978c2ecf20Sopenharmony_ci}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_cistatic void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
5008c2ecf20Sopenharmony_ci{
5018c2ecf20Sopenharmony_ci	struct dlm_ls *ls = seq->private;
5028c2ecf20Sopenharmony_ci	struct rsbtbl_iter *ri = iter_ptr;
5038c2ecf20Sopenharmony_ci	struct rb_root *tree;
5048c2ecf20Sopenharmony_ci	struct rb_node *next;
5058c2ecf20Sopenharmony_ci	struct dlm_rsb *r, *rp;
5068c2ecf20Sopenharmony_ci	loff_t n = *pos;
5078c2ecf20Sopenharmony_ci	unsigned bucket;
5088c2ecf20Sopenharmony_ci	int toss = (seq->op == &format4_seq_ops);
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	bucket = n >> 32;
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	/*
5138c2ecf20Sopenharmony_ci	 * move to the next rsb in the same bucket
5148c2ecf20Sopenharmony_ci	 */
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	spin_lock(&ls->ls_rsbtbl[bucket].lock);
5178c2ecf20Sopenharmony_ci	rp = ri->rsb;
5188c2ecf20Sopenharmony_ci	next = rb_next(&rp->res_hashnode);
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	if (next) {
5218c2ecf20Sopenharmony_ci		r = rb_entry(next, struct dlm_rsb, res_hashnode);
5228c2ecf20Sopenharmony_ci		dlm_hold_rsb(r);
5238c2ecf20Sopenharmony_ci		ri->rsb = r;
5248c2ecf20Sopenharmony_ci		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
5258c2ecf20Sopenharmony_ci		dlm_put_rsb(rp);
5268c2ecf20Sopenharmony_ci		++*pos;
5278c2ecf20Sopenharmony_ci		return ri;
5288c2ecf20Sopenharmony_ci	}
5298c2ecf20Sopenharmony_ci	spin_unlock(&ls->ls_rsbtbl[bucket].lock);
5308c2ecf20Sopenharmony_ci	dlm_put_rsb(rp);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	/*
5338c2ecf20Sopenharmony_ci	 * move to the first rsb in the next non-empty bucket
5348c2ecf20Sopenharmony_ci	 */
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	/* zero the entry */
5378c2ecf20Sopenharmony_ci	n &= ~((1LL << 32) - 1);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	while (1) {
5408c2ecf20Sopenharmony_ci		bucket++;
5418c2ecf20Sopenharmony_ci		n += 1LL << 32;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci		if (bucket >= ls->ls_rsbtbl_size) {
5448c2ecf20Sopenharmony_ci			kfree(ri);
5458c2ecf20Sopenharmony_ci			++*pos;
5468c2ecf20Sopenharmony_ci			return NULL;
5478c2ecf20Sopenharmony_ci		}
5488c2ecf20Sopenharmony_ci		tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci		spin_lock(&ls->ls_rsbtbl[bucket].lock);
5518c2ecf20Sopenharmony_ci		if (!RB_EMPTY_ROOT(tree)) {
5528c2ecf20Sopenharmony_ci			next = rb_first(tree);
5538c2ecf20Sopenharmony_ci			r = rb_entry(next, struct dlm_rsb, res_hashnode);
5548c2ecf20Sopenharmony_ci			dlm_hold_rsb(r);
5558c2ecf20Sopenharmony_ci			ri->rsb = r;
5568c2ecf20Sopenharmony_ci			ri->bucket = bucket;
5578c2ecf20Sopenharmony_ci			spin_unlock(&ls->ls_rsbtbl[bucket].lock);
5588c2ecf20Sopenharmony_ci			*pos = n;
5598c2ecf20Sopenharmony_ci			return ri;
5608c2ecf20Sopenharmony_ci		}
5618c2ecf20Sopenharmony_ci		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_cistatic void table_seq_stop(struct seq_file *seq, void *iter_ptr)
5668c2ecf20Sopenharmony_ci{
5678c2ecf20Sopenharmony_ci	struct rsbtbl_iter *ri = iter_ptr;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	if (ri) {
5708c2ecf20Sopenharmony_ci		dlm_put_rsb(ri->rsb);
5718c2ecf20Sopenharmony_ci		kfree(ri);
5728c2ecf20Sopenharmony_ci	}
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_cistatic const struct seq_operations format1_seq_ops = {
5768c2ecf20Sopenharmony_ci	.start = table_seq_start,
5778c2ecf20Sopenharmony_ci	.next  = table_seq_next,
5788c2ecf20Sopenharmony_ci	.stop  = table_seq_stop,
5798c2ecf20Sopenharmony_ci	.show  = table_seq_show,
5808c2ecf20Sopenharmony_ci};
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic const struct seq_operations format2_seq_ops = {
5838c2ecf20Sopenharmony_ci	.start = table_seq_start,
5848c2ecf20Sopenharmony_ci	.next  = table_seq_next,
5858c2ecf20Sopenharmony_ci	.stop  = table_seq_stop,
5868c2ecf20Sopenharmony_ci	.show  = table_seq_show,
5878c2ecf20Sopenharmony_ci};
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_cistatic const struct seq_operations format3_seq_ops = {
5908c2ecf20Sopenharmony_ci	.start = table_seq_start,
5918c2ecf20Sopenharmony_ci	.next  = table_seq_next,
5928c2ecf20Sopenharmony_ci	.stop  = table_seq_stop,
5938c2ecf20Sopenharmony_ci	.show  = table_seq_show,
5948c2ecf20Sopenharmony_ci};
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_cistatic const struct seq_operations format4_seq_ops = {
5978c2ecf20Sopenharmony_ci	.start = table_seq_start,
5988c2ecf20Sopenharmony_ci	.next  = table_seq_next,
5998c2ecf20Sopenharmony_ci	.stop  = table_seq_stop,
6008c2ecf20Sopenharmony_ci	.show  = table_seq_show,
6018c2ecf20Sopenharmony_ci};
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_cistatic const struct file_operations format1_fops;
6048c2ecf20Sopenharmony_cistatic const struct file_operations format2_fops;
6058c2ecf20Sopenharmony_cistatic const struct file_operations format3_fops;
6068c2ecf20Sopenharmony_cistatic const struct file_operations format4_fops;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_cistatic int table_open1(struct inode *inode, struct file *file)
6098c2ecf20Sopenharmony_ci{
6108c2ecf20Sopenharmony_ci	struct seq_file *seq;
6118c2ecf20Sopenharmony_ci	int ret;
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	ret = seq_open(file, &format1_seq_ops);
6148c2ecf20Sopenharmony_ci	if (ret)
6158c2ecf20Sopenharmony_ci		return ret;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	seq = file->private_data;
6188c2ecf20Sopenharmony_ci	seq->private = inode->i_private; /* the dlm_ls */
6198c2ecf20Sopenharmony_ci	return 0;
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_cistatic int table_open2(struct inode *inode, struct file *file)
6238c2ecf20Sopenharmony_ci{
6248c2ecf20Sopenharmony_ci	struct seq_file *seq;
6258c2ecf20Sopenharmony_ci	int ret;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	ret = seq_open(file, &format2_seq_ops);
6288c2ecf20Sopenharmony_ci	if (ret)
6298c2ecf20Sopenharmony_ci		return ret;
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	seq = file->private_data;
6328c2ecf20Sopenharmony_ci	seq->private = inode->i_private; /* the dlm_ls */
6338c2ecf20Sopenharmony_ci	return 0;
6348c2ecf20Sopenharmony_ci}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_cistatic int table_open3(struct inode *inode, struct file *file)
6378c2ecf20Sopenharmony_ci{
6388c2ecf20Sopenharmony_ci	struct seq_file *seq;
6398c2ecf20Sopenharmony_ci	int ret;
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	ret = seq_open(file, &format3_seq_ops);
6428c2ecf20Sopenharmony_ci	if (ret)
6438c2ecf20Sopenharmony_ci		return ret;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	seq = file->private_data;
6468c2ecf20Sopenharmony_ci	seq->private = inode->i_private; /* the dlm_ls */
6478c2ecf20Sopenharmony_ci	return 0;
6488c2ecf20Sopenharmony_ci}
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_cistatic int table_open4(struct inode *inode, struct file *file)
6518c2ecf20Sopenharmony_ci{
6528c2ecf20Sopenharmony_ci	struct seq_file *seq;
6538c2ecf20Sopenharmony_ci	int ret;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	ret = seq_open(file, &format4_seq_ops);
6568c2ecf20Sopenharmony_ci	if (ret)
6578c2ecf20Sopenharmony_ci		return ret;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	seq = file->private_data;
6608c2ecf20Sopenharmony_ci	seq->private = inode->i_private; /* the dlm_ls */
6618c2ecf20Sopenharmony_ci	return 0;
6628c2ecf20Sopenharmony_ci}
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_cistatic const struct file_operations format1_fops = {
6658c2ecf20Sopenharmony_ci	.owner   = THIS_MODULE,
6668c2ecf20Sopenharmony_ci	.open    = table_open1,
6678c2ecf20Sopenharmony_ci	.read    = seq_read,
6688c2ecf20Sopenharmony_ci	.llseek  = seq_lseek,
6698c2ecf20Sopenharmony_ci	.release = seq_release
6708c2ecf20Sopenharmony_ci};
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistatic const struct file_operations format2_fops = {
6738c2ecf20Sopenharmony_ci	.owner   = THIS_MODULE,
6748c2ecf20Sopenharmony_ci	.open    = table_open2,
6758c2ecf20Sopenharmony_ci	.read    = seq_read,
6768c2ecf20Sopenharmony_ci	.llseek  = seq_lseek,
6778c2ecf20Sopenharmony_ci	.release = seq_release
6788c2ecf20Sopenharmony_ci};
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_cistatic const struct file_operations format3_fops = {
6818c2ecf20Sopenharmony_ci	.owner   = THIS_MODULE,
6828c2ecf20Sopenharmony_ci	.open    = table_open3,
6838c2ecf20Sopenharmony_ci	.read    = seq_read,
6848c2ecf20Sopenharmony_ci	.llseek  = seq_lseek,
6858c2ecf20Sopenharmony_ci	.release = seq_release
6868c2ecf20Sopenharmony_ci};
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_cistatic const struct file_operations format4_fops = {
6898c2ecf20Sopenharmony_ci	.owner   = THIS_MODULE,
6908c2ecf20Sopenharmony_ci	.open    = table_open4,
6918c2ecf20Sopenharmony_ci	.read    = seq_read,
6928c2ecf20Sopenharmony_ci	.llseek  = seq_lseek,
6938c2ecf20Sopenharmony_ci	.release = seq_release
6948c2ecf20Sopenharmony_ci};
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci/*
6978c2ecf20Sopenharmony_ci * dump lkb's on the ls_waiters list
6988c2ecf20Sopenharmony_ci */
6998c2ecf20Sopenharmony_cistatic ssize_t waiters_read(struct file *file, char __user *userbuf,
7008c2ecf20Sopenharmony_ci			    size_t count, loff_t *ppos)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	struct dlm_ls *ls = file->private_data;
7038c2ecf20Sopenharmony_ci	struct dlm_lkb *lkb;
7048c2ecf20Sopenharmony_ci	size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	mutex_lock(&debug_buf_lock);
7078c2ecf20Sopenharmony_ci	mutex_lock(&ls->ls_waiters_mutex);
7088c2ecf20Sopenharmony_ci	memset(debug_buf, 0, sizeof(debug_buf));
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
7118c2ecf20Sopenharmony_ci		ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
7128c2ecf20Sopenharmony_ci			       lkb->lkb_id, lkb->lkb_wait_type,
7138c2ecf20Sopenharmony_ci			       lkb->lkb_nodeid, lkb->lkb_resource->res_name);
7148c2ecf20Sopenharmony_ci		if (ret >= len - pos)
7158c2ecf20Sopenharmony_ci			break;
7168c2ecf20Sopenharmony_ci		pos += ret;
7178c2ecf20Sopenharmony_ci	}
7188c2ecf20Sopenharmony_ci	mutex_unlock(&ls->ls_waiters_mutex);
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
7218c2ecf20Sopenharmony_ci	mutex_unlock(&debug_buf_lock);
7228c2ecf20Sopenharmony_ci	return rv;
7238c2ecf20Sopenharmony_ci}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_cistatic const struct file_operations waiters_fops = {
7268c2ecf20Sopenharmony_ci	.owner   = THIS_MODULE,
7278c2ecf20Sopenharmony_ci	.open    = simple_open,
7288c2ecf20Sopenharmony_ci	.read    = waiters_read,
7298c2ecf20Sopenharmony_ci	.llseek  = default_llseek,
7308c2ecf20Sopenharmony_ci};
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_civoid dlm_delete_debug_file(struct dlm_ls *ls)
7338c2ecf20Sopenharmony_ci{
7348c2ecf20Sopenharmony_ci	debugfs_remove(ls->ls_debug_rsb_dentry);
7358c2ecf20Sopenharmony_ci	debugfs_remove(ls->ls_debug_waiters_dentry);
7368c2ecf20Sopenharmony_ci	debugfs_remove(ls->ls_debug_locks_dentry);
7378c2ecf20Sopenharmony_ci	debugfs_remove(ls->ls_debug_all_dentry);
7388c2ecf20Sopenharmony_ci	debugfs_remove(ls->ls_debug_toss_dentry);
7398c2ecf20Sopenharmony_ci}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_civoid dlm_create_debug_file(struct dlm_ls *ls)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	char name[DLM_LOCKSPACE_LEN + 8];
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	/* format 1 */
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
7488c2ecf20Sopenharmony_ci						      S_IFREG | S_IRUGO,
7498c2ecf20Sopenharmony_ci						      dlm_root,
7508c2ecf20Sopenharmony_ci						      ls,
7518c2ecf20Sopenharmony_ci						      &format1_fops);
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	/* format 2 */
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	memset(name, 0, sizeof(name));
7568c2ecf20Sopenharmony_ci	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_locks", ls->ls_name);
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	ls->ls_debug_locks_dentry = debugfs_create_file(name,
7598c2ecf20Sopenharmony_ci							S_IFREG | S_IRUGO,
7608c2ecf20Sopenharmony_ci							dlm_root,
7618c2ecf20Sopenharmony_ci							ls,
7628c2ecf20Sopenharmony_ci							&format2_fops);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	/* format 3 */
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	memset(name, 0, sizeof(name));
7678c2ecf20Sopenharmony_ci	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_all", ls->ls_name);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	ls->ls_debug_all_dentry = debugfs_create_file(name,
7708c2ecf20Sopenharmony_ci						      S_IFREG | S_IRUGO,
7718c2ecf20Sopenharmony_ci						      dlm_root,
7728c2ecf20Sopenharmony_ci						      ls,
7738c2ecf20Sopenharmony_ci						      &format3_fops);
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	/* format 4 */
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	memset(name, 0, sizeof(name));
7788c2ecf20Sopenharmony_ci	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_toss", ls->ls_name);
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	ls->ls_debug_toss_dentry = debugfs_create_file(name,
7818c2ecf20Sopenharmony_ci						       S_IFREG | S_IRUGO,
7828c2ecf20Sopenharmony_ci						       dlm_root,
7838c2ecf20Sopenharmony_ci						       ls,
7848c2ecf20Sopenharmony_ci						       &format4_fops);
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	memset(name, 0, sizeof(name));
7878c2ecf20Sopenharmony_ci	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_waiters", ls->ls_name);
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	ls->ls_debug_waiters_dentry = debugfs_create_file(name,
7908c2ecf20Sopenharmony_ci							  S_IFREG | S_IRUGO,
7918c2ecf20Sopenharmony_ci							  dlm_root,
7928c2ecf20Sopenharmony_ci							  ls,
7938c2ecf20Sopenharmony_ci							  &waiters_fops);
7948c2ecf20Sopenharmony_ci}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_civoid __init dlm_register_debugfs(void)
7978c2ecf20Sopenharmony_ci{
7988c2ecf20Sopenharmony_ci	mutex_init(&debug_buf_lock);
7998c2ecf20Sopenharmony_ci	dlm_root = debugfs_create_dir("dlm", NULL);
8008c2ecf20Sopenharmony_ci}
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_civoid dlm_unregister_debugfs(void)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	debugfs_remove(dlm_root);
8058c2ecf20Sopenharmony_ci}
8068c2ecf20Sopenharmony_ci
807