162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci******************************************************************************* 462306a36Sopenharmony_ci** 562306a36Sopenharmony_ci** Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved. 662306a36Sopenharmony_ci** 762306a36Sopenharmony_ci** 862306a36Sopenharmony_ci******************************************************************************* 962306a36Sopenharmony_ci******************************************************************************/ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/pagemap.h> 1262306a36Sopenharmony_ci#include <linux/seq_file.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/ctype.h> 1562306a36Sopenharmony_ci#include <linux/debugfs.h> 1662306a36Sopenharmony_ci#include <linux/slab.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "dlm_internal.h" 1962306a36Sopenharmony_ci#include "midcomms.h" 2062306a36Sopenharmony_ci#include "lock.h" 2162306a36Sopenharmony_ci#include "ast.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define DLM_DEBUG_BUF_LEN 4096 2462306a36Sopenharmony_cistatic char debug_buf[DLM_DEBUG_BUF_LEN]; 2562306a36Sopenharmony_cistatic struct mutex debug_buf_lock; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic struct dentry *dlm_root; 2862306a36Sopenharmony_cistatic struct dentry *dlm_comms; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic char *print_lockmode(int mode) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci switch (mode) { 3362306a36Sopenharmony_ci case DLM_LOCK_IV: 3462306a36Sopenharmony_ci return "--"; 3562306a36Sopenharmony_ci case DLM_LOCK_NL: 3662306a36Sopenharmony_ci return "NL"; 3762306a36Sopenharmony_ci case DLM_LOCK_CR: 3862306a36Sopenharmony_ci return "CR"; 3962306a36Sopenharmony_ci case DLM_LOCK_CW: 4062306a36Sopenharmony_ci return "CW"; 4162306a36Sopenharmony_ci case DLM_LOCK_PR: 4262306a36Sopenharmony_ci return "PR"; 4362306a36Sopenharmony_ci case DLM_LOCK_PW: 4462306a36Sopenharmony_ci return "PW"; 4562306a36Sopenharmony_ci case DLM_LOCK_EX: 4662306a36Sopenharmony_ci return "EX"; 4762306a36Sopenharmony_ci default: 4862306a36Sopenharmony_ci return "??"; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic void print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb, 5362306a36Sopenharmony_ci struct dlm_rsb *res) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode)); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (lkb->lkb_status == DLM_LKSTS_CONVERT || 5862306a36Sopenharmony_ci lkb->lkb_status == DLM_LKSTS_WAITING) 5962306a36Sopenharmony_ci seq_printf(s, " (%s)", print_lockmode(lkb->lkb_rqmode)); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if (lkb->lkb_nodeid) { 6262306a36Sopenharmony_ci if (lkb->lkb_nodeid != res->res_nodeid) 6362306a36Sopenharmony_ci seq_printf(s, " Remote: %3d %08x", lkb->lkb_nodeid, 6462306a36Sopenharmony_ci lkb->lkb_remid); 6562306a36Sopenharmony_ci else 6662306a36Sopenharmony_ci seq_printf(s, " Master: %08x", lkb->lkb_remid); 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (lkb->lkb_wait_type) 7062306a36Sopenharmony_ci seq_printf(s, " wait_type: %d", lkb->lkb_wait_type); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci seq_putc(s, '\n'); 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic void print_format1(struct dlm_rsb *res, struct seq_file *s) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct dlm_lkb *lkb; 7862306a36Sopenharmony_ci int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci lock_rsb(res); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci for (i = 0; i < res->res_length; i++) { 8562306a36Sopenharmony_ci if (isprint(res->res_name[i])) 8662306a36Sopenharmony_ci seq_printf(s, "%c", res->res_name[i]); 8762306a36Sopenharmony_ci else 8862306a36Sopenharmony_ci seq_printf(s, "%c", '.'); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (res->res_nodeid > 0) 9262306a36Sopenharmony_ci seq_printf(s, "\"\nLocal Copy, Master is node %d\n", 9362306a36Sopenharmony_ci res->res_nodeid); 9462306a36Sopenharmony_ci else if (res->res_nodeid == 0) 9562306a36Sopenharmony_ci seq_puts(s, "\"\nMaster Copy\n"); 9662306a36Sopenharmony_ci else if (res->res_nodeid == -1) 9762306a36Sopenharmony_ci seq_printf(s, "\"\nLooking up master (lkid %x)\n", 9862306a36Sopenharmony_ci res->res_first_lkid); 9962306a36Sopenharmony_ci else 10062306a36Sopenharmony_ci seq_printf(s, "\"\nInvalid master %d\n", res->res_nodeid); 10162306a36Sopenharmony_ci if (seq_has_overflowed(s)) 10262306a36Sopenharmony_ci goto out; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Print the LVB: */ 10562306a36Sopenharmony_ci if (res->res_lvbptr) { 10662306a36Sopenharmony_ci seq_puts(s, "LVB: "); 10762306a36Sopenharmony_ci for (i = 0; i < lvblen; i++) { 10862306a36Sopenharmony_ci if (i == lvblen / 2) 10962306a36Sopenharmony_ci seq_puts(s, "\n "); 11062306a36Sopenharmony_ci seq_printf(s, "%02x ", 11162306a36Sopenharmony_ci (unsigned char) res->res_lvbptr[i]); 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci if (rsb_flag(res, RSB_VALNOTVALID)) 11462306a36Sopenharmony_ci seq_puts(s, " (INVALID)"); 11562306a36Sopenharmony_ci seq_putc(s, '\n'); 11662306a36Sopenharmony_ci if (seq_has_overflowed(s)) 11762306a36Sopenharmony_ci goto out; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci root_list = !list_empty(&res->res_root_list); 12162306a36Sopenharmony_ci recover_list = !list_empty(&res->res_recover_list); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci if (root_list || recover_list) { 12462306a36Sopenharmony_ci seq_printf(s, "Recovery: root %d recover %d flags %lx count %d\n", 12562306a36Sopenharmony_ci root_list, recover_list, 12662306a36Sopenharmony_ci res->res_flags, res->res_recover_locks_count); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* Print the locks attached to this resource */ 13062306a36Sopenharmony_ci seq_puts(s, "Granted Queue\n"); 13162306a36Sopenharmony_ci list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) { 13262306a36Sopenharmony_ci print_format1_lock(s, lkb, res); 13362306a36Sopenharmony_ci if (seq_has_overflowed(s)) 13462306a36Sopenharmony_ci goto out; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci seq_puts(s, "Conversion Queue\n"); 13862306a36Sopenharmony_ci list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) { 13962306a36Sopenharmony_ci print_format1_lock(s, lkb, res); 14062306a36Sopenharmony_ci if (seq_has_overflowed(s)) 14162306a36Sopenharmony_ci goto out; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci seq_puts(s, "Waiting Queue\n"); 14562306a36Sopenharmony_ci list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) { 14662306a36Sopenharmony_ci print_format1_lock(s, lkb, res); 14762306a36Sopenharmony_ci if (seq_has_overflowed(s)) 14862306a36Sopenharmony_ci goto out; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (list_empty(&res->res_lookup)) 15262306a36Sopenharmony_ci goto out; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci seq_puts(s, "Lookup Queue\n"); 15562306a36Sopenharmony_ci list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) { 15662306a36Sopenharmony_ci seq_printf(s, "%08x %s", 15762306a36Sopenharmony_ci lkb->lkb_id, print_lockmode(lkb->lkb_rqmode)); 15862306a36Sopenharmony_ci if (lkb->lkb_wait_type) 15962306a36Sopenharmony_ci seq_printf(s, " wait_type: %d", lkb->lkb_wait_type); 16062306a36Sopenharmony_ci seq_putc(s, '\n'); 16162306a36Sopenharmony_ci if (seq_has_overflowed(s)) 16262306a36Sopenharmony_ci goto out; 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci out: 16562306a36Sopenharmony_ci unlock_rsb(res); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic void print_format2_lock(struct seq_file *s, struct dlm_lkb *lkb, 16962306a36Sopenharmony_ci struct dlm_rsb *r) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci u64 xid = 0; 17262306a36Sopenharmony_ci u64 us; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) { 17562306a36Sopenharmony_ci if (lkb->lkb_ua) 17662306a36Sopenharmony_ci xid = lkb->lkb_ua->xid; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* microseconds since lkb was added to current queue */ 18062306a36Sopenharmony_ci us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_timestamp)); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* id nodeid remid pid xid exflags flags sts grmode rqmode time_us 18362306a36Sopenharmony_ci r_nodeid r_len r_name */ 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %llu %u %d \"%s\"\n", 18662306a36Sopenharmony_ci lkb->lkb_id, 18762306a36Sopenharmony_ci lkb->lkb_nodeid, 18862306a36Sopenharmony_ci lkb->lkb_remid, 18962306a36Sopenharmony_ci lkb->lkb_ownpid, 19062306a36Sopenharmony_ci (unsigned long long)xid, 19162306a36Sopenharmony_ci lkb->lkb_exflags, 19262306a36Sopenharmony_ci dlm_iflags_val(lkb), 19362306a36Sopenharmony_ci lkb->lkb_status, 19462306a36Sopenharmony_ci lkb->lkb_grmode, 19562306a36Sopenharmony_ci lkb->lkb_rqmode, 19662306a36Sopenharmony_ci (unsigned long long)us, 19762306a36Sopenharmony_ci r->res_nodeid, 19862306a36Sopenharmony_ci r->res_length, 19962306a36Sopenharmony_ci r->res_name); 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic void print_format2(struct dlm_rsb *r, struct seq_file *s) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci struct dlm_lkb *lkb; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci lock_rsb(r); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) { 20962306a36Sopenharmony_ci print_format2_lock(s, lkb, r); 21062306a36Sopenharmony_ci if (seq_has_overflowed(s)) 21162306a36Sopenharmony_ci goto out; 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) { 21562306a36Sopenharmony_ci print_format2_lock(s, lkb, r); 21662306a36Sopenharmony_ci if (seq_has_overflowed(s)) 21762306a36Sopenharmony_ci goto out; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) { 22162306a36Sopenharmony_ci print_format2_lock(s, lkb, r); 22262306a36Sopenharmony_ci if (seq_has_overflowed(s)) 22362306a36Sopenharmony_ci goto out; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci out: 22662306a36Sopenharmony_ci unlock_rsb(r); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic void print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb, 23062306a36Sopenharmony_ci int rsb_lookup) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci u64 xid = 0; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) { 23562306a36Sopenharmony_ci if (lkb->lkb_ua) 23662306a36Sopenharmony_ci xid = lkb->lkb_ua->xid; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci seq_printf(s, "lkb %x %d %x %u %llu %x %x %d %d %d %d %d %d %u %llu %llu\n", 24062306a36Sopenharmony_ci lkb->lkb_id, 24162306a36Sopenharmony_ci lkb->lkb_nodeid, 24262306a36Sopenharmony_ci lkb->lkb_remid, 24362306a36Sopenharmony_ci lkb->lkb_ownpid, 24462306a36Sopenharmony_ci (unsigned long long)xid, 24562306a36Sopenharmony_ci lkb->lkb_exflags, 24662306a36Sopenharmony_ci dlm_iflags_val(lkb), 24762306a36Sopenharmony_ci lkb->lkb_status, 24862306a36Sopenharmony_ci lkb->lkb_grmode, 24962306a36Sopenharmony_ci lkb->lkb_rqmode, 25062306a36Sopenharmony_ci lkb->lkb_last_bast_mode, 25162306a36Sopenharmony_ci rsb_lookup, 25262306a36Sopenharmony_ci lkb->lkb_wait_type, 25362306a36Sopenharmony_ci lkb->lkb_lvbseq, 25462306a36Sopenharmony_ci (unsigned long long)ktime_to_ns(lkb->lkb_timestamp), 25562306a36Sopenharmony_ci (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time)); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic void print_format3(struct dlm_rsb *r, struct seq_file *s) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci struct dlm_lkb *lkb; 26162306a36Sopenharmony_ci int i, lvblen = r->res_ls->ls_lvblen; 26262306a36Sopenharmony_ci int print_name = 1; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci lock_rsb(r); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci seq_printf(s, "rsb %p %d %x %lx %d %d %u %d ", 26762306a36Sopenharmony_ci r, 26862306a36Sopenharmony_ci r->res_nodeid, 26962306a36Sopenharmony_ci r->res_first_lkid, 27062306a36Sopenharmony_ci r->res_flags, 27162306a36Sopenharmony_ci !list_empty(&r->res_root_list), 27262306a36Sopenharmony_ci !list_empty(&r->res_recover_list), 27362306a36Sopenharmony_ci r->res_recover_locks_count, 27462306a36Sopenharmony_ci r->res_length); 27562306a36Sopenharmony_ci if (seq_has_overflowed(s)) 27662306a36Sopenharmony_ci goto out; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci for (i = 0; i < r->res_length; i++) { 27962306a36Sopenharmony_ci if (!isascii(r->res_name[i]) || !isprint(r->res_name[i])) 28062306a36Sopenharmony_ci print_name = 0; 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci seq_puts(s, print_name ? "str " : "hex"); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci for (i = 0; i < r->res_length; i++) { 28662306a36Sopenharmony_ci if (print_name) 28762306a36Sopenharmony_ci seq_printf(s, "%c", r->res_name[i]); 28862306a36Sopenharmony_ci else 28962306a36Sopenharmony_ci seq_printf(s, " %02x", (unsigned char)r->res_name[i]); 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci seq_putc(s, '\n'); 29262306a36Sopenharmony_ci if (seq_has_overflowed(s)) 29362306a36Sopenharmony_ci goto out; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (!r->res_lvbptr) 29662306a36Sopenharmony_ci goto do_locks; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci seq_printf(s, "lvb %u %d", r->res_lvbseq, lvblen); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci for (i = 0; i < lvblen; i++) 30162306a36Sopenharmony_ci seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]); 30262306a36Sopenharmony_ci seq_putc(s, '\n'); 30362306a36Sopenharmony_ci if (seq_has_overflowed(s)) 30462306a36Sopenharmony_ci goto out; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci do_locks: 30762306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) { 30862306a36Sopenharmony_ci print_format3_lock(s, lkb, 0); 30962306a36Sopenharmony_ci if (seq_has_overflowed(s)) 31062306a36Sopenharmony_ci goto out; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) { 31462306a36Sopenharmony_ci print_format3_lock(s, lkb, 0); 31562306a36Sopenharmony_ci if (seq_has_overflowed(s)) 31662306a36Sopenharmony_ci goto out; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) { 32062306a36Sopenharmony_ci print_format3_lock(s, lkb, 0); 32162306a36Sopenharmony_ci if (seq_has_overflowed(s)) 32262306a36Sopenharmony_ci goto out; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) { 32662306a36Sopenharmony_ci print_format3_lock(s, lkb, 1); 32762306a36Sopenharmony_ci if (seq_has_overflowed(s)) 32862306a36Sopenharmony_ci goto out; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci out: 33162306a36Sopenharmony_ci unlock_rsb(r); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic void print_format4(struct dlm_rsb *r, struct seq_file *s) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci int our_nodeid = dlm_our_nodeid(); 33762306a36Sopenharmony_ci int print_name = 1; 33862306a36Sopenharmony_ci int i; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci lock_rsb(r); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci seq_printf(s, "rsb %p %d %d %d %d %lu %lx %d ", 34362306a36Sopenharmony_ci r, 34462306a36Sopenharmony_ci r->res_nodeid, 34562306a36Sopenharmony_ci r->res_master_nodeid, 34662306a36Sopenharmony_ci r->res_dir_nodeid, 34762306a36Sopenharmony_ci our_nodeid, 34862306a36Sopenharmony_ci r->res_toss_time, 34962306a36Sopenharmony_ci r->res_flags, 35062306a36Sopenharmony_ci r->res_length); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci for (i = 0; i < r->res_length; i++) { 35362306a36Sopenharmony_ci if (!isascii(r->res_name[i]) || !isprint(r->res_name[i])) 35462306a36Sopenharmony_ci print_name = 0; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci seq_puts(s, print_name ? "str " : "hex"); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci for (i = 0; i < r->res_length; i++) { 36062306a36Sopenharmony_ci if (print_name) 36162306a36Sopenharmony_ci seq_printf(s, "%c", r->res_name[i]); 36262306a36Sopenharmony_ci else 36362306a36Sopenharmony_ci seq_printf(s, " %02x", (unsigned char)r->res_name[i]); 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci seq_putc(s, '\n'); 36662306a36Sopenharmony_ci unlock_rsb(r); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic void print_format5_lock(struct seq_file *s, struct dlm_lkb *lkb) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci struct dlm_callback *cb; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* lkb_id lkb_flags mode flags sb_status sb_flags */ 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci spin_lock(&lkb->lkb_cb_lock); 37662306a36Sopenharmony_ci list_for_each_entry(cb, &lkb->lkb_callbacks, list) { 37762306a36Sopenharmony_ci seq_printf(s, "%x %x %d %x %d %x\n", 37862306a36Sopenharmony_ci lkb->lkb_id, 37962306a36Sopenharmony_ci dlm_iflags_val(lkb), 38062306a36Sopenharmony_ci cb->mode, 38162306a36Sopenharmony_ci cb->flags, 38262306a36Sopenharmony_ci cb->sb_status, 38362306a36Sopenharmony_ci cb->sb_flags); 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci spin_unlock(&lkb->lkb_cb_lock); 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic void print_format5(struct dlm_rsb *r, struct seq_file *s) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci struct dlm_lkb *lkb; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci lock_rsb(r); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) { 39562306a36Sopenharmony_ci print_format5_lock(s, lkb); 39662306a36Sopenharmony_ci if (seq_has_overflowed(s)) 39762306a36Sopenharmony_ci goto out; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) { 40162306a36Sopenharmony_ci print_format5_lock(s, lkb); 40262306a36Sopenharmony_ci if (seq_has_overflowed(s)) 40362306a36Sopenharmony_ci goto out; 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) { 40762306a36Sopenharmony_ci print_format5_lock(s, lkb); 40862306a36Sopenharmony_ci if (seq_has_overflowed(s)) 40962306a36Sopenharmony_ci goto out; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci out: 41262306a36Sopenharmony_ci unlock_rsb(r); 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistruct rsbtbl_iter { 41662306a36Sopenharmony_ci struct dlm_rsb *rsb; 41762306a36Sopenharmony_ci unsigned bucket; 41862306a36Sopenharmony_ci int format; 41962306a36Sopenharmony_ci int header; 42062306a36Sopenharmony_ci}; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci/* 42362306a36Sopenharmony_ci * If the buffer is full, seq_printf can be called again, but it 42462306a36Sopenharmony_ci * does nothing. So, the these printing routines periodically check 42562306a36Sopenharmony_ci * seq_has_overflowed to avoid wasting too much time trying to print to 42662306a36Sopenharmony_ci * a full buffer. 42762306a36Sopenharmony_ci */ 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cistatic int table_seq_show(struct seq_file *seq, void *iter_ptr) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci struct rsbtbl_iter *ri = iter_ptr; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci switch (ri->format) { 43462306a36Sopenharmony_ci case 1: 43562306a36Sopenharmony_ci print_format1(ri->rsb, seq); 43662306a36Sopenharmony_ci break; 43762306a36Sopenharmony_ci case 2: 43862306a36Sopenharmony_ci if (ri->header) { 43962306a36Sopenharmony_ci seq_puts(seq, "id nodeid remid pid xid exflags flags sts grmode rqmode time_ms r_nodeid r_len r_name\n"); 44062306a36Sopenharmony_ci ri->header = 0; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci print_format2(ri->rsb, seq); 44362306a36Sopenharmony_ci break; 44462306a36Sopenharmony_ci case 3: 44562306a36Sopenharmony_ci if (ri->header) { 44662306a36Sopenharmony_ci seq_puts(seq, "version rsb 1.1 lvb 1.1 lkb 1.1\n"); 44762306a36Sopenharmony_ci ri->header = 0; 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci print_format3(ri->rsb, seq); 45062306a36Sopenharmony_ci break; 45162306a36Sopenharmony_ci case 4: 45262306a36Sopenharmony_ci if (ri->header) { 45362306a36Sopenharmony_ci seq_puts(seq, "version 4 rsb 2\n"); 45462306a36Sopenharmony_ci ri->header = 0; 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci print_format4(ri->rsb, seq); 45762306a36Sopenharmony_ci break; 45862306a36Sopenharmony_ci case 5: 45962306a36Sopenharmony_ci if (ri->header) { 46062306a36Sopenharmony_ci seq_puts(seq, "lkb_id lkb_flags mode flags sb_status sb_flags\n"); 46162306a36Sopenharmony_ci ri->header = 0; 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci print_format5(ri->rsb, seq); 46462306a36Sopenharmony_ci break; 46562306a36Sopenharmony_ci } 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci return 0; 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic const struct seq_operations format1_seq_ops; 47162306a36Sopenharmony_cistatic const struct seq_operations format2_seq_ops; 47262306a36Sopenharmony_cistatic const struct seq_operations format3_seq_ops; 47362306a36Sopenharmony_cistatic const struct seq_operations format4_seq_ops; 47462306a36Sopenharmony_cistatic const struct seq_operations format5_seq_ops; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_cistatic void *table_seq_start(struct seq_file *seq, loff_t *pos) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct rb_root *tree; 47962306a36Sopenharmony_ci struct rb_node *node; 48062306a36Sopenharmony_ci struct dlm_ls *ls = seq->private; 48162306a36Sopenharmony_ci struct rsbtbl_iter *ri; 48262306a36Sopenharmony_ci struct dlm_rsb *r; 48362306a36Sopenharmony_ci loff_t n = *pos; 48462306a36Sopenharmony_ci unsigned bucket, entry; 48562306a36Sopenharmony_ci int toss = (seq->op == &format4_seq_ops); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci bucket = n >> 32; 48862306a36Sopenharmony_ci entry = n & ((1LL << 32) - 1); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (bucket >= ls->ls_rsbtbl_size) 49162306a36Sopenharmony_ci return NULL; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci ri = kzalloc(sizeof(*ri), GFP_NOFS); 49462306a36Sopenharmony_ci if (!ri) 49562306a36Sopenharmony_ci return NULL; 49662306a36Sopenharmony_ci if (n == 0) 49762306a36Sopenharmony_ci ri->header = 1; 49862306a36Sopenharmony_ci if (seq->op == &format1_seq_ops) 49962306a36Sopenharmony_ci ri->format = 1; 50062306a36Sopenharmony_ci if (seq->op == &format2_seq_ops) 50162306a36Sopenharmony_ci ri->format = 2; 50262306a36Sopenharmony_ci if (seq->op == &format3_seq_ops) 50362306a36Sopenharmony_ci ri->format = 3; 50462306a36Sopenharmony_ci if (seq->op == &format4_seq_ops) 50562306a36Sopenharmony_ci ri->format = 4; 50662306a36Sopenharmony_ci if (seq->op == &format5_seq_ops) 50762306a36Sopenharmony_ci ri->format = 5; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[bucket].lock); 51262306a36Sopenharmony_ci if (!RB_EMPTY_ROOT(tree)) { 51362306a36Sopenharmony_ci for (node = rb_first(tree); node; node = rb_next(node)) { 51462306a36Sopenharmony_ci r = rb_entry(node, struct dlm_rsb, res_hashnode); 51562306a36Sopenharmony_ci if (!entry--) { 51662306a36Sopenharmony_ci dlm_hold_rsb(r); 51762306a36Sopenharmony_ci ri->rsb = r; 51862306a36Sopenharmony_ci ri->bucket = bucket; 51962306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 52062306a36Sopenharmony_ci return ri; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* 52762306a36Sopenharmony_ci * move to the first rsb in the next non-empty bucket 52862306a36Sopenharmony_ci */ 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci /* zero the entry */ 53162306a36Sopenharmony_ci n &= ~((1LL << 32) - 1); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci while (1) { 53462306a36Sopenharmony_ci bucket++; 53562306a36Sopenharmony_ci n += 1LL << 32; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci if (bucket >= ls->ls_rsbtbl_size) { 53862306a36Sopenharmony_ci kfree(ri); 53962306a36Sopenharmony_ci return NULL; 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[bucket].lock); 54462306a36Sopenharmony_ci if (!RB_EMPTY_ROOT(tree)) { 54562306a36Sopenharmony_ci node = rb_first(tree); 54662306a36Sopenharmony_ci r = rb_entry(node, struct dlm_rsb, res_hashnode); 54762306a36Sopenharmony_ci dlm_hold_rsb(r); 54862306a36Sopenharmony_ci ri->rsb = r; 54962306a36Sopenharmony_ci ri->bucket = bucket; 55062306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 55162306a36Sopenharmony_ci *pos = n; 55262306a36Sopenharmony_ci return ri; 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci struct dlm_ls *ls = seq->private; 56162306a36Sopenharmony_ci struct rsbtbl_iter *ri = iter_ptr; 56262306a36Sopenharmony_ci struct rb_root *tree; 56362306a36Sopenharmony_ci struct rb_node *next; 56462306a36Sopenharmony_ci struct dlm_rsb *r, *rp; 56562306a36Sopenharmony_ci loff_t n = *pos; 56662306a36Sopenharmony_ci unsigned bucket; 56762306a36Sopenharmony_ci int toss = (seq->op == &format4_seq_ops); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci bucket = n >> 32; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci /* 57262306a36Sopenharmony_ci * move to the next rsb in the same bucket 57362306a36Sopenharmony_ci */ 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[bucket].lock); 57662306a36Sopenharmony_ci rp = ri->rsb; 57762306a36Sopenharmony_ci next = rb_next(&rp->res_hashnode); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (next) { 58062306a36Sopenharmony_ci r = rb_entry(next, struct dlm_rsb, res_hashnode); 58162306a36Sopenharmony_ci dlm_hold_rsb(r); 58262306a36Sopenharmony_ci ri->rsb = r; 58362306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 58462306a36Sopenharmony_ci dlm_put_rsb(rp); 58562306a36Sopenharmony_ci ++*pos; 58662306a36Sopenharmony_ci return ri; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 58962306a36Sopenharmony_ci dlm_put_rsb(rp); 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci /* 59262306a36Sopenharmony_ci * move to the first rsb in the next non-empty bucket 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci /* zero the entry */ 59662306a36Sopenharmony_ci n &= ~((1LL << 32) - 1); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci while (1) { 59962306a36Sopenharmony_ci bucket++; 60062306a36Sopenharmony_ci n += 1LL << 32; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci if (bucket >= ls->ls_rsbtbl_size) { 60362306a36Sopenharmony_ci kfree(ri); 60462306a36Sopenharmony_ci ++*pos; 60562306a36Sopenharmony_ci return NULL; 60662306a36Sopenharmony_ci } 60762306a36Sopenharmony_ci tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[bucket].lock); 61062306a36Sopenharmony_ci if (!RB_EMPTY_ROOT(tree)) { 61162306a36Sopenharmony_ci next = rb_first(tree); 61262306a36Sopenharmony_ci r = rb_entry(next, struct dlm_rsb, res_hashnode); 61362306a36Sopenharmony_ci dlm_hold_rsb(r); 61462306a36Sopenharmony_ci ri->rsb = r; 61562306a36Sopenharmony_ci ri->bucket = bucket; 61662306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 61762306a36Sopenharmony_ci *pos = n; 61862306a36Sopenharmony_ci return ri; 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_cistatic void table_seq_stop(struct seq_file *seq, void *iter_ptr) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci struct rsbtbl_iter *ri = iter_ptr; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci if (ri) { 62962306a36Sopenharmony_ci dlm_put_rsb(ri->rsb); 63062306a36Sopenharmony_ci kfree(ri); 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_cistatic const struct seq_operations format1_seq_ops = { 63562306a36Sopenharmony_ci .start = table_seq_start, 63662306a36Sopenharmony_ci .next = table_seq_next, 63762306a36Sopenharmony_ci .stop = table_seq_stop, 63862306a36Sopenharmony_ci .show = table_seq_show, 63962306a36Sopenharmony_ci}; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic const struct seq_operations format2_seq_ops = { 64262306a36Sopenharmony_ci .start = table_seq_start, 64362306a36Sopenharmony_ci .next = table_seq_next, 64462306a36Sopenharmony_ci .stop = table_seq_stop, 64562306a36Sopenharmony_ci .show = table_seq_show, 64662306a36Sopenharmony_ci}; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_cistatic const struct seq_operations format3_seq_ops = { 64962306a36Sopenharmony_ci .start = table_seq_start, 65062306a36Sopenharmony_ci .next = table_seq_next, 65162306a36Sopenharmony_ci .stop = table_seq_stop, 65262306a36Sopenharmony_ci .show = table_seq_show, 65362306a36Sopenharmony_ci}; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic const struct seq_operations format4_seq_ops = { 65662306a36Sopenharmony_ci .start = table_seq_start, 65762306a36Sopenharmony_ci .next = table_seq_next, 65862306a36Sopenharmony_ci .stop = table_seq_stop, 65962306a36Sopenharmony_ci .show = table_seq_show, 66062306a36Sopenharmony_ci}; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic const struct seq_operations format5_seq_ops = { 66362306a36Sopenharmony_ci .start = table_seq_start, 66462306a36Sopenharmony_ci .next = table_seq_next, 66562306a36Sopenharmony_ci .stop = table_seq_stop, 66662306a36Sopenharmony_ci .show = table_seq_show, 66762306a36Sopenharmony_ci}; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_cistatic const struct file_operations format1_fops; 67062306a36Sopenharmony_cistatic const struct file_operations format2_fops; 67162306a36Sopenharmony_cistatic const struct file_operations format3_fops; 67262306a36Sopenharmony_cistatic const struct file_operations format4_fops; 67362306a36Sopenharmony_cistatic const struct file_operations format5_fops; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cistatic int table_open1(struct inode *inode, struct file *file) 67662306a36Sopenharmony_ci{ 67762306a36Sopenharmony_ci struct seq_file *seq; 67862306a36Sopenharmony_ci int ret; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci ret = seq_open(file, &format1_seq_ops); 68162306a36Sopenharmony_ci if (ret) 68262306a36Sopenharmony_ci return ret; 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci seq = file->private_data; 68562306a36Sopenharmony_ci seq->private = inode->i_private; /* the dlm_ls */ 68662306a36Sopenharmony_ci return 0; 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic int table_open2(struct inode *inode, struct file *file) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci struct seq_file *seq; 69262306a36Sopenharmony_ci int ret; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci ret = seq_open(file, &format2_seq_ops); 69562306a36Sopenharmony_ci if (ret) 69662306a36Sopenharmony_ci return ret; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci seq = file->private_data; 69962306a36Sopenharmony_ci seq->private = inode->i_private; /* the dlm_ls */ 70062306a36Sopenharmony_ci return 0; 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic ssize_t table_write2(struct file *file, const char __user *user_buf, 70462306a36Sopenharmony_ci size_t count, loff_t *ppos) 70562306a36Sopenharmony_ci{ 70662306a36Sopenharmony_ci struct seq_file *seq = file->private_data; 70762306a36Sopenharmony_ci int n, len, lkb_nodeid, lkb_status, error; 70862306a36Sopenharmony_ci char name[DLM_RESNAME_MAXLEN + 1] = {}; 70962306a36Sopenharmony_ci struct dlm_ls *ls = seq->private; 71062306a36Sopenharmony_ci unsigned int lkb_flags; 71162306a36Sopenharmony_ci char buf[256] = {}; 71262306a36Sopenharmony_ci uint32_t lkb_id; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (copy_from_user(buf, user_buf, 71562306a36Sopenharmony_ci min_t(size_t, sizeof(buf) - 1, count))) 71662306a36Sopenharmony_ci return -EFAULT; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci n = sscanf(buf, "%x %" __stringify(DLM_RESNAME_MAXLEN) "s %x %d %d", 71962306a36Sopenharmony_ci &lkb_id, name, &lkb_flags, &lkb_nodeid, &lkb_status); 72062306a36Sopenharmony_ci if (n != 5) 72162306a36Sopenharmony_ci return -EINVAL; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci len = strnlen(name, DLM_RESNAME_MAXLEN); 72462306a36Sopenharmony_ci error = dlm_debug_add_lkb(ls, lkb_id, name, len, lkb_flags, 72562306a36Sopenharmony_ci lkb_nodeid, lkb_status); 72662306a36Sopenharmony_ci if (error) 72762306a36Sopenharmony_ci return error; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci return count; 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_cistatic int table_open3(struct inode *inode, struct file *file) 73362306a36Sopenharmony_ci{ 73462306a36Sopenharmony_ci struct seq_file *seq; 73562306a36Sopenharmony_ci int ret; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci ret = seq_open(file, &format3_seq_ops); 73862306a36Sopenharmony_ci if (ret) 73962306a36Sopenharmony_ci return ret; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci seq = file->private_data; 74262306a36Sopenharmony_ci seq->private = inode->i_private; /* the dlm_ls */ 74362306a36Sopenharmony_ci return 0; 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_cistatic int table_open4(struct inode *inode, struct file *file) 74762306a36Sopenharmony_ci{ 74862306a36Sopenharmony_ci struct seq_file *seq; 74962306a36Sopenharmony_ci int ret; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci ret = seq_open(file, &format4_seq_ops); 75262306a36Sopenharmony_ci if (ret) 75362306a36Sopenharmony_ci return ret; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci seq = file->private_data; 75662306a36Sopenharmony_ci seq->private = inode->i_private; /* the dlm_ls */ 75762306a36Sopenharmony_ci return 0; 75862306a36Sopenharmony_ci} 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic int table_open5(struct inode *inode, struct file *file) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci struct seq_file *seq; 76362306a36Sopenharmony_ci int ret; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci ret = seq_open(file, &format5_seq_ops); 76662306a36Sopenharmony_ci if (ret) 76762306a36Sopenharmony_ci return ret; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci seq = file->private_data; 77062306a36Sopenharmony_ci seq->private = inode->i_private; /* the dlm_ls */ 77162306a36Sopenharmony_ci return 0; 77262306a36Sopenharmony_ci} 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_cistatic const struct file_operations format1_fops = { 77562306a36Sopenharmony_ci .owner = THIS_MODULE, 77662306a36Sopenharmony_ci .open = table_open1, 77762306a36Sopenharmony_ci .read = seq_read, 77862306a36Sopenharmony_ci .llseek = seq_lseek, 77962306a36Sopenharmony_ci .release = seq_release 78062306a36Sopenharmony_ci}; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_cistatic const struct file_operations format2_fops = { 78362306a36Sopenharmony_ci .owner = THIS_MODULE, 78462306a36Sopenharmony_ci .open = table_open2, 78562306a36Sopenharmony_ci .read = seq_read, 78662306a36Sopenharmony_ci .write = table_write2, 78762306a36Sopenharmony_ci .llseek = seq_lseek, 78862306a36Sopenharmony_ci .release = seq_release 78962306a36Sopenharmony_ci}; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_cistatic const struct file_operations format3_fops = { 79262306a36Sopenharmony_ci .owner = THIS_MODULE, 79362306a36Sopenharmony_ci .open = table_open3, 79462306a36Sopenharmony_ci .read = seq_read, 79562306a36Sopenharmony_ci .llseek = seq_lseek, 79662306a36Sopenharmony_ci .release = seq_release 79762306a36Sopenharmony_ci}; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_cistatic const struct file_operations format4_fops = { 80062306a36Sopenharmony_ci .owner = THIS_MODULE, 80162306a36Sopenharmony_ci .open = table_open4, 80262306a36Sopenharmony_ci .read = seq_read, 80362306a36Sopenharmony_ci .llseek = seq_lseek, 80462306a36Sopenharmony_ci .release = seq_release 80562306a36Sopenharmony_ci}; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_cistatic const struct file_operations format5_fops = { 80862306a36Sopenharmony_ci .owner = THIS_MODULE, 80962306a36Sopenharmony_ci .open = table_open5, 81062306a36Sopenharmony_ci .read = seq_read, 81162306a36Sopenharmony_ci .llseek = seq_lseek, 81262306a36Sopenharmony_ci .release = seq_release 81362306a36Sopenharmony_ci}; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci/* 81662306a36Sopenharmony_ci * dump lkb's on the ls_waiters list 81762306a36Sopenharmony_ci */ 81862306a36Sopenharmony_cistatic ssize_t waiters_read(struct file *file, char __user *userbuf, 81962306a36Sopenharmony_ci size_t count, loff_t *ppos) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci struct dlm_ls *ls = file->private_data; 82262306a36Sopenharmony_ci struct dlm_lkb *lkb; 82362306a36Sopenharmony_ci size_t len = DLM_DEBUG_BUF_LEN, pos = 0, ret, rv; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci mutex_lock(&debug_buf_lock); 82662306a36Sopenharmony_ci mutex_lock(&ls->ls_waiters_mutex); 82762306a36Sopenharmony_ci memset(debug_buf, 0, sizeof(debug_buf)); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) { 83062306a36Sopenharmony_ci ret = snprintf(debug_buf + pos, len - pos, "%x %d %d %s\n", 83162306a36Sopenharmony_ci lkb->lkb_id, lkb->lkb_wait_type, 83262306a36Sopenharmony_ci lkb->lkb_nodeid, lkb->lkb_resource->res_name); 83362306a36Sopenharmony_ci if (ret >= len - pos) 83462306a36Sopenharmony_ci break; 83562306a36Sopenharmony_ci pos += ret; 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci mutex_unlock(&ls->ls_waiters_mutex); 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci rv = simple_read_from_buffer(userbuf, count, ppos, debug_buf, pos); 84062306a36Sopenharmony_ci mutex_unlock(&debug_buf_lock); 84162306a36Sopenharmony_ci return rv; 84262306a36Sopenharmony_ci} 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_cistatic ssize_t waiters_write(struct file *file, const char __user *user_buf, 84562306a36Sopenharmony_ci size_t count, loff_t *ppos) 84662306a36Sopenharmony_ci{ 84762306a36Sopenharmony_ci struct dlm_ls *ls = file->private_data; 84862306a36Sopenharmony_ci int mstype, to_nodeid; 84962306a36Sopenharmony_ci char buf[128] = {}; 85062306a36Sopenharmony_ci uint32_t lkb_id; 85162306a36Sopenharmony_ci int n, error; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci if (copy_from_user(buf, user_buf, 85462306a36Sopenharmony_ci min_t(size_t, sizeof(buf) - 1, count))) 85562306a36Sopenharmony_ci return -EFAULT; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci n = sscanf(buf, "%x %d %d", &lkb_id, &mstype, &to_nodeid); 85862306a36Sopenharmony_ci if (n != 3) 85962306a36Sopenharmony_ci return -EINVAL; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci error = dlm_debug_add_lkb_to_waiters(ls, lkb_id, mstype, to_nodeid); 86262306a36Sopenharmony_ci if (error) 86362306a36Sopenharmony_ci return error; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci return count; 86662306a36Sopenharmony_ci} 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_cistatic const struct file_operations waiters_fops = { 86962306a36Sopenharmony_ci .owner = THIS_MODULE, 87062306a36Sopenharmony_ci .open = simple_open, 87162306a36Sopenharmony_ci .read = waiters_read, 87262306a36Sopenharmony_ci .write = waiters_write, 87362306a36Sopenharmony_ci .llseek = default_llseek, 87462306a36Sopenharmony_ci}; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_civoid dlm_delete_debug_file(struct dlm_ls *ls) 87762306a36Sopenharmony_ci{ 87862306a36Sopenharmony_ci debugfs_remove(ls->ls_debug_rsb_dentry); 87962306a36Sopenharmony_ci debugfs_remove(ls->ls_debug_waiters_dentry); 88062306a36Sopenharmony_ci debugfs_remove(ls->ls_debug_locks_dentry); 88162306a36Sopenharmony_ci debugfs_remove(ls->ls_debug_all_dentry); 88262306a36Sopenharmony_ci debugfs_remove(ls->ls_debug_toss_dentry); 88362306a36Sopenharmony_ci debugfs_remove(ls->ls_debug_queued_asts_dentry); 88462306a36Sopenharmony_ci} 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_cistatic int dlm_state_show(struct seq_file *file, void *offset) 88762306a36Sopenharmony_ci{ 88862306a36Sopenharmony_ci seq_printf(file, "%s\n", dlm_midcomms_state(file->private)); 88962306a36Sopenharmony_ci return 0; 89062306a36Sopenharmony_ci} 89162306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(dlm_state); 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_cistatic int dlm_flags_show(struct seq_file *file, void *offset) 89462306a36Sopenharmony_ci{ 89562306a36Sopenharmony_ci seq_printf(file, "%lu\n", dlm_midcomms_flags(file->private)); 89662306a36Sopenharmony_ci return 0; 89762306a36Sopenharmony_ci} 89862306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(dlm_flags); 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic int dlm_send_queue_cnt_show(struct seq_file *file, void *offset) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci seq_printf(file, "%d\n", dlm_midcomms_send_queue_cnt(file->private)); 90362306a36Sopenharmony_ci return 0; 90462306a36Sopenharmony_ci} 90562306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(dlm_send_queue_cnt); 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cistatic int dlm_version_show(struct seq_file *file, void *offset) 90862306a36Sopenharmony_ci{ 90962306a36Sopenharmony_ci seq_printf(file, "0x%08x\n", dlm_midcomms_version(file->private)); 91062306a36Sopenharmony_ci return 0; 91162306a36Sopenharmony_ci} 91262306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(dlm_version); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cistatic ssize_t dlm_rawmsg_write(struct file *fp, const char __user *user_buf, 91562306a36Sopenharmony_ci size_t count, loff_t *ppos) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci void *buf; 91862306a36Sopenharmony_ci int ret; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci if (count > PAGE_SIZE || count < sizeof(struct dlm_header)) 92162306a36Sopenharmony_ci return -EINVAL; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci buf = kmalloc(PAGE_SIZE, GFP_NOFS); 92462306a36Sopenharmony_ci if (!buf) 92562306a36Sopenharmony_ci return -ENOMEM; 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci if (copy_from_user(buf, user_buf, count)) { 92862306a36Sopenharmony_ci ret = -EFAULT; 92962306a36Sopenharmony_ci goto out; 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci ret = dlm_midcomms_rawmsg_send(fp->private_data, buf, count); 93362306a36Sopenharmony_ci if (ret) 93462306a36Sopenharmony_ci goto out; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci kfree(buf); 93762306a36Sopenharmony_ci return count; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ciout: 94062306a36Sopenharmony_ci kfree(buf); 94162306a36Sopenharmony_ci return ret; 94262306a36Sopenharmony_ci} 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_cistatic const struct file_operations dlm_rawmsg_fops = { 94562306a36Sopenharmony_ci .open = simple_open, 94662306a36Sopenharmony_ci .write = dlm_rawmsg_write, 94762306a36Sopenharmony_ci .llseek = no_llseek, 94862306a36Sopenharmony_ci}; 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_civoid *dlm_create_debug_comms_file(int nodeid, void *data) 95162306a36Sopenharmony_ci{ 95262306a36Sopenharmony_ci struct dentry *d_node; 95362306a36Sopenharmony_ci char name[256]; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci memset(name, 0, sizeof(name)); 95662306a36Sopenharmony_ci snprintf(name, 256, "%d", nodeid); 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci d_node = debugfs_create_dir(name, dlm_comms); 95962306a36Sopenharmony_ci debugfs_create_file("state", 0444, d_node, data, &dlm_state_fops); 96062306a36Sopenharmony_ci debugfs_create_file("flags", 0444, d_node, data, &dlm_flags_fops); 96162306a36Sopenharmony_ci debugfs_create_file("send_queue_count", 0444, d_node, data, 96262306a36Sopenharmony_ci &dlm_send_queue_cnt_fops); 96362306a36Sopenharmony_ci debugfs_create_file("version", 0444, d_node, data, &dlm_version_fops); 96462306a36Sopenharmony_ci debugfs_create_file("rawmsg", 0200, d_node, data, &dlm_rawmsg_fops); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci return d_node; 96762306a36Sopenharmony_ci} 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_civoid dlm_delete_debug_comms_file(void *ctx) 97062306a36Sopenharmony_ci{ 97162306a36Sopenharmony_ci debugfs_remove(ctx); 97262306a36Sopenharmony_ci} 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_civoid dlm_create_debug_file(struct dlm_ls *ls) 97562306a36Sopenharmony_ci{ 97662306a36Sopenharmony_ci /* Reserve enough space for the longest file name */ 97762306a36Sopenharmony_ci char name[DLM_LOCKSPACE_LEN + sizeof("_queued_asts")]; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci /* format 1 */ 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci ls->ls_debug_rsb_dentry = debugfs_create_file(ls->ls_name, 98262306a36Sopenharmony_ci S_IFREG | S_IRUGO, 98362306a36Sopenharmony_ci dlm_root, 98462306a36Sopenharmony_ci ls, 98562306a36Sopenharmony_ci &format1_fops); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci /* format 2 */ 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci memset(name, 0, sizeof(name)); 99062306a36Sopenharmony_ci snprintf(name, sizeof(name), "%s_locks", ls->ls_name); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci ls->ls_debug_locks_dentry = debugfs_create_file(name, 99362306a36Sopenharmony_ci 0644, 99462306a36Sopenharmony_ci dlm_root, 99562306a36Sopenharmony_ci ls, 99662306a36Sopenharmony_ci &format2_fops); 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci /* format 3 */ 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci memset(name, 0, sizeof(name)); 100162306a36Sopenharmony_ci snprintf(name, sizeof(name), "%s_all", ls->ls_name); 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci ls->ls_debug_all_dentry = debugfs_create_file(name, 100462306a36Sopenharmony_ci S_IFREG | S_IRUGO, 100562306a36Sopenharmony_ci dlm_root, 100662306a36Sopenharmony_ci ls, 100762306a36Sopenharmony_ci &format3_fops); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci /* format 4 */ 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci memset(name, 0, sizeof(name)); 101262306a36Sopenharmony_ci snprintf(name, sizeof(name), "%s_toss", ls->ls_name); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci ls->ls_debug_toss_dentry = debugfs_create_file(name, 101562306a36Sopenharmony_ci S_IFREG | S_IRUGO, 101662306a36Sopenharmony_ci dlm_root, 101762306a36Sopenharmony_ci ls, 101862306a36Sopenharmony_ci &format4_fops); 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci memset(name, 0, sizeof(name)); 102162306a36Sopenharmony_ci snprintf(name, sizeof(name), "%s_waiters", ls->ls_name); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci ls->ls_debug_waiters_dentry = debugfs_create_file(name, 102462306a36Sopenharmony_ci 0644, 102562306a36Sopenharmony_ci dlm_root, 102662306a36Sopenharmony_ci ls, 102762306a36Sopenharmony_ci &waiters_fops); 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci /* format 5 */ 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci memset(name, 0, sizeof(name)); 103262306a36Sopenharmony_ci snprintf(name, sizeof(name), "%s_queued_asts", ls->ls_name); 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci ls->ls_debug_queued_asts_dentry = debugfs_create_file(name, 103562306a36Sopenharmony_ci 0644, 103662306a36Sopenharmony_ci dlm_root, 103762306a36Sopenharmony_ci ls, 103862306a36Sopenharmony_ci &format5_fops); 103962306a36Sopenharmony_ci} 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_civoid __init dlm_register_debugfs(void) 104262306a36Sopenharmony_ci{ 104362306a36Sopenharmony_ci mutex_init(&debug_buf_lock); 104462306a36Sopenharmony_ci dlm_root = debugfs_create_dir("dlm", NULL); 104562306a36Sopenharmony_ci dlm_comms = debugfs_create_dir("comms", dlm_root); 104662306a36Sopenharmony_ci} 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_civoid dlm_unregister_debugfs(void) 104962306a36Sopenharmony_ci{ 105062306a36Sopenharmony_ci debugfs_remove(dlm_root); 105162306a36Sopenharmony_ci} 105262306a36Sopenharmony_ci 1053