Commit 3f67eaed authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull dlm updates from David Teigland:
 "This set includes the normal collection of minor fixes and cleanups,
  new kmem caches for network messaging structs, a start on some basic
  tracepoints, and some new debugfs files for inserting test messages"

* tag 'dlm-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm: (32 commits)
  fs: dlm: print cluster addr if non-cluster node connects
  fs: dlm: memory cache for lowcomms hotpath
  fs: dlm: memory cache for writequeue_entry
  fs: dlm: memory cache for midcomms hotpath
  fs: dlm: remove wq_alloc mutex
  fs: dlm: use event based wait for pending remove
  fs: dlm: check for pending users filling buffers
  fs: dlm: use list_empty() to check last iteration
  fs: dlm: fix build with CONFIG_IPV6 disabled
  fs: dlm: replace use of socket sk_callback_lock with sock_lock
  fs: dlm: don't call kernel_getpeername() in error_report()
  fs: dlm: fix potential buffer overflow
  fs: dlm:Remove unneeded semicolon
  fs: dlm: remove double list_first_entry call
  fs: dlm: filter user dlm messages for kernel locks
  fs: dlm: add lkb waiters debugfs functionality
  fs: dlm: add lkb debugfs functionality
  fs: dlm: allow create lkb with specific id range
  fs: dlm: add debugfs rawmsg send functionality
  fs: dlm: let handle callback data as void
  ...
parents 8481c323 feae43f8
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
*******************************************************************************
******************************************************************************/

#include <trace/events/dlm.h>

#include "dlm_internal.h"
#include "lock.h"
#include "user.h"
@@ -254,10 +256,12 @@ void dlm_callback_work(struct work_struct *work)
			continue;
		} else if (callbacks[i].flags & DLM_CB_BAST) {
			bastfn(lkb->lkb_astparam, callbacks[i].mode);
			trace_dlm_bast(ls, lkb, callbacks[i].mode);
		} else if (callbacks[i].flags & DLM_CB_CAST) {
			lkb->lkb_lksb->sb_status = callbacks[i].sb_status;
			lkb->lkb_lksb->sb_flags = callbacks[i].sb_flags;
			castfn(lkb->lkb_astparam);
			trace_dlm_ast(ls, lkb, lkb->lkb_lksb);
		}
	}

@@ -295,7 +299,8 @@ void dlm_callback_suspend(struct dlm_ls *ls)
void dlm_callback_resume(struct dlm_ls *ls)
{
	struct dlm_lkb *lkb, *safe;
	int count = 0;
	int count = 0, sum = 0;
	bool empty;

	clear_bit(LSFL_CB_DELAY, &ls->ls_flags);

@@ -311,14 +316,17 @@ void dlm_callback_resume(struct dlm_ls *ls)
		if (count == MAX_CB_QUEUE)
			break;
	}
	empty = list_empty(&ls->ls_cb_delay);
	mutex_unlock(&ls->ls_cb_mutex);

	if (count)
		log_rinfo(ls, "dlm_callback_resume %d", count);
	if (count == MAX_CB_QUEUE) {
	sum += count;
	if (!empty) {
		count = 0;
		cond_resched();
		goto more;
	}

	if (sum)
		log_rinfo(ls, "%s %d", __func__, sum);
}
+94 −2
Original line number Diff line number Diff line
@@ -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 + 1] = {};
	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
};
@@ -724,10 +754,35 @@ static ssize_t waiters_read(struct file *file, char __user *userbuf,
	return rv;
}

static ssize_t waiters_write(struct file *file, const char __user *user_buf,
			     size_t count, loff_t *ppos)
{
	struct dlm_ls *ls = file->private_data;
	int mstype, to_nodeid;
	char buf[128] = {};
	uint32_t lkb_id;
	int n, error;

	if (copy_from_user(buf, user_buf,
			   min_t(size_t, sizeof(buf) - 1, count)))
		return -EFAULT;

	n = sscanf(buf, "%x %d %d", &lkb_id, &mstype, &to_nodeid);
	if (n != 3)
		return -EINVAL;

	error = dlm_debug_add_lkb_to_waiters(ls, lkb_id, mstype, to_nodeid);
	if (error)
		return error;

	return count;
}

static const struct file_operations waiters_fops = {
	.owner   = THIS_MODULE,
	.open    = simple_open,
	.read    = waiters_read,
	.write   = waiters_write,
	.llseek  = default_llseek,
};

@@ -768,6 +823,42 @@ static int dlm_version_show(struct seq_file *file, void *offset)
}
DEFINE_SHOW_ATTRIBUTE(dlm_version);

static ssize_t dlm_rawmsg_write(struct file *fp, const char __user *user_buf,
				size_t count, loff_t *ppos)
{
	void *buf;
	int ret;

	if (count > PAGE_SIZE || count < sizeof(struct dlm_header))
		return -EINVAL;

	buf = kmalloc(PAGE_SIZE, GFP_NOFS);
	if (!buf)
		return -ENOMEM;

	if (copy_from_user(buf, user_buf, count)) {
		ret = -EFAULT;
		goto out;
	}

	ret = dlm_midcomms_rawmsg_send(fp->private_data, buf, count);
	if (ret)
		goto out;

	kfree(buf);
	return count;

out:
	kfree(buf);
	return ret;
}

static const struct file_operations dlm_rawmsg_fops = {
	.open	= simple_open,
	.write	= dlm_rawmsg_write,
	.llseek	= no_llseek,
};

void *dlm_create_debug_comms_file(int nodeid, void *data)
{
	struct dentry *d_node;
@@ -782,6 +873,7 @@ void *dlm_create_debug_comms_file(int nodeid, void *data)
	debugfs_create_file("send_queue_count", 0444, d_node, data,
			    &dlm_send_queue_cnt_fops);
	debugfs_create_file("version", 0444, d_node, data, &dlm_version_fops);
	debugfs_create_file("rawmsg", 0200, d_node, data, &dlm_rawmsg_fops);

	return d_node;
}
@@ -809,7 +901,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);
@@ -840,7 +932,7 @@ void dlm_create_debug_file(struct dlm_ls *ls)
	snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_waiters", ls->ls_name);

	ls->ls_debug_waiters_dentry = debugfs_create_file(name,
							  S_IFREG | S_IRUGO,
							  0644,
							  dlm_root,
							  ls,
							  &waiters_fops);
+1 −2
Original line number Diff line number Diff line
@@ -84,8 +84,7 @@ int dlm_recover_directory(struct dlm_ls *ls)

		for (;;) {
			int left;
			error = dlm_recovery_stopped(ls);
			if (error) {
			if (dlm_recovery_stopped(ls)) {
				error = -EINTR;
				goto out_free;
			}
+5 −7
Original line number Diff line number Diff line
@@ -41,12 +41,6 @@
#include <linux/dlm.h>
#include "config.h"

/* Size of the temp buffer midcomms allocates on the stack.
   We try to make this large enough so most messages fit.
   FIXME: should sctp make this unnecessary? */

#define DLM_INBUF_LEN		148

struct dlm_ls;
struct dlm_lkb;
struct dlm_rsb;
@@ -554,8 +548,9 @@ struct dlm_ls {
	uint32_t		ls_generation;
	uint32_t		ls_exflags;
	int			ls_lvblen;
	int			ls_count;	/* refcount of processes in
	atomic_t		ls_count;	/* refcount of processes in
						   the dlm using this ls */
	wait_queue_head_t	ls_count_wait;
	int			ls_create_count; /* create/release refcount */
	unsigned long		ls_flags;	/* LSFL_ */
	unsigned long		ls_scan_time;
@@ -581,6 +576,7 @@ struct dlm_ls {
	struct list_head	ls_new_rsb;	/* new rsb structs */

	spinlock_t		ls_remove_spin;
	wait_queue_head_t	ls_remove_wait;
	char			ls_remove_name[DLM_RESNAME_MAXLEN+1];
	char			*ls_remove_names[DLM_REMOVE_NAMES_MAX];
	int			ls_remove_len;
@@ -632,6 +628,8 @@ struct dlm_ls {
	struct rw_semaphore	ls_in_recovery;	/* block local requests */
	struct rw_semaphore	ls_recv_active;	/* block dlm_recv */
	struct list_head	ls_requestqueue;/* queue remote requests */
	atomic_t		ls_requestqueue_cnt;
	wait_queue_head_t	ls_requestqueue_wait;
	struct mutex		ls_requestqueue_mutex;
	struct dlm_rcom		*ls_recover_buf;
	int			ls_recover_nodeid; /* for debugging */
+100 −9
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@
                                   R: do_xxxx()
   L: receive_xxxx_reply()     <-  R: send_xxxx_reply()
*/
#include <trace/events/dlm.h>

#include <linux/types.h>
#include <linux/rbtree.h>
#include <linux/slab.h>
@@ -1178,7 +1180,8 @@ static void detach_lkb(struct dlm_lkb *lkb)
	}
}

static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
static int _create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret,
		       int start, int end)
{
	struct dlm_lkb *lkb;
	int rv;
@@ -1199,7 +1202,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)

	idr_preload(GFP_NOFS);
	spin_lock(&ls->ls_lkbidr_spin);
	rv = idr_alloc(&ls->ls_lkbidr, lkb, 1, 0, GFP_NOWAIT);
	rv = idr_alloc(&ls->ls_lkbidr, lkb, start, end, GFP_NOWAIT);
	if (rv >= 0)
		lkb->lkb_id = rv;
	spin_unlock(&ls->ls_lkbidr_spin);
@@ -1215,6 +1218,11 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
	return 0;
}

static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
{
	return _create_lkb(ls, lkb_ret, 1, 0);
}

static int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret)
{
	struct dlm_lkb *lkb;
@@ -1618,21 +1626,24 @@ static int remove_from_waiters_ms(struct dlm_lkb *lkb, struct dlm_message *ms)
}

