⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlmdebug.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- mode: c; c-basic-offset: 8; -*- * vim: noexpandtab sw=8 ts=8 sts=0: * * dlmdebug.c * * debug functionality for the dlm * * Copyright (C) 2004 Oracle.  All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. * */#include <linux/types.h>#include <linux/slab.h>#include <linux/highmem.h>#include <linux/utsname.h>#include <linux/sysctl.h>#include <linux/spinlock.h>#include <linux/proc_fs.h>#include "cluster/heartbeat.h"#include "cluster/nodemanager.h"#include "cluster/tcp.h"#include "dlmapi.h"#include "dlmcommon.h"#include "dlmdebug.h"#include "dlmdomain.h"#include "dlmdebug.h"#define MLOG_MASK_PREFIX ML_DLM#include "cluster/masklog.h"static int dlm_dump_all_lock_resources(const char __user *data,					unsigned int len);static void dlm_dump_purge_list(struct dlm_ctxt *dlm);static int dlm_dump_all_purge_lists(const char __user *data, unsigned int len);static int dlm_trigger_migration(const char __user *data, unsigned int len);static int dlm_dump_one_lock_resource(const char __user *data,				       unsigned int len);static int dlm_dump_work_queues(const char __user *data, unsigned int len);static int dlm_parse_domain_and_lockres(char *buf, unsigned int len,					struct dlm_ctxt **dlm,					struct dlm_lock_resource **res);static int dlm_proc_stats(char *page, char **start, off_t off,			  int count, int *eof, void *data);typedef int (dlm_debug_func_t)(const char __user *data, unsigned int len);struct dlm_debug_funcs{	char key;	dlm_debug_func_t *func;};static struct dlm_debug_funcs dlm_debug_map[] = {	{ 'r', dlm_dump_all_lock_resources },	{ 'R', dlm_dump_one_lock_resource },	{ 'm', dlm_dump_all_mles },	{ 'p', dlm_dump_all_purge_lists  },	{ 'M', dlm_trigger_migration },	{ 'w', dlm_dump_work_queues }};static int dlm_debug_map_sz = (sizeof(dlm_debug_map) /			       sizeof(struct dlm_debug_funcs));static ssize_t write_dlm_debug(struct file *file, const char __user *buf,			       size_t count, loff_t *ppos){	int i;	char c;	dlm_debug_func_t *fn;	int ret;	mlog(0, "(%p, %p, %u, %lld)\n",		  file, buf, (unsigned int)count, (long long)*ppos);	ret = 0;	if (count<=0)		goto done;	ret = -EFAULT;	if (get_user(c, buf))		goto done;	ret = count;	for (i=0; i < dlm_debug_map_sz; i++) {		struct dlm_debug_funcs *d = &dlm_debug_map[i];		if (c == d->key) {			fn = d->func;			if (fn)				ret = (fn)(buf, count);			goto done;		}	}done:	return ret;}static struct file_operations dlm_debug_operations = {	.write          = write_dlm_debug,};#define OCFS2_DLM_PROC_PATH "fs/ocfs2_dlm"#define DLM_DEBUG_PROC_NAME "debug"#define DLM_STAT_PROC_NAME  "stat"static struct proc_dir_entry *ocfs2_dlm_proc;void dlm_remove_proc(void){	if (ocfs2_dlm_proc) {		remove_proc_entry(DLM_DEBUG_PROC_NAME, ocfs2_dlm_proc);		remove_proc_entry(OCFS2_DLM_PROC_PATH, NULL);	}}void dlm_init_proc(void){	struct proc_dir_entry *entry;	ocfs2_dlm_proc = proc_mkdir(OCFS2_DLM_PROC_PATH, NULL);	if (!ocfs2_dlm_proc) {		mlog_errno(-ENOMEM);		return;	}	entry = create_proc_entry(DLM_DEBUG_PROC_NAME, S_IWUSR,				  ocfs2_dlm_proc);	if (entry)		entry->proc_fops = &dlm_debug_operations;}static int dlm_proc_stats(char *page, char **start, off_t off,			  int count, int *eof, void *data){	int len;	struct dlm_ctxt *dlm = data;	len = sprintf(page, "local=%d, remote=%d, unknown=%d, key=0x%08x\n",		      atomic_read(&dlm->local_resources),		      atomic_read(&dlm->remote_resources),		      atomic_read(&dlm->unknown_resources),		      dlm->key);	if (len <= off + count)		*eof = 1;	*start = page + off;	len -= off;	if (len > count)		len = count;	if (len < 0)		len = 0;	return len;}void dlm_proc_add_domain(struct dlm_ctxt *dlm){	struct proc_dir_entry *entry;	dlm->dlm_proc = proc_mkdir(dlm->name, ocfs2_dlm_proc);	if (dlm->dlm_proc) {		entry = create_proc_read_entry(DLM_STAT_PROC_NAME,					       S_IFREG | S_IRUGO, dlm->dlm_proc,					       dlm_proc_stats, (char *)dlm);		if (entry)			entry->owner = THIS_MODULE;	}}void dlm_proc_del_domain(struct dlm_ctxt *dlm){	if (dlm->dlm_proc) {		remove_proc_entry(DLM_STAT_PROC_NAME, dlm->dlm_proc);		remove_proc_entry(dlm->name, ocfs2_dlm_proc);	}}/* lock resource printing is usually very important (printed * right before a BUG in some cases), but we'd like to be * able to shut it off if needed, hence the KERN_NOTICE level */static int dlm_dump_all_lock_resources(const char __user *data,				       unsigned int len){	struct dlm_ctxt *dlm;	struct list_head *iter;	mlog(ML_NOTICE, "dumping ALL dlm state for node %s\n",		  system_utsname.nodename);	spin_lock(&dlm_domain_lock);	list_for_each(iter, &dlm_domains) {		dlm = list_entry (iter, struct dlm_ctxt, list);		dlm_dump_lock_resources(dlm);	}	spin_unlock(&dlm_domain_lock);	return len;}static int dlm_dump_one_lock_resource(const char __user *data,				       unsigned int len){	struct dlm_ctxt *dlm;	struct dlm_lock_resource *res;	char *buf = NULL;	int ret = -EINVAL;	int tmpret;	if (len >= PAGE_SIZE-1) {		mlog(ML_ERROR, "user passed too much data: %d bytes\n", len);		goto leave;	}	if (len < 5) {		mlog(ML_ERROR, "user passed too little data: %d bytes\n", len);		goto leave;	}	buf = kmalloc(len+1, GFP_NOFS);	if (!buf) {		mlog(ML_ERROR, "could not alloc %d bytes\n", len+1);		ret = -ENOMEM;		goto leave;	}	if (strncpy_from_user(buf, data, len) < len) {		mlog(ML_ERROR, "failed to get all user data.  done.\n");		goto leave;	}	buf[len]='\0';	mlog(0, "got this data from user: %s\n", buf);	if (*buf != 'R') {		mlog(0, "bad data\n");		goto leave;	}	tmpret = dlm_parse_domain_and_lockres(buf, len, &dlm, &res);	if (tmpret < 0) {		mlog(0, "bad data\n");		goto leave;	}	mlog(ML_NOTICE, "struct dlm_ctxt: %s, node=%u, key=%u\n",		dlm->name, dlm->node_num, dlm->key);	dlm_print_one_lock_resource(res);	dlm_lockres_put(res);	dlm_put(dlm);	ret = len;leave:	if (buf)		kfree(buf);	return ret;}static void dlm_print_lockres_refmap(struct dlm_lock_resource *res){	int bit;	assert_spin_locked(&res->spinlock);	mlog(ML_NOTICE, "  refmap nodes: [ ");	bit = 0;	while (1) {		bit = find_next_bit(res->refmap, O2NM_MAX_NODES, bit);		if (bit >= O2NM_MAX_NODES)			break;		printk("%u ", bit);		bit++;	}	printk("], inflight=%u\n", res->inflight_locks);}void dlm_print_one_lock_resource(struct dlm_lock_resource *res){	mlog(ML_NOTICE, "lockres: %.*s, owner=%u, state=%u\n",	       res->lockname.len, res->lockname.name,	       res->owner, res->state);	spin_lock(&res->spinlock);	__dlm_print_one_lock_resource(res);	spin_unlock(&res->spinlock);}void __dlm_print_one_lock_resource(struct dlm_lock_resource *res){	struct list_head *iter2;	struct dlm_lock *lock;	assert_spin_locked(&res->spinlock);	mlog(ML_NOTICE, "lockres: %.*s, owner=%u, state=%u\n",	       res->lockname.len, res->lockname.name,	       res->owner, res->state);	mlog(ML_NOTICE, "  last used: %lu, on purge list: %s\n",	     res->last_used, list_empty(&res->purge) ? "no" : "yes");	dlm_print_lockres_refmap(res);	mlog(ML_NOTICE, "  granted queue: \n");	list_for_each(iter2, &res->granted) {		lock = list_entry(iter2, struct dlm_lock, list);		spin_lock(&lock->spinlock);		mlog(ML_NOTICE, "    type=%d, conv=%d, node=%u, "		       "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",		       lock->ml.type, lock->ml.convert_type, lock->ml.node,		       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),		       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),		       list_empty(&lock->ast_list) ? 'y' : 'n',		       lock->ast_pending ? 'y' : 'n',		       list_empty(&lock->bast_list) ? 'y' : 'n',		       lock->bast_pending ? 'y' : 'n');		spin_unlock(&lock->spinlock);	}	mlog(ML_NOTICE, "  converting queue: \n");	list_for_each(iter2, &res->converting) {		lock = list_entry(iter2, struct dlm_lock, list);		spin_lock(&lock->spinlock);		mlog(ML_NOTICE, "    type=%d, conv=%d, node=%u, "		       "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",		       lock->ml.type, lock->ml.convert_type, lock->ml.node,		       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),		       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),		       list_empty(&lock->ast_list) ? 'y' : 'n',		       lock->ast_pending ? 'y' : 'n',		       list_empty(&lock->bast_list) ? 'y' : 'n',		       lock->bast_pending ? 'y' : 'n');		spin_unlock(&lock->spinlock);	}	mlog(ML_NOTICE, "  blocked queue: \n");	list_for_each(iter2, &res->blocked) {		lock = list_entry(iter2, struct dlm_lock, list);		spin_lock(&lock->spinlock);		mlog(ML_NOTICE, "    type=%d, conv=%d, node=%u, "		       "cookie=%u:%llu, ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",		       lock->ml.type, lock->ml.convert_type, lock->ml.node,		       dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),		       dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),		       list_empty(&lock->ast_list) ? 'y' : 'n',

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -