fs: dlm: add lkb debugfs functionality
This patch adds functionality to add an lkb during runtime. This is a highly debugging feature only, wrong input can crash the kernel. It is a early state feature as well. The goal is to provide a user interface for manipulate dlm state and combine it with the rawmsg feature. It is debugfs functionality, we don't care about UAPI breakage. Even it's possible to add lkb's/rsb's which could never be exists in such wat by using normal DLM operation. The user of this interface always need to think before using this feature, not every crash which happens can really occur during normal dlm operation. Future there should be more functionality to add a more realistic lkb which reflects normal DLM state inside the kernel. For now this is enough. Signed-off-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
This commit is contained in:
Родитель
75d25ffe38
Коммит
5054e79de9
|
@ -635,6 +635,35 @@ static int table_open2(struct inode *inode, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t table_write2(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct seq_file *seq = file->private_data;
|
||||
int n, len, lkb_nodeid, lkb_status, error;
|
||||
char name[DLM_RESNAME_MAXLEN] = {};
|
||||
struct dlm_ls *ls = seq->private;
|
||||
unsigned int lkb_flags;
|
||||
char buf[256] = {};
|
||||
uint32_t lkb_id;
|
||||
|
||||
if (copy_from_user(buf, user_buf,
|
||||
min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
n = sscanf(buf, "%x %" __stringify(DLM_RESNAME_MAXLEN) "s %x %d %d",
|
||||
&lkb_id, name, &lkb_flags, &lkb_nodeid, &lkb_status);
|
||||
if (n != 5)
|
||||
return -EINVAL;
|
||||
|
||||
len = strnlen(name, DLM_RESNAME_MAXLEN);
|
||||
error = dlm_debug_add_lkb(ls, lkb_id, name, len, lkb_flags,
|
||||
lkb_nodeid, lkb_status);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int table_open3(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct seq_file *seq;
|
||||
|
@ -675,6 +704,7 @@ static const struct file_operations format2_fops = {
|
|||
.owner = THIS_MODULE,
|
||||
.open = table_open2,
|
||||
.read = seq_read,
|
||||
.write = table_write2,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release
|
||||
};
|
||||
|
@ -846,7 +876,7 @@ void dlm_create_debug_file(struct dlm_ls *ls)
|
|||
snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_locks", ls->ls_name);
|
||||
|
||||
ls->ls_debug_locks_dentry = debugfs_create_file(name,
|
||||
S_IFREG | S_IRUGO,
|
||||
0644,
|
||||
dlm_root,
|
||||
ls,
|
||||
&format2_fops);
|
||||
|
|
|
@ -6317,3 +6317,49 @@ int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
|
|||
return error;
|
||||
}
|
||||
|
||||
/* debug functionality */
|
||||
int dlm_debug_add_lkb(struct dlm_ls *ls, uint32_t lkb_id, char *name, int len,
|
||||
int lkb_nodeid, unsigned int lkb_flags, int lkb_status)
|
||||
{
|
||||
struct dlm_lksb *lksb;
|
||||
struct dlm_lkb *lkb;
|
||||
struct dlm_rsb *r;
|
||||
int error;
|
||||
|
||||
/* we currently can't set a valid user lock */
|
||||
if (lkb_flags & DLM_IFL_USER)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
lksb = kzalloc(sizeof(*lksb), GFP_NOFS);
|
||||
if (!lksb)
|
||||
return -ENOMEM;
|
||||
|
||||
error = _create_lkb(ls, &lkb, lkb_id, lkb_id + 1);
|
||||
if (error) {
|
||||
kfree(lksb);
|
||||
return error;
|
||||
}
|
||||
|
||||
lkb->lkb_flags = lkb_flags;
|
||||
lkb->lkb_nodeid = lkb_nodeid;
|
||||
lkb->lkb_lksb = lksb;
|
||||
/* user specific pointer, just don't have it NULL for kernel locks */
|
||||
if (~lkb_flags & DLM_IFL_USER)
|
||||
lkb->lkb_astparam = (void *)0xDEADBEEF;
|
||||
|
||||
error = find_rsb(ls, name, len, 0, R_REQUEST, &r);
|
||||
if (error) {
|
||||
kfree(lksb);
|
||||
__put_lkb(ls, lkb);
|
||||
return error;
|
||||
}
|
||||
|
||||
lock_rsb(r);
|
||||
attach_lkb(r, lkb);
|
||||
add_lkb(r, lkb, lkb_status);
|
||||
unlock_rsb(r);
|
||||
put_rsb(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
|
|||
int nodeid, int pid);
|
||||
int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid);
|
||||
void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc);
|
||||
int dlm_debug_add_lkb(struct dlm_ls *ls, uint32_t lkb_id, char *name, int len,
|
||||
int lkb_nodeid, unsigned int lkb_flags, int lkb_status);
|
||||
|
||||
static inline int is_master(struct dlm_rsb *r)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче