cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

debug_fs.c (22048B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/******************************************************************************
      3*******************************************************************************
      4**
      5**  Copyright (C) 2005-2009 Red Hat, Inc.  All rights reserved.
      6**
      7**
      8*******************************************************************************
      9******************************************************************************/
     10
     11#include <linux/pagemap.h>
     12#include <linux/seq_file.h>
     13#include <linux/init.h>
     14#include <linux/ctype.h>
     15#include <linux/debugfs.h>
     16#include <linux/slab.h>
     17
     18#include "dlm_internal.h"
     19#include "midcomms.h"
     20#include "lock.h"
     21
     22#define DLM_DEBUG_BUF_LEN 4096
     23static char debug_buf[DLM_DEBUG_BUF_LEN];
     24static struct mutex debug_buf_lock;
     25
     26static struct dentry *dlm_root;
     27static struct dentry *dlm_comms;
     28
     29static char *print_lockmode(int mode)
     30{
     31	switch (mode) {
     32	case DLM_LOCK_IV:
     33		return "--";
     34	case DLM_LOCK_NL:
     35		return "NL";
     36	case DLM_LOCK_CR:
     37		return "CR";
     38	case DLM_LOCK_CW:
     39		return "CW";
     40	case DLM_LOCK_PR:
     41		return "PR";
     42	case DLM_LOCK_PW:
     43		return "PW";
     44	case DLM_LOCK_EX:
     45		return "EX";
     46	default:
     47		return "??";
     48	}
     49}
     50
     51static void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
     52			       struct dlm_rsb *res)
     53{
     54	seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
     55
     56	if (lkb->lkb_status == DLM_LKSTS_CONVERT ||
     57	    lkb->lkb_status == DLM_LKSTS_WAITING)
     58		seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode));
     59
     60	if (lkb->lkb_nodeid) {
     61		if (lkb->lkb_nodeid != res->res_nodeid)
     62			seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid,
     63				   lkb->lkb_remid);
     64		else
     65			seq_printf(s, " Master:     %08x", lkb->lkb_remid);
     66	}
     67
     68	if (lkb->lkb_wait_type)
     69		seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
     70
     71	seq_putc(s, '\n');
     72}
     73
     74static void print_format1(struct dlm_rsb *res, struct seq_file *s)
     75{
     76	struct dlm_lkb *lkb;
     77	int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
     78
     79	lock_rsb(res);
     80
     81	seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
     82
     83	for (i = 0; i < res->res_length; i++) {
     84		if (isprint(res->res_name[i]))
     85			seq_printf(s, "%c", res->res_name[i]);
     86		else
     87			seq_printf(s, "%c", '.');
     88	}
     89
     90	if (res->res_nodeid > 0)
     91		seq_printf(s, "\"\nLocal Copy, Master is node %d\n",
     92			   res->res_nodeid);
     93	else if (res->res_nodeid == 0)
     94		seq_puts(s, "\"\nMaster Copy\n");
     95	else if (res->res_nodeid == -1)
     96		seq_printf(s, "\"\nLooking up master (lkid %x)\n",
     97			   res->res_first_lkid);
     98	else
     99		seq_printf(s, "\"\nInvalid master %d\n", res->res_nodeid);
    100	if (seq_has_overflowed(s))
    101		goto out;
    102
    103	/* Print the LVB: */
    104	if (res->res_lvbptr) {
    105		seq_puts(s, "LVB: ");
    106		for (i = 0; i < lvblen; i++) {
    107			if (i == lvblen / 2)
    108				seq_puts(s, "\n     ");
    109			seq_printf(s, "%02x ",
    110				   (unsigned char) res->res_lvbptr[i]);
    111		}
    112		if (rsb_flag(res, RSB_VALNOTVALID))
    113			seq_puts(s, " (INVALID)");
    114		seq_putc(s, '\n');
    115		if (seq_has_overflowed(s))
    116			goto out;
    117	}
    118
    119	root_list = !list_empty(&res->res_root_list);
    120	recover_list = !list_empty(&res->res_recover_list);
    121
    122	if (root_list || recover_list) {
    123		seq_printf(s, "Recovery: root %d recover %d flags %lx count %d\n",
    124			   root_list, recover_list,
    125			   res->res_flags, res->res_recover_locks_count);
    126	}
    127
    128	/* Print the locks attached to this resource */
    129	seq_puts(s, "Granted Queue\n");
    130	list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
    131		print_format1_lock(s, lkb, res);
    132		if (seq_has_overflowed(s))
    133			goto out;
    134	}
    135
    136	seq_puts(s, "Conversion Queue\n");
    137	list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
    138		print_format1_lock(s, lkb, res);
    139		if (seq_has_overflowed(s))
    140			goto out;
    141	}
    142
    143	seq_puts(s, "Waiting Queue\n");
    144	list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
    145		print_format1_lock(s, lkb, res);
    146		if (seq_has_overflowed(s))
    147			goto out;
    148	}
    149
    150	if (list_empty(&res->res_lookup))
    151		goto out;
    152
    153	seq_puts(s, "Lookup Queue\n");
    154	list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
    155		seq_printf(s, "%08x %s",
    156			   lkb->lkb_id, print_lockmode(lkb->lkb_rqmode));
    157		if (lkb->lkb_wait_type)
    158			seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
    159		seq_putc(s, '\n');
    160		if (seq_has_overflowed(s))
    161			goto out;
    162	}
    163 out:
    164	unlock_rsb(res);
    165}
    166
    167static void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb,
    168			       struct dlm_rsb *r)
    169{
    170	u64 xid = 0;
    171	u64 us;
    172
    173	if (lkb->lkb_flags & DLM_IFL_USER) {
    174		if (lkb->lkb_ua)
    175			xid = lkb->lkb_ua->xid;
    176	}
    177
    178	/* microseconds since lkb was added to current queue */
    179	us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp));
    180
    181	/* id nodeid remid pid xid exflags flags sts grmode rqmode time_us
    182	   r_nodeid r_len r_name */
    183
    184	seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n",
    185		   lkb->lkb_id,
    186		   lkb->lkb_nodeid,
    187		   lkb->lkb_remid,
    188		   lkb->lkb_ownpid,
    189		   (unsigned long long)xid,
    190		   lkb->lkb_exflags,
    191		   lkb->lkb_flags,
    192		   lkb->lkb_status,
    193		   lkb->lkb_grmode,
    194		   lkb->lkb_rqmode,
    195		   (unsigned long long)us,
    196		   r->res_nodeid,
    197		   r->res_length,
    198		   r->res_name);
    199}
    200
    201static void print_format2(struct dlm_rsb *r, struct seq_file *s)
    202{
    203	struct dlm_lkb *lkb;
    204
    205	lock_rsb(r);
    206
    207	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
    208		print_format2_lock(s, lkb, r);
    209		if (seq_has_overflowed(s))
    210			goto out;
    211	}
    212
    213	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
    214		print_format2_lock(s, lkb, r);
    215		if (seq_has_overflowed(s))
    216			goto out;
    217	}
    218
    219	list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
    220		print_format2_lock(s, lkb, r);
    221		if (seq_has_overflowed(s))
    222			goto out;
    223	}
    224 out:
    225	unlock_rsb(r);
    226}
    227
    228static void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
    229			      int rsb_lookup)
    230{
    231	u64 xid = 0;
    232
    233	if (lkb->lkb_flags & DLM_IFL_USER) {
    234		if (lkb->lkb_ua)
    235			xid = lkb->lkb_ua->xid;
    236	}
    237
    238	seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n",
    239		   lkb->lkb_id,
    240		   lkb->lkb_nodeid,
    241		   lkb->lkb_remid,
    242		   lkb->lkb_ownpid,
    243		   (unsigned long long)xid,
    244		   lkb->lkb_exflags,
    245		   lkb->lkb_flags,
    246		   lkb->lkb_status,
    247		   lkb->lkb_grmode,
    248		   lkb->lkb_rqmode,
    249		   lkb->lkb_last_bast.mode,
    250		   rsb_lookup,
    251		   lkb->lkb_wait_type,
    252		   lkb->lkb_lvbseq,
    253		   (unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
    254		   (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time));
    255}
    256
    257static void print_format3(struct dlm_rsb *r, struct seq_file *s)
    258{
    259	struct dlm_lkb *lkb;
    260	int i, lvblen = r->res_ls->ls_lvblen;
    261	int print_name = 1;
    262
    263	lock_rsb(r);
    264
    265	seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ",
    266		   r,
    267		   r->res_nodeid,
    268		   r->res_first_lkid,
    269		   r->res_flags,
    270		   !list_empty(&r->res_root_list),
    271		   !list_empty(&r->res_recover_list),
    272		   r->res_recover_locks_count,
    273		   r->res_length);
    274	if (seq_has_overflowed(s))
    275		goto out;
    276
    277	for (i = 0; i < r->res_length; i++) {
    278		if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
    279			print_name = 0;
    280	}
    281
    282	seq_puts(s, print_name ? "str " : "hex");
    283
    284	for (i = 0; i < r->res_length; i++) {
    285		if (print_name)
    286			seq_printf(s, "%c", r->res_name[i]);
    287		else
    288			seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
    289	}
    290	seq_putc(s, '\n');
    291	if (seq_has_overflowed(s))
    292		goto out;
    293
    294	if (!r->res_lvbptr)
    295		goto do_locks;
    296
    297	seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen);
    298
    299	for (i = 0; i < lvblen; i++)
    300		seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
    301	seq_putc(s, '\n');
    302	if (seq_has_overflowed(s))
    303		goto out;
    304
    305 do_locks:
    306	list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
    307		print_format3_lock(s, lkb, 0);
    308		if (seq_has_overflowed(s))
    309			goto out;
    310	}
    311
    312	list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
    313		print_format3_lock(s, lkb, 0);
    314		if (seq_has_overflowed(s))
    315			goto out;
    316	}
    317
    318	list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
    319		print_format3_lock(s, lkb, 0);
    320		if (seq_has_overflowed(s))
    321			goto out;
    322	}
    323
    324	list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) {
    325		print_format3_lock(s, lkb, 1);
    326		if (seq_has_overflowed(s))
    327			goto out;
    328	}
    329 out:
    330	unlock_rsb(r);
    331}
    332
    333static void print_format4(struct dlm_rsb *r, struct seq_file *s)
    334{
    335	int our_nodeid = dlm_our_nodeid();
    336	int print_name = 1;
    337	int i;
    338
    339	lock_rsb(r);
    340
    341	seq_printf(s, "rsb %p %d %d %d %d %lu %lx %d ",
    342		   r,
    343		   r->res_nodeid,
    344		   r->res_master_nodeid,
    345		   r->res_dir_nodeid,
    346		   our_nodeid,
    347		   r->res_toss_time,
    348		   r->res_flags,
    349		   r->res_length);
    350
    351	for (i = 0; i < r->res_length; i++) {
    352		if (!isascii(r->res_name[i]) || !isprint(r->res_name[i]))
    353			print_name = 0;
    354	}
    355
    356	seq_puts(s, print_name ? "str " : "hex");
    357
    358	for (i = 0; i < r->res_length; i++) {
    359		if (print_name)
    360			seq_printf(s, "%c", r->res_name[i]);
    361		else
    362			seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
    363	}
    364	seq_putc(s, '\n');
    365	unlock_rsb(r);
    366}
    367
    368struct rsbtbl_iter {
    369	struct dlm_rsb *rsb;
    370	unsigned bucket;
    371	int format;
    372	int header;
    373};
    374
    375/*
    376 * If the buffer is full, seq_printf can be called again, but it
    377 * does nothing.  So, the these printing routines periodically check
    378 * seq_has_overflowed to avoid wasting too much time trying to print to
    379 * a full buffer.
    380 */
    381
    382static int table_seq_show(struct seq_file *seq, void *iter_ptr)
    383{
    384	struct rsbtbl_iter *ri = iter_ptr;
    385
    386	switch (ri->format) {
    387	case 1:
    388		print_format1(ri->rsb, seq);
    389		break;
    390	case 2:
    391		if (ri->header) {
    392			seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n");
    393			ri->header = 0;
    394		}
    395		print_format2(ri->rsb, seq);
    396		break;
    397	case 3:
    398		if (ri->header) {
    399			seq_puts(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n");
    400			ri->header = 0;
    401		}
    402		print_format3(ri->rsb, seq);
    403		break;
    404	case 4:
    405		if (ri->header) {
    406			seq_puts(seq, "version 4 rsb 2\n");
    407			ri->header = 0;
    408		}
    409		print_format4(ri->rsb, seq);
    410		break;
    411	}
    412
    413	return 0;
    414}
    415
    416static const struct seq_operations format1_seq_ops;
    417static const struct seq_operations format2_seq_ops;
    418static const struct seq_operations format3_seq_ops;
    419static const struct seq_operations format4_seq_ops;
    420
    421static void *table_seq_start(struct seq_file *seq, loff_t *pos)
    422{
    423	struct rb_root *tree;
    424	struct rb_node *node;
    425	struct dlm_ls *ls = seq->private;
    426	struct rsbtbl_iter *ri;
    427	struct dlm_rsb *r;
    428	loff_t n = *pos;
    429	unsigned bucket, entry;
    430	int toss = (seq->op == &format4_seq_ops);
    431
    432	bucket = n >> 32;
    433	entry = n & ((1LL << 32) - 1);
    434
    435	if (bucket >= ls->ls_rsbtbl_size)
    436		return NULL;
    437
    438	ri = kzalloc(sizeof(*ri), GFP_NOFS);
    439	if (!ri)
    440		return NULL;
    441	if (n == 0)
    442		ri->header = 1;
    443	if (seq->op == &format1_seq_ops)
    444		ri->format = 1;
    445	if (seq->op == &format2_seq_ops)
    446		ri->format = 2;
    447	if (seq->op == &format3_seq_ops)
    448		ri->format = 3;
    449	if (seq->op == &format4_seq_ops)
    450		ri->format = 4;
    451
    452	tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
    453
    454	spin_lock(&ls->ls_rsbtbl[bucket].lock);
    455	if (!RB_EMPTY_ROOT(tree)) {
    456		for (node = rb_first(tree); node; node = rb_next(node)) {
    457			r = rb_entry(node, struct dlm_rsb, res_hashnode);
    458			if (!entry--) {
    459				dlm_hold_rsb(r);
    460				ri->rsb = r;
    461				ri->bucket = bucket;
    462				spin_unlock(&ls->ls_rsbtbl[bucket].lock);
    463				return ri;
    464			}
    465		}
    466	}
    467	spin_unlock(&ls->ls_rsbtbl[bucket].lock);
    468
    469	/*
    470	 * move to the first rsb in the next non-empty bucket
    471	 */
    472
    473	/* zero the entry */
    474	n &= ~((1LL << 32) - 1);
    475
    476	while (1) {
    477		bucket++;
    478		n += 1LL << 32;
    479
    480		if (bucket >= ls->ls_rsbtbl_size) {
    481			kfree(ri);
    482			return NULL;
    483		}
    484		tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
    485
    486		spin_lock(&ls->ls_rsbtbl[bucket].lock);
    487		if (!RB_EMPTY_ROOT(tree)) {
    488			node = rb_first(tree);
    489			r = rb_entry(node, struct dlm_rsb, res_hashnode);
    490			dlm_hold_rsb(r);
    491			ri->rsb = r;
    492			ri->bucket = bucket;
    493			spin_unlock(&ls->ls_rsbtbl[bucket].lock);
    494			*pos = n;
    495			return ri;
    496		}
    497		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
    498	}
    499}
    500
    501static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
    502{
    503	struct dlm_ls *ls = seq->private;
    504	struct rsbtbl_iter *ri = iter_ptr;
    505	struct rb_root *tree;
    506	struct rb_node *next;
    507	struct dlm_rsb *r, *rp;
    508	loff_t n = *pos;
    509	unsigned bucket;
    510	int toss = (seq->op == &format4_seq_ops);
    511
    512	bucket = n >> 32;
    513
    514	/*
    515	 * move to the next rsb in the same bucket
    516	 */
    517
    518	spin_lock(&ls->ls_rsbtbl[bucket].lock);
    519	rp = ri->rsb;
    520	next = rb_next(&rp->res_hashnode);
    521
    522	if (next) {
    523		r = rb_entry(next, struct dlm_rsb, res_hashnode);
    524		dlm_hold_rsb(r);
    525		ri->rsb = r;
    526		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
    527		dlm_put_rsb(rp);
    528		++*pos;
    529		return ri;
    530	}
    531	spin_unlock(&ls->ls_rsbtbl[bucket].lock);
    532	dlm_put_rsb(rp);
    533
    534	/*
    535	 * move to the first rsb in the next non-empty bucket
    536	 */
    537
    538	/* zero the entry */
    539	n &= ~((1LL << 32) - 1);
    540
    541	while (1) {
    542		bucket++;
    543		n += 1LL << 32;
    544
    545		if (bucket >= ls->ls_rsbtbl_size) {
    546			kfree(ri);
    547			++*pos;
    548			return NULL;
    549		}
    550		tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
    551
    552		spin_lock(&ls->ls_rsbtbl[bucket].lock);
    553		if (!RB_EMPTY_ROOT(tree)) {
    554			next = rb_first(tree);
    555			r = rb_entry(next, struct dlm_rsb, res_hashnode);
    556			dlm_hold_rsb(r);
    557			ri->rsb = r;
    558			ri->bucket = bucket;
    559			spin_unlock(&ls->ls_rsbtbl[bucket].lock);
    560			*pos = n;
    561			return ri;
    562		}
    563		spin_unlock(&ls->ls_rsbtbl[bucket].lock);
    564	}
    565}
    566
    567static void table_seq_stop(struct seq_file *seq, void *iter_ptr)
    568{
    569	struct rsbtbl_iter *ri = iter_ptr;
    570
    571	if (ri) {
    572		dlm_put_rsb(ri->rsb);
    573		kfree(ri);
    574	}
    575}
    576
    577static const struct seq_operations format1_seq_ops = {
    578	.start = table_seq_start,
    579	.next  = table_seq_next,
    580	.stop  = table_seq_stop,
    581	.show  = table_seq_show,
    582};
    583
    584static const struct seq_operations format2_seq_ops = {
    585	.start = table_seq_start,
    586	.next  = table_seq_next,
    587	.stop  = table_seq_stop,
    588	.show  = table_seq_show,
    589};
    590
    591static const struct seq_operations format3_seq_ops = {
    592	.start = table_seq_start,
    593	.next  = table_seq_next,
    594	.stop  = table_seq_stop,
    595	.show  = table_seq_show,
    596};
    597
    598static const struct seq_operations format4_seq_ops = {
    599	.start = table_seq_start,
    600	.next  = table_seq_next,
    601	.stop  = table_seq_stop,
    602	.show  = table_seq_show,
    603};
    604
    605static const struct file_operations format1_fops;
    606static const struct file_operations format2_fops;
    607static const struct file_operations format3_fops;
    608static const struct file_operations format4_fops;
    609
    610static int table_open1(struct inode *inode, struct file *file)
    611{
    612	struct seq_file *seq;
    613	int ret;
    614
    615	ret = seq_open(file, &format1_seq_ops);
    616	if (ret)
    617		return ret;
    618
    619	seq = file->private_data;
    620	seq->private = inode->i_private; /* the dlm_ls */
    621	return 0;
    622}
    623
    624static int table_open2(struct inode *inode, struct file *file)
    625{
    626	struct seq_file *seq;
    627	int ret;
    628
    629	ret = seq_open(file, &format2_seq_ops);
    630	if (ret)
    631		return ret;
    632
    633	seq = file->private_data;
    634	seq->private = inode->i_private; /* the dlm_ls */
    635	return 0;
    636}
    637
    638static ssize_t table_write2(struct file *file, const char __user *user_buf,
    639			    size_t count, loff_t *ppos)
    640{
    641	struct seq_file *seq = file->private_data;
    642	int n, len, lkb_nodeid, lkb_status, error;
    643	char name[DLM_RESNAME_MAXLEN + 1] = {};
    644	struct dlm_ls *ls = seq->private;
    645	unsigned int lkb_flags;
    646	char buf[256] = {};
    647	uint32_t lkb_id;
    648
    649	if (copy_from_user(buf, user_buf,
    650			   min_t(size_t, sizeof(buf) - 1, count)))
    651		return -EFAULT;
    652
    653	n = sscanf(buf, "%x %" __stringify(DLM_RESNAME_MAXLEN) "s %x %d %d",
    654		   &lkb_id, name, &lkb_flags, &lkb_nodeid, &lkb_status);
    655	if (n != 5)
    656		return -EINVAL;
    657
    658	len = strnlen(name, DLM_RESNAME_MAXLEN);
    659	error = dlm_debug_add_lkb(ls, lkb_id, name, len, lkb_flags,
    660				  lkb_nodeid, lkb_status);
    661	if (error)
    662		return error;
    663
    664	return count;
    665}
    666
    667static int table_open3(struct inode *inode, struct file *file)
    668{
    669	struct seq_file *seq;
    670	int ret;
    671
    672	ret = seq_open(file, &format3_seq_ops);
    673	if (ret)
    674		return ret;
    675
    676	seq = file->private_data;
    677	seq->private = inode->i_private; /* the dlm_ls */
    678	return 0;
    679}
    680
    681static int table_open4(struct inode *inode, struct file *file)
    682{
    683	struct seq_file *seq;
    684	int ret;
    685
    686	ret = seq_open(file, &format4_seq_ops);
    687	if (ret)
    688		return ret;
    689
    690	seq = file->private_data;
    691	seq->private = inode->i_private; /* the dlm_ls */
    692	return 0;
    693}
    694
    695static const struct file_operations format1_fops = {
    696	.owner   = THIS_MODULE,
    697	.open    = table_open1,
    698	.read    = seq_read,
    699	.llseek  = seq_lseek,
    700	.release = seq_release
    701};
    702
    703static const struct file_operations format2_fops = {
    704	.owner   = THIS_MODULE,
    705	.open    = table_open2,
    706	.read    = seq_read,
    707	.write   = table_write2,
    708	.llseek  = seq_lseek,
    709	.release = seq_release
    710};
    711
    712static const struct file_operations format3_fops = {
    713	.owner   = THIS_MODULE,
    714	.open    = table_open3,
    715	.read    = seq_read,
    716	.llseek  = seq_lseek,
    717	.release = seq_release
    718};
    719
    720static const struct file_operations format4_fops = {
    721	.owner   = THIS_MODULE,
    722	.open    = table_open4,
    723	.read    = seq_read,
    724	.llseek  = seq_lseek,
    725	.release = seq_release
    726};
    727
    728/*
    729 * dump lkb's on the ls_waiters list
    730 */
    731static ssize_t waiters_read(struct file *file, char __user *userbuf,
    732			    size_t count, loff_t *ppos)
    733{
    734	struct dlm_ls *ls = file->private_data;
    735	struct dlm_lkb *lkb;
    736	size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv;
    737
    738	mutex_lock(&debug_buf_lock);
    739	mutex_lock(&ls->ls_waiters_mutex);
    740	memset(debug_buf, 0, sizeof(debug_buf));
    741
    742	list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) {
    743		ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n",
    744			       lkb->lkb_id, lkb->lkb_wait_type,
    745			       lkb->lkb_nodeid, lkb->lkb_resource->res_name);
    746		if (ret >= len - pos)
    747			break;
    748		pos += ret;
    749	}
    750	mutex_unlock(&ls->ls_waiters_mutex);
    751
    752	rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos);
    753	mutex_unlock(&debug_buf_lock);
    754	return rv;
    755}
    756
    757static ssize_t waiters_write(struct file *file, const char __user *user_buf,
    758			     size_t count, loff_t *ppos)
    759{
    760	struct dlm_ls *ls = file->private_data;
    761	int mstype, to_nodeid;
    762	char buf[128] = {};
    763	uint32_t lkb_id;
    764	int n, error;
    765
    766	if (copy_from_user(buf, user_buf,
    767			   min_t(size_t, sizeof(buf) - 1, count)))
    768		return -EFAULT;
    769
    770	n = sscanf(buf, "%x %d %d", &lkb_id, &mstype, &to_nodeid);
    771	if (n != 3)
    772		return -EINVAL;
    773
    774	error = dlm_debug_add_lkb_to_waiters(ls, lkb_id, mstype, to_nodeid);
    775	if (error)
    776		return error;
    777
    778	return count;
    779}
    780
    781static const struct file_operations waiters_fops = {
    782	.owner   = THIS_MODULE,
    783	.open    = simple_open,
    784	.read    = waiters_read,
    785	.write   = waiters_write,
    786	.llseek  = default_llseek,
    787};
    788
    789void dlm_delete_debug_file(struct dlm_ls *ls)
    790{
    791	debugfs_remove(ls->ls_debug_rsb_dentry);
    792	debugfs_remove(ls->ls_debug_waiters_dentry);
    793	debugfs_remove(ls->ls_debug_locks_dentry);
    794	debugfs_remove(ls->ls_debug_all_dentry);
    795	debugfs_remove(ls->ls_debug_toss_dentry);
    796}
    797
    798static int dlm_state_show(struct seq_file *file, void *offset)
    799{
    800	seq_printf(file, "%s\n", dlm_midcomms_state(file->private));
    801	return 0;
    802}
    803DEFINE_SHOW_ATTRIBUTE(dlm_state);
    804
    805static int dlm_flags_show(struct seq_file *file, void *offset)
    806{
    807	seq_printf(file, "%lu\n", dlm_midcomms_flags(file->private));
    808	return 0;
    809}
    810DEFINE_SHOW_ATTRIBUTE(dlm_flags);
    811
    812static int dlm_send_queue_cnt_show(struct seq_file *file, void *offset)
    813{
    814	seq_printf(file, "%d\n", dlm_midcomms_send_queue_cnt(file->private));
    815	return 0;
    816}
    817DEFINE_SHOW_ATTRIBUTE(dlm_send_queue_cnt);
    818
    819static int dlm_version_show(struct seq_file *file, void *offset)
    820{
    821	seq_printf(file, "0x%08x\n", dlm_midcomms_version(file->private));
    822	return 0;
    823}
    824DEFINE_SHOW_ATTRIBUTE(dlm_version);
    825
    826static ssize_t dlm_rawmsg_write(struct file *fp, const char __user *user_buf,
    827				size_t count, loff_t *ppos)
    828{
    829	void *buf;
    830	int ret;
    831
    832	if (count > PAGE_SIZE || count < sizeof(struct dlm_header))
    833		return -EINVAL;
    834
    835	buf = kmalloc(PAGE_SIZE, GFP_NOFS);
    836	if (!buf)
    837		return -ENOMEM;
    838
    839	if (copy_from_user(buf, user_buf, count)) {
    840		ret = -EFAULT;
    841		goto out;
    842	}
    843
    844	ret = dlm_midcomms_rawmsg_send(fp->private_data, buf, count);
    845	if (ret)
    846		goto out;
    847
    848	kfree(buf);
    849	return count;
    850
    851out:
    852	kfree(buf);
    853	return ret;
    854}
    855
    856static const struct file_operations dlm_rawmsg_fops = {
    857	.open	= simple_open,
    858	.write	= dlm_rawmsg_write,
    859	.llseek	= no_llseek,
    860};
    861
    862void *dlm_create_debug_comms_file(int nodeid, void *data)
    863{
    864	struct dentry *d_node;
    865	char name[256];
    866
    867	memset(name, 0, sizeof(name));
    868	snprintf(name, 256, "%d", nodeid);
    869
    870	d_node = debugfs_create_dir(name, dlm_comms);
    871	debugfs_create_file("state", 0444, d_node, data, &dlm_state_fops);
    872	debugfs_create_file("flags", 0444, d_node, data, &dlm_flags_fops);
    873	debugfs_create_file("send_queue_count", 0444, d_node, data,
    874			    &dlm_send_queue_cnt_fops);
    875	debugfs_create_file("version", 0444, d_node, data, &dlm_version_fops);
    876	debugfs_create_file("rawmsg", 0200, d_node, data, &dlm_rawmsg_fops);
    877
    878	return d_node;
    879}
    880
    881void dlm_delete_debug_comms_file(void *ctx)
    882{
    883	debugfs_remove(ctx);
    884}
    885
    886void dlm_create_debug_file(struct dlm_ls *ls)
    887{
    888	char name[DLM_LOCKSPACE_LEN + 8];
    889
    890	/* format 1 */
    891
    892	ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name,
    893						      S_IFREG | S_IRUGO,
    894						      dlm_root,
    895						      ls,
    896						      &format1_fops);
    897
    898	/* format 2 */
    899
    900	memset(name, 0, sizeof(name));
    901	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_locks", ls->ls_name);
    902
    903	ls->ls_debug_locks_dentry = debugfs_create_file(name,
    904							0644,
    905							dlm_root,
    906							ls,
    907							&format2_fops);
    908
    909	/* format 3 */
    910
    911	memset(name, 0, sizeof(name));
    912	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_all", ls->ls_name);
    913
    914	ls->ls_debug_all_dentry = debugfs_create_file(name,
    915						      S_IFREG | S_IRUGO,
    916						      dlm_root,
    917						      ls,
    918						      &format3_fops);
    919
    920	/* format 4 */
    921
    922	memset(name, 0, sizeof(name));
    923	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_toss", ls->ls_name);
    924
    925	ls->ls_debug_toss_dentry = debugfs_create_file(name,
    926						       S_IFREG | S_IRUGO,
    927						       dlm_root,
    928						       ls,
    929						       &format4_fops);
    930
    931	memset(name, 0, sizeof(name));
    932	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_waiters", ls->ls_name);
    933
    934	ls->ls_debug_waiters_dentry = debugfs_create_file(name,
    935							  0644,
    936							  dlm_root,
    937							  ls,
    938							  &waiters_fops);
    939}
    940
    941void __init dlm_register_debugfs(void)
    942{
    943	mutex_init(&debug_buf_lock);
    944	dlm_root = debugfs_create_dir("dlm", NULL);
    945	dlm_comms = debugfs_create_dir("comms", dlm_root);
    946}
    947
    948void dlm_unregister_debugfs(void)
    949{
    950	debugfs_remove(dlm_root);
    951}
    952