/* If there's an rsb for the same resource being removed, ensure
   that the remove message is sent before the new lookup message.
   It should be rare to need a delay here, but if not, then it may
   be worthwhile to add a proper wait mechanism rather than a delay. */
 * that the remove message is sent before the new lookup message.
 */

#define DLM_WAIT_PENDING_COND(ls, r)		\
	(ls->ls_remove_len &&			\
	 !rsb_cmp(r, ls->ls_remove_name,	\
		  ls->ls_remove_len))

static void wait_pending_remove(struct dlm_rsb *r)
{
	struct dlm_ls *ls = r->res_ls;
 restart:
	spin_lock(&ls->ls_remove_spin);
	if (ls->ls_remove_len &&
	    !rsb_cmp(r, ls->ls_remove_name, ls->ls_remove_len)) {
	if (DLM_WAIT_PENDING_COND(ls, r)) {
		log_debug(ls, "delay lookup for remove dir %d %s",
			  r->res_dir_nodeid, r->res_name);
		spin_unlock(&ls->ls_remove_spin);
		msleep(1);
		wait_event(ls->ls_remove_wait, !DLM_WAIT_PENDING_COND(ls, r));
		goto restart;
	}
	spin_unlock(&ls->ls_remove_spin);
@@ -1784,6 +1795,7 @@ static void shrink_bucket(struct dlm_ls *ls, int b)
		memcpy(ls->ls_remove_name, name, DLM_RESNAME_MAXLEN);
		spin_unlock(&ls->ls_remove_spin);
		spin_unlock(&ls->ls_rsbtbl[b].lock);
		wake_up(&ls->ls_remove_wait);

		send_remove(r);

@@ -3437,6 +3449,8 @@ int dlm_lock(dlm_lockspace_t *lockspace,
	if (error)
		goto out;

	trace_dlm_lock_start(ls, lkb, mode, flags);

	error = set_lock_args(mode, lksb, flags, namelen, 0, ast,
			      astarg, bast, &args);
	if (error)
@@ -3450,6 +3464,8 @@ int dlm_lock(dlm_lockspace_t *lockspace,
	if (error == -EINPROGRESS)
		error = 0;
 out_put:
	trace_dlm_lock_end(ls, lkb, mode, flags, error);

	if (convert || error)
		__put_lkb(ls, lkb);
	if (error == -EAGAIN || error == -EDEADLK)
@@ -3481,6 +3497,8 @@ int dlm_unlock(dlm_lockspace_t *lockspace,
	if (error)
		goto out;

	trace_dlm_unlock_start(ls, lkb, flags);

	error = set_unlock_args(flags, astarg, &args);
	if (error)
		goto out_put;
@@ -3495,6 +3513,8 @@ int dlm_unlock(dlm_lockspace_t *lockspace,
	if (error == -EBUSY && (flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)))
		error = 0;
 out_put:
	trace_dlm_unlock_end(ls, lkb, flags, error);

	dlm_put_lkb(lkb);
 out:
	dlm_unlock_recovery(ls);
@@ -3973,6 +3993,14 @@ static int validate_message(struct dlm_lkb *lkb, struct dlm_message *ms)
	int from = ms->m_header.h_nodeid;
	int error = 0;

	/* currently mixing of user/kernel locks are not supported */
	if (ms->m_flags & DLM_IFL_USER && ~lkb->lkb_flags & DLM_IFL_USER) {
		log_error(lkb->lkb_resource->res_ls,
			  "got user dlm message for a kernel lock");
		error = -EINVAL;
		goto out;
	}

	switch (ms->m_type) {
	case DLM_MSG_CONVERT:
	case DLM_MSG_UNLOCK:
@@ -4001,6 +4029,7 @@ static int validate_message(struct dlm_lkb *lkb, struct dlm_message *ms)
		error = -EINVAL;
	}

out:
	if (error)
		log_error(lkb->lkb_resource->res_ls,
			  "ignore invalid message %d from %d %x %x %x %d",
@@ -4050,6 +4079,7 @@ static void send_repeat_remove(struct dlm_ls *ls, char *ms_name, int len)
	memcpy(ls->ls_remove_name, name, DLM_RESNAME_MAXLEN);
	spin_unlock(&ls->ls_remove_spin);
	spin_unlock(&ls->ls_rsbtbl[b].lock);
	wake_up(&ls->ls_remove_wait);

	rv = _create_message(ls, sizeof(struct dlm_message) + len,
			     dir_nodeid, DLM_MSG_REMOVE, &ms, &mh);
@@ -6301,3 +6331,64 @@ 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;
}

int dlm_debug_add_lkb_to_waiters(struct dlm_ls *ls, uint32_t lkb_id,
				 int mstype, int to_nodeid)
{
	struct dlm_lkb *lkb;
	int error;

	error = find_lkb(ls, lkb_id, &lkb);
	if (error)
		return error;

	error = add_to_waiters(lkb, mstype, to_nodeid);
	dlm_put_lkb(lkb);
	return error;
}
Loading