Commit 659b3613 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dlm-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm

Pull dlm updates from David Teigland:

 - Allow blocking posix lock requests to be interrupted while waiting.
   This requires a cancel request to be sent to the userspace daemon
   where posix lock requests are processed across the cluster.

 - Fix a posix lock patch from the previous cycle in which lock requests
   from different file systems could be mixed up.

 - Fix some long standing problems with nfs posix lock cancelation.

 - Add a new debugfs file for printing queued callbacks.

 - Stop modifying buffers that have been used to receive a message.

 - Misc cleanups and some refactoring.

* tag 'dlm-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm:
  dlm: fix plock lookup when using multiple lockspaces
  fs: dlm: don't use RCOM_NAMES for version detection
  fs: dlm: create midcomms nodes when configure
  fs: dlm: constify receive buffer
  fs: dlm: drop rxbuf manipulation in dlm_recover_master_copy
  fs: dlm: drop rxbuf manipulation in dlm_copy_master_names
  fs: dlm: get recovery sequence number as parameter
  fs: dlm: cleanup lock order
  fs: dlm: remove clear_members_cb
  fs: dlm: add plock dev tracepoints
  fs: dlm: check on plock ops when exit dlm
  fs: dlm: debugfs for queued callbacks
  fs: dlm: remove unused processed_nodes
  fs: dlm: add missing spin_unlock
  fs: dlm: fix F_CANCELLK to cancel pending request
  fs: dlm: allow to F_SETLKW getting interrupted
  fs: dlm: remove twice newline
parents e7e9423d 7c53e847
......@@ -664,7 +664,7 @@ static ssize_t comm_addr_store(struct config_item *item, const char *buf,
memcpy(addr, buf, len);
rv = dlm_lowcomms_addr(cm->nodeid, addr, len);
rv = dlm_midcomms_addr(cm->nodeid, addr, len);
if (rv) {
kfree(addr);
return rv;
......
......@@ -18,6 +18,7 @@
#include "dlm_internal.h"
#include "midcomms.h"
#include "lock.h"
#include "ast.h"
#define DLM_DEBUG_BUF_LEN 4096
static char debug_buf[DLM_DEBUG_BUF_LEN];
......@@ -365,6 +366,52 @@ static void print_format4(struct dlm_rsb *r, struct seq_file *s)
unlock_rsb(r);
}
static void print_format5_lock(struct seq_file *s, struct dlm_lkb *lkb)
{
struct dlm_callback *cb;
/* lkb_id lkb_flags mode flags sb_status sb_flags */
spin_lock(&lkb->lkb_cb_lock);
list_for_each_entry(cb, &lkb->lkb_callbacks, list) {
seq_printf(s, "%x %x %d %x %d %x\n",
lkb->lkb_id,
dlm_iflags_val(lkb),
cb->mode,
cb->flags,
cb->sb_status,
cb->sb_flags);
}
spin_unlock(&lkb->lkb_cb_lock);
}
static void print_format5(struct dlm_rsb *r, struct seq_file *s)
{
struct dlm_lkb *lkb;
lock_rsb(r);
list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) {
print_format5_lock(s, lkb);
if (seq_has_overflowed(s))
goto out;
}
list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
print_format5_lock(s, lkb);
if (seq_has_overflowed(s))
goto out;
}
list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) {
print_format5_lock(s, lkb);
if (seq_has_overflowed(s))
goto out;
}
out:
unlock_rsb(r);
}
struct rsbtbl_iter {
struct dlm_rsb *rsb;
unsigned bucket;
......@@ -408,6 +455,13 @@ static int table_seq_show(struct seq_file *seq, void *iter_ptr)
}
print_format4(ri->rsb, seq);
break;
case 5:
if (ri->header) {
seq_puts(seq, "lkb_id lkb_flags mode flags sb_status sb_flags\n");
ri->header = 0;
}
print_format5(ri->rsb, seq);
break;
}
return 0;
......@@ -417,6 +471,7 @@ static const struct seq_operations format1_seq_ops;
static const struct seq_operations format2_seq_ops;
static const struct seq_operations format3_seq_ops;
static const struct seq_operations format4_seq_ops;
static const struct seq_operations format5_seq_ops;
static void *table_seq_start(struct seq_file *seq, loff_t *pos)
{
......@@ -448,6 +503,8 @@ static void *table_seq_start(struct seq_file *seq, loff_t *pos)
ri->format = 3;
if (seq->op == &format4_seq_ops)
ri->format = 4;
if (seq->op == &format5_seq_ops)
ri->format = 5;
tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
......@@ -602,10 +659,18 @@ static const struct seq_operations format4_seq_ops = {
.show = table_seq_show,
};
static const struct seq_operations format5_seq_ops = {
.start = table_seq_start,
.next = table_seq_next,
.stop = table_seq_stop,
.show = table_seq_show,
};
static const struct file_operations format1_fops;
static const struct file_operations format2_fops;
static const struct file_operations format3_fops;
static const struct file_operations format4_fops;
static const struct file_operations format5_fops;
static int table_open1(struct inode *inode, struct file *file)
{
......@@ -683,7 +748,21 @@ static int table_open4(struct inode *inode, struct file *file)
struct seq_file *seq;
int ret;
ret = seq_open(file, &format4_seq_ops);
ret = seq_open(file, &format5_seq_ops);
if (ret)
return ret;
seq = file->private_data;
seq->private = inode->i_private; /* the dlm_ls */
return 0;
}
static int table_open5(struct inode *inode, struct file *file)
{
struct seq_file *seq;
int ret;
ret = seq_open(file, &format5_seq_ops);
if (ret)
return ret;
......@@ -725,6 +804,14 @@ static const struct file_operations format4_fops = {
.release = seq_release
};
static const struct file_operations format5_fops = {
.owner = THIS_MODULE,
.open = table_open5,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release
};
/*
* dump lkb's on the ls_waiters list
*/
......@@ -793,6 +880,7 @@ void dlm_delete_debug_file(struct dlm_ls *ls)
debugfs_remove(ls->ls_debug_locks_dentry);
debugfs_remove(ls->ls_debug_all_dentry);
debugfs_remove(ls->ls_debug_toss_dentry);
debugfs_remove(ls->ls_debug_queued_asts_dentry);
}
static int dlm_state_show(struct seq_file *file, void *offset)
......@@ -936,6 +1024,17 @@ void dlm_create_debug_file(struct dlm_ls *ls)
dlm_root,
ls,
&waiters_fops);
/* format 5 */
memset(name, 0, sizeof(name));
snprintf(name, DLM_LOCKSPACE_LEN + 8, "%s_queued_asts", ls->ls_name);
ls->ls_debug_queued_asts_dentry = debugfs_create_file(name,
0644,
dlm_root,
ls,
&format5_fops);
}
void __init dlm_register_debugfs(void)
......
......@@ -58,7 +58,7 @@ void dlm_recover_dir_nodeid(struct dlm_ls *ls)
up_read(&ls->ls_root_sem);
}
int dlm_recover_directory(struct dlm_ls *ls)
int dlm_recover_directory(struct dlm_ls *ls, uint64_t seq)
{
struct dlm_member *memb;
char *b, *last_name = NULL;
......@@ -90,7 +90,7 @@ int dlm_recover_directory(struct dlm_ls *ls)
}
error = dlm_rcom_names(ls, memb->nodeid,
last_name, last_len);
last_name, last_len, seq);
if (error)
goto out_free;
......@@ -196,7 +196,8 @@ int dlm_recover_directory(struct dlm_ls *ls)
return error;
}
static struct dlm_rsb *find_rsb_root(struct dlm_ls *ls, char *name, int len)
static struct dlm_rsb *find_rsb_root(struct dlm_ls *ls, const char *name,
int len)
{
struct dlm_rsb *r;
uint32_t hash, bucket;
......@@ -232,7 +233,7 @@ static struct dlm_rsb *find_rsb_root(struct dlm_ls *ls, char *name, int len)
for rsb's we're master of and whose directory node matches the requesting
node. inbuf is the rsb name last sent, inlen is the name's length */
void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
void dlm_copy_master_names(struct dlm_ls *ls, const char *inbuf, int inlen,
char *outbuf, int outlen, int nodeid)
{
struct list_head *list;
......@@ -245,9 +246,8 @@ void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
if (inlen > 1) {
r = find_rsb_root(ls, inbuf, inlen);
if (!r) {
inbuf[inlen - 1] = '\0';
log_error(ls, "copy_master_names from %d start %d %s",
nodeid, inlen, inbuf);
log_error(ls, "copy_master_names from %d start %d %.*s",
nodeid, inlen, inlen, inbuf);
goto out;
}
list = r->res_root_list.next;
......
......@@ -15,9 +15,9 @@
int dlm_dir_nodeid(struct dlm_rsb *rsb);
int dlm_hash2nodeid(struct dlm_ls *ls, uint32_t hash);
void dlm_recover_dir_nodeid(struct dlm_ls *ls);
int dlm_recover_directory(struct dlm_ls *ls);
void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
char *outbuf, int outlen, int nodeid);
int dlm_recover_directory(struct dlm_ls *ls, uint64_t seq);
void dlm_copy_master_names(struct dlm_ls *ls, const char *inbuf, int inlen,
char *outbuf, int outlen, int nodeid);
#endif /* __DIR_DOT_H__ */
......@@ -598,6 +598,7 @@ struct dlm_ls {
struct dentry *ls_debug_locks_dentry; /* debugfs */
struct dentry *ls_debug_all_dentry; /* debugfs */
struct dentry *ls_debug_toss_dentry; /* debugfs */
struct dentry *ls_debug_queued_asts_dentry; /* debugfs */
wait_queue_head_t ls_uevent_wait; /* user part of join/leave */
int ls_uevent_result;
......
This diff is collapsed.
......@@ -12,11 +12,11 @@
#define __LOCK_DOT_H__
void dlm_dump_rsb(struct dlm_rsb *r);
void dlm_dump_rsb_name(struct dlm_ls *ls, char *name, int len);
void dlm_dump_rsb_name(struct dlm_ls *ls, const char *name, int len);
void dlm_print_lkb(struct dlm_lkb *lkb);
void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms,
void dlm_receive_message_saved(struct dlm_ls *ls, const struct dlm_message *ms,
uint32_t saved_seq);
void dlm_receive_buffer(union dlm_packet *p, int nodeid);
void dlm_receive_buffer(const union dlm_packet *p, int nodeid);
int dlm_modes_compat(int mode1, int mode2);
void dlm_put_rsb(struct dlm_rsb *r);
void dlm_hold_rsb(struct dlm_rsb *r);
......@@ -25,8 +25,8 @@ void dlm_scan_rsbs(struct dlm_ls *ls);
int dlm_lock_recovery_try(struct dlm_ls *ls);
void dlm_unlock_recovery(struct dlm_ls *ls);
int dlm_master_lookup(struct dlm_ls *ls, int nodeid, char *name, int len,
unsigned int flags, int *r_nodeid, int *result);
int dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *name,
int len, unsigned int flags, int *r_nodeid, int *result);
int dlm_search_rsb_tree(struct rb_root *tree, const void *name, int len,
struct dlm_rsb **r_ret);
......@@ -36,8 +36,10 @@ void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
void dlm_recover_grant(struct dlm_ls *ls);
int dlm_recover_waiters_post(struct dlm_ls *ls);
void dlm_recover_waiters_pre(struct dlm_ls *ls);
int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
int dlm_recover_master_copy(struct dlm_ls *ls, const struct dlm_rcom *rc,
__le32 *rl_remid, __le32 *rl_result);
int dlm_recover_process_copy(struct dlm_ls *ls, const struct dlm_rcom *rc,
uint64_t seq);
int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode,
uint32_t flags, void *name, unsigned int namelen);
......
......@@ -863,7 +863,6 @@ struct dlm_processed_nodes {
static void process_dlm_messages(struct work_struct *work)
{
struct processqueue_entry *pentry;
LIST_HEAD(processed_nodes);
spin_lock(&processqueue_lock);
pentry = list_first_entry_or_null(&processqueue,
......
......@@ -18,7 +18,7 @@
#include "midcomms.h"
#include "lowcomms.h"
int dlm_slots_version(struct dlm_header *h)
int dlm_slots_version(const struct dlm_header *h)
{
if ((le32_to_cpu(h->h_version) & 0x0000FFFF) < DLM_HEADER_SLOTS)
return 0;
......@@ -393,14 +393,9 @@ static void remove_remote_member(int nodeid)
dlm_midcomms_remove_member(nodeid);
}
static void clear_members_cb(int nodeid)
{
remove_remote_member(nodeid);
}
void dlm_clear_members(struct dlm_ls *ls)
{
clear_memb_list(&ls->ls_nodes, clear_members_cb);
clear_memb_list(&ls->ls_nodes, remove_remote_member);
ls->ls_num_nodes = 0;
}
......@@ -454,7 +449,7 @@ static void make_member_array(struct dlm_ls *ls)
/* send a status request to all members just to establish comms connections */
static int ping_members(struct dlm_ls *ls)
static int ping_members(struct dlm_ls *ls, uint64_t seq)
{
struct dlm_member *memb;
int error = 0;
......@@ -464,7 +459,7 @@ static int ping_members(struct dlm_ls *ls)
error = -EINTR;
break;
}
error = dlm_rcom_status(ls, memb->nodeid, 0);
error = dlm_rcom_status(ls, memb->nodeid, 0, seq);
if (error)
break;
}
......@@ -612,7 +607,7 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
make_member_array(ls);
*neg_out = neg;
error = ping_members(ls);
error = ping_members(ls, rv->seq);
log_rinfo(ls, "dlm_recover_members %d nodes", ls->ls_num_nodes);
return error;
}
......
......@@ -18,7 +18,7 @@ void dlm_clear_members_gone(struct dlm_ls *ls);
int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv,int *neg_out);
int dlm_is_removed(struct dlm_ls *ls, int nodeid);
int dlm_is_member(struct dlm_ls *ls, int nodeid);
int dlm_slots_version(struct dlm_header *h);
int dlm_slots_version(const struct dlm_header *h);
void dlm_slot_save(struct dlm_ls *ls, struct dlm_rcom *rc,
struct dlm_member *memb);
void dlm_slots_copy_out(struct dlm_ls *ls, struct dlm_rcom *rc);
......
This diff is collapsed.
......@@ -20,6 +20,7 @@ struct dlm_mhandle *dlm_midcomms_get_mhandle(int nodeid, int len,
gfp_t allocation, char **ppc);
void dlm_midcomms_commit_mhandle(struct dlm_mhandle *mh, const void *name,
int namelen);
int dlm_midcomms_addr(int nodeid, struct sockaddr_storage *addr, int len);
void dlm_midcomms_version_wait(void);
int dlm_midcomms_close(int nodeid);
int dlm_midcomms_start(void);
......
......@@ -11,6 +11,8 @@
#include <linux/dlm_plock.h>
#include <linux/slab.h>
#include <trace/events/dlm.h>
#include "dlm_internal.h"
#include "lockspace.h"
......@@ -42,6 +44,27 @@ static inline void set_version(struct dlm_plock_info *info)
info->version[2] = DLM_PLOCK_VERSION_PATCH;
}
static struct plock_op *plock_lookup_waiter(const struct dlm_plock_info *info)
{
struct plock_op *op = NULL, *iter;
list_for_each_entry(iter, &recv_list, list) {
if (iter->info.fsid == info->fsid &&
iter->info.number == info->number &&
iter->info.owner == info->owner &&
iter->info.pid == info->pid &&
iter->info.start == info->start &&
iter->info.end == info->end &&
iter->info.ex == info->ex &&
iter->info.wait) {
op = iter;
break;
}
}
return op;
}
static int check_version(struct dlm_plock_info *info)
{
if ((DLM_PLOCK_VERSION_MAJOR != info->version[0]) ||
......@@ -74,30 +97,26 @@ static void send_op(struct plock_op *op)
wake_up(&send_wq);
}
/* If a process was killed while waiting for the only plock on a file,
locks_remove_posix will not see any lock on the file so it won't
send an unlock-close to us to pass on to userspace to clean up the
abandoned waiter. So, we have to insert the unlock-close when the
lock call is interrupted. */
static void do_unlock_close(const struct dlm_plock_info *info)
static int do_lock_cancel(const struct dlm_plock_info *orig_info)
{
struct plock_op *op;
int rv;
op = kzalloc(sizeof(*op), GFP_NOFS);
if (!op)
return;
return -ENOMEM;
op->info = *orig_info;
op->info.optype = DLM_PLOCK_OP_CANCEL;
op->info.wait = 0;
op->info.optype = DLM_PLOCK_OP_UNLOCK;
op->info.pid = info->pid;
op->info.fsid = info->fsid;
op->info.number = info->number;
op->info.start = 0;
op->info.end = OFFSET_MAX;
op->info.owner = info->owner;
op->info.flags |= DLM_PLOCK_FL_CLOSE;
send_op(op);
wait_event(recv_wq, (op->done != 0));
rv = op->info.rv;
dlm_release_plock_op(op);
return rv;
}
int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
......@@ -156,7 +175,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
send_op(op);
if (op->info.wait) {
rv = wait_event_killable(recv_wq, (op->done != 0));
rv = wait_event_interruptible(recv_wq, (op->done != 0));
if (rv == -ERESTARTSYS) {
spin_lock(&ops_lock);
/* recheck under ops_lock if we got a done != 0,
......@@ -166,17 +185,37 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
spin_unlock(&ops_lock);
goto do_lock_wait;
}
list_del(&op->list);
spin_unlock(&ops_lock);
rv = do_lock_cancel(&op->info);
switch (rv) {
case 0:
/* waiter was deleted in user space, answer will never come
* remove original request. The original request must be
* on recv_list because the answer of do_lock_cancel()
* synchronized it.
*/
spin_lock(&ops_lock);
list_del(&op->list);
spin_unlock(&ops_lock);
rv = -EINTR;
break;
case -ENOENT:
/* cancellation wasn't successful but op should be done */
fallthrough;
default:
/* internal error doing cancel we need to wait */
goto wait;
}
log_debug(ls, "%s: wait interrupted %x %llx pid %d",
__func__, ls->ls_global_id,
(unsigned long long)number, op->info.pid);
do_unlock_close(&op->info);
dlm_release_plock_op(op);
goto out;
}
} else {
wait:
wait_event(recv_wq, (op->done != 0));
}
......@@ -240,8 +279,8 @@ static int dlm_plock_callback(struct plock_op *op)
rv = notify(fl, 0);
if (rv) {
/* XXX: We need to cancel the fs lock here: */
log_print("dlm_plock_callback: lock granted after lock request "
"failed; dangling lock!\n");
log_print("%s: lock granted after lock request failed; dangling lock!",
__func__);
goto out;
}
......@@ -318,6 +357,75 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
}
EXPORT_SYMBOL_GPL(dlm_posix_unlock);
/*
* NOTE: This implementation can only handle async lock requests as nfs
* do it. It cannot handle cancellation of a pending lock request sitting
* in wait_event(), but for now only nfs is the only user local kernel
* user.
*/
int dlm_posix_cancel(dlm_lockspace_t *lockspace, u64 number, struct file *file,
struct file_lock *fl)
{
struct dlm_plock_info info;
struct plock_op *op;
struct dlm_ls *ls;
int rv;
/* this only works for async request for now and nfs is the only
* kernel user right now.
*/
if (WARN_ON_ONCE(!fl->fl_lmops || !fl->fl_lmops->lm_grant))
return -EOPNOTSUPP;
ls = dlm_find_lockspace_local(lockspace);
if (!ls)
return -EINVAL;
memset(&info, 0, sizeof(info));
info.pid = fl->fl_pid;
info.ex = (fl->fl_type == F_WRLCK);
info.fsid = ls->ls_global_id;
dlm_put_lockspace(ls);
info.number = number;
info.start = fl->fl_start;
info.end = fl->fl_end;
info.owner = (__u64)fl->fl_pid;
rv = do_lock_cancel(&info);
switch (rv) {
case 0:
spin_lock(&ops_lock);
/* lock request to cancel must be on recv_list because
* do_lock_cancel() synchronizes it.
*/
op = plock_lookup_waiter(&info);
if (WARN_ON_ONCE(!op)) {
spin_unlock(&ops_lock);
rv = -ENOLCK;
break;
}
list_del(&op->list);
spin_unlock(&ops_lock);
WARN_ON(op->info.optype != DLM_PLOCK_OP_LOCK);
op->data->callback(op->data->fl, -EINTR);
dlm_release_plock_op(op);
rv = -EINTR;
break;
case -ENOENT:
/* if cancel wasn't successful we probably were to late
* or it was a non-blocking lock request, so just unlock it.
*/
rv = dlm_posix_unlock(lockspace, number, file, fl);
break;
default:
break;
}
return rv;
}
EXPORT_SYMBOL_GPL(dlm_posix_cancel);
int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
struct file_lock *fl)
{
......@@ -403,6 +511,8 @@ static ssize_t dev_read(struct file *file, char __user *u, size_t count,
if (!op)
return -EAGAIN;
trace_dlm_plock_read(&info);
/* there is no need to get a reply from userspace for unlocks
that were generated by the vfs cleaning up for a close
(the process did not make an unlock call). */
......@@ -430,6 +540,8 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
if (copy_from_user(&info, u, sizeof(info)))
return -EFAULT;
trace_dlm_plock_write(&info);
if (check_version(&info))
return -EINVAL;
......@@ -441,22 +553,11 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
*/
spin_lock(&ops_lock);
if (info.wait) {
list_for_each_entry(iter, &recv_list, list) {
if (iter->info.fsid == info.fsid &&
iter->info.number == info.number &&
iter->info.owner == info.owner &&
iter->info.pid == info.pid &&
iter->info.start == info.start &&
iter->info.end == info.end &&
iter->info.ex == info.ex &&
iter->info.wait) {
op = iter;
break;
}
}
op = plock_lookup_waiter(&info);
} else {
list_for_each_entry(iter, &recv_list, list) {
if (!iter->info.wait) {
if (!iter->info.wait &&
iter->info.fsid == info.fsid) {
op = iter;
break;
}
......@@ -468,8 +569,7 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
if (info.wait)
WARN_ON(op->info.optype != DLM_PLOCK_OP_LOCK);
else
WARN_ON(op->info.fsid != info.fsid ||
op->info.number != info.number ||
WARN_ON(op->info.number != info.number ||
op->info.owner != info.owner ||
op->info.optype != info.optype);
......@@ -534,5 +634,7 @@ int dlm_plock_init(void)
void dlm_plock_exit(void)
{
misc_deregister(&plock_dev_misc);
WARN_ON(!list_empty(&send_list));
WARN_ON(!list_empty(&recv_list));
}
This diff is collapsed.
......@@ -12,12 +12,15 @@
#ifndef __RCOM_DOT_H__
#define __RCOM_DOT_H__
int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags);
int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,int last_len);
int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid);
int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid);
int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in);
int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags,
uint64_t seq);
int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name,
int last_len, uint64_t seq);
int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid, uint64_t seq);
int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, uint64_t seq);
void dlm_receive_rcom(struct dlm_ls *ls, const struct dlm_rcom *rc,
int nodeid);
int dlm_send_ls_not_ready(int nodeid, const struct dlm_rcom *rc_in);
#endif
......@@ -93,7 +93,7 @@ void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status)
}
static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status,
int save_slots)
int save_slots, uint64_t seq)
{
struct dlm_rcom *rc = ls->ls_recover_buf;
struct dlm_member *memb;
......@@ -107,7 +107,7 @@ static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status,
goto out;
}
error = dlm_rcom_status(ls, memb->nodeid, 0);
error = dlm_rcom_status(ls, memb->nodeid, 0, seq);
if (error)
goto out;
......@@ -126,7 +126,7 @@ static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status,
}
static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status,
uint32_t status_flags)
uint32_t status_flags, uint64_t seq)
{
struct dlm_rcom *rc = ls->ls_recover_buf;
int error = 0, delay = 0, nodeid = ls->ls_low_nodeid;
......@@ -137,7 +137,7 @@ static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status,
goto out;
}
error = dlm_rcom_status(ls, nodeid, status_flags);
error = dlm_rcom_status(ls, nodeid, status_flags, seq);
if (error)
break;
......@@ -151,22 +151,22 @@ static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status,
return error;
}
static int wait_status(struct dlm_ls *ls, uint32_t status)
static int wait_status(struct dlm_ls *ls, uint32_t status, uint64_t seq)
{
uint32_t status_all = status << 1;
int error;
if (ls->ls_low_nodeid == dlm_our_nodeid()) {
error = wait_status_all(ls, status, 0);
error = wait_status_all(ls, status, 0, seq);
if (!error)
dlm_set_recover_status(ls, status_all);
} else
error = wait_status_low(ls, status_all, 0);
error = wait_status_low(ls, status_all, 0, seq);
return error;
}
int dlm_recover_members_wait(struct dlm_ls *ls)
int dlm_recover_members_wait(struct dlm_ls *ls, uint64_t seq)
{
struct dlm_member *memb;
struct dlm_slot *slots;
......@@ -180,7 +180,7 @@ int dlm_recover_members_wait(struct dlm_ls *ls)
}
if (ls->ls_low_nodeid == dlm_our_nodeid()) {
error = wait_status_all(ls, DLM_RS_NODES, 1);
error = wait_status_all(ls, DLM_RS_NODES, 1, seq);
if (error)
goto out;
......@@ -199,7 +199,8 @@ int dlm_recover_members_wait(struct dlm_ls *ls)
dlm_set_recover_status(ls, DLM_RS_NODES_ALL);
}
} else {
error = wait_status_low(ls, DLM_RS_NODES_ALL, DLM_RSF_NEED_SLOTS);
error = wait_status_low(ls, DLM_RS_NODES_ALL,
DLM_RSF_NEED_SLOTS, seq);
if (error)
goto out;
......@@ -209,19 +210,19 @@ int dlm_recover_members_wait(struct dlm_ls *ls)
return error;
}
int dlm_recover_directory_wait(struct dlm_ls *ls)
int dlm_recover_directory_wait(struct dlm_ls *ls, uint64_t seq)
{
return wait_status(ls, DLM_RS_DIR);
return wait_status(ls, DLM_RS_DIR, seq);
}
int dlm_recover_locks_wait(struct dlm_ls *ls)
int dlm_recover_locks_wait(struct dlm_ls *ls, uint64_t seq)
{
return wait_status(ls, DLM_RS_LOCKS);
return wait_status(ls, DLM_RS_LOCKS, seq);
}
int dlm_recover_done_wait(struct dlm_ls *ls)
int dlm_recover_done_wait(struct dlm_ls *ls, uint64_t seq)
{
return wait_status(ls, DLM_RS_DONE);
return wait_status(ls, DLM_RS_DONE, seq);
}
/*
......@@ -441,7 +442,7 @@ static void set_new_master(struct dlm_rsb *r)
* equals our_nodeid below).
*/
static int recover_master(struct dlm_rsb *r, unsigned int *count)
static int recover_master(struct dlm_rsb *r, unsigned int *count, uint64_t seq)
{
struct dlm_ls *ls = r->res_ls;
int our_nodeid, dir_nodeid;
......@@ -472,7 +473,7 @@ static int recover_master(struct dlm_rsb *r, unsigned int *count)
error = 0;
} else {
recover_idr_add(r);
error = dlm_send_rcom_lookup(r, dir_nodeid);
error = dlm_send_rcom_lookup(r, dir_nodeid, seq);
}
(*count)++;
......@@ -520,7 +521,7 @@ static int recover_master_static(struct dlm_rsb *r, unsigned int *count)
* the correct dir node.
*/
int dlm_recover_masters(struct dlm_ls *ls)
int dlm_recover_masters(struct dlm_ls *ls, uint64_t seq)
{
struct dlm_rsb *r;
unsigned int total = 0;
......@@ -542,7 +543,7 @@ int dlm_recover_masters(struct dlm_ls *ls)
if (nodir)
error = recover_master_static(r, &count);
else
error = recover_master(r, &count);
error = recover_master(r, &count, seq);
unlock_rsb(r);
cond_resched();
total++;
......@@ -563,7 +564,7 @@ int dlm_recover_masters(struct dlm_ls *ls)
return error;
}
int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
int dlm_recover_master_reply(struct dlm_ls *ls, const struct dlm_rcom *rc)
{
struct dlm_rsb *r;
int ret_nodeid, new_master;
......@@ -614,13 +615,14 @@ int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
* an equal number of replies then recovery for the rsb is done
*/
static int recover_locks_queue(struct dlm_rsb *r, struct list_head *head)
static int recover_locks_queue(struct dlm_rsb *r, struct list_head *head,
uint64_t seq)
{
struct dlm_lkb *lkb;
int error = 0;
list_for_each_entry(lkb, head, lkb_statequeue) {
error = dlm_send_rcom_lock(r, lkb);
error = dlm_send_rcom_lock(r, lkb, seq);
if (error)
break;
r->res_recover_locks_count++;
......@@ -629,7 +631,7 @@ static int recover_locks_queue(struct dlm_rsb *r, struct list_head *head)
return error;
}
static int recover_locks(struct dlm_rsb *r)
static int recover_locks(struct dlm_rsb *r, uint64_t seq)
{
int error = 0;
......@@ -637,13 +639,13 @@ static int recover_locks(struct dlm_rsb *r)
DLM_ASSERT(!r->res_recover_locks_count, dlm_dump_rsb(r););
error = recover_locks_queue(r, &r->res_grantqueue);
error = recover_locks_queue(r, &r->res_grantqueue, seq);
if (error)
goto out;
error = recover_locks_queue(r, &r->res_convertqueue);
error = recover_locks_queue(r, &r->res_convertqueue, seq);
if (error)
goto out;
error = recover_locks_queue(r, &r->res_waitqueue);
error = recover_locks_queue(r, &r->res_waitqueue, seq);
if (error)
goto out;
......@@ -656,7 +658,7 @@ static int recover_locks(struct dlm_rsb *r)
return error;
}
int dlm_recover_locks(struct dlm_ls *ls)
int dlm_recover_locks(struct dlm_ls *ls, uint64_t seq)
{
struct dlm_rsb *r;
int error, count = 0;
......@@ -677,7 +679,7 @@ int dlm_recover_locks(struct dlm_ls *ls)
goto out;
}
error = recover_locks(r);
error = recover_locks(r, seq);
if (error) {
up_read(&ls->ls_root_sem);
goto out;
......
......@@ -15,13 +15,13 @@
int dlm_wait_function(struct dlm_ls *ls, int (*testfn) (struct dlm_ls *ls));
uint32_t dlm_recover_status(struct dlm_ls *ls);
void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status);
int dlm_recover_members_wait(struct dlm_ls *ls);
int dlm_recover_directory_wait(struct dlm_ls *ls);
int dlm_recover_locks_wait(struct dlm_ls *ls);
int dlm_recover_done_wait(struct dlm_ls *ls);
int dlm_recover_masters(struct dlm_ls *ls);
int dlm_recover_master_reply(struct dlm_ls *ls, struct dlm_rcom *rc);
int dlm_recover_locks(struct dlm_ls *ls);
int dlm_recover_members_wait(struct dlm_ls *ls, uint64_t seq);
int dlm_recover_directory_wait(struct dlm_ls *ls, uint64_t seq);
int dlm_recover_locks_wait(struct dlm_ls *ls, uint64_t seq);
int dlm_recover_done_wait(struct dlm_ls *ls, uint64_t seq);
int dlm_recover_masters(struct dlm_ls *ls, uint64_t seq);
int dlm_recover_master_reply(struct dlm_ls *ls, const struct dlm_rcom *rc);
int dlm_recover_locks(struct dlm_ls *ls, uint64_t seq);
void dlm_recovered_lock(struct dlm_rsb *r);
int dlm_create_root_list(struct dlm_ls *ls);
void dlm_release_root_list(struct dlm_ls *ls);
......
......@@ -90,7 +90,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
dlm_set_recover_status(ls, DLM_RS_NODES);
error = dlm_recover_members_wait(ls);
error = dlm_recover_members_wait(ls, rv->seq);
if (error) {
log_rinfo(ls, "dlm_recover_members_wait error %d", error);
goto fail;
......@@ -103,7 +103,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
* nodes their master rsb names that hash to us.
*/
error = dlm_recover_directory(ls);
error = dlm_recover_directory(ls, rv->seq);
if (error) {
log_rinfo(ls, "dlm_recover_directory error %d", error);
goto fail;
......@@ -111,7 +111,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
dlm_set_recover_status(ls, DLM_RS_DIR);
error = dlm_recover_directory_wait(ls);
error = dlm_recover_directory_wait(ls, rv->seq);
if (error) {
log_rinfo(ls, "dlm_recover_directory_wait error %d", error);
goto fail;
......@@ -145,7 +145,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
* departed nodes.
*/
error = dlm_recover_masters(ls);
error = dlm_recover_masters(ls, rv->seq);
if (error) {
log_rinfo(ls, "dlm_recover_masters error %d", error);
goto fail;
......@@ -155,7 +155,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
* Send our locks on remastered rsb's to the new masters.
*/
error = dlm_recover_locks(ls);
error = dlm_recover_locks(ls, rv->seq);
if (error) {
log_rinfo(ls, "dlm_recover_locks error %d", error);
goto fail;
......@@ -163,7 +163,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
dlm_set_recover_status(ls, DLM_RS_LOCKS);
error = dlm_recover_locks_wait(ls);
error = dlm_recover_locks_wait(ls, rv->seq);
if (error) {
log_rinfo(ls, "dlm_recover_locks_wait error %d", error);
goto fail;
......@@ -187,7 +187,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
*/
dlm_set_recover_status(ls, DLM_RS_LOCKS);
error = dlm_recover_locks_wait(ls);
error = dlm_recover_locks_wait(ls, rv->seq);
if (error) {
log_rinfo(ls, "dlm_recover_locks_wait error %d", error);
goto fail;
......@@ -206,7 +206,7 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
dlm_set_recover_status(ls, DLM_RS_DONE);
error = dlm_recover_done_wait(ls);
error = dlm_recover_done_wait(ls, rv->seq);
if (error) {
log_rinfo(ls, "dlm_recover_done_wait error %d", error);
goto fail;
......
......@@ -30,7 +30,8 @@ struct rq_entry {
* lockspace is enabled on some while still suspended on others.
*/
void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms)
void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid,
const struct dlm_message *ms)
{
struct rq_entry *e;
int length = le16_to_cpu(ms->m_header.h_length) -
......
......@@ -11,7 +11,8 @@
#ifndef __REQUESTQUEUE_DOT_H__
#define __REQUESTQUEUE_DOT_H__
void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms);
void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid,
const struct dlm_message *ms);
int dlm_process_requestqueue(struct dlm_ls *ls);
void dlm_wait_requestqueue(struct dlm_ls *ls);
void dlm_purge_requestqueue(struct dlm_ls *ls);
......
......@@ -1436,17 +1436,14 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
if (!(fl->fl_flags & FL_POSIX))
return -ENOLCK;
if (cmd == F_CANCELLK) {
/* Hack: */
cmd = F_SETLK;
fl->fl_type = F_UNLCK;
}
if (unlikely(gfs2_withdrawn(sdp))) {
if (fl->fl_type == F_UNLCK)
locks_lock_file_wait(file, fl);
return -EIO;
}
if (IS_GETLK(cmd))
if (cmd == F_CANCELLK)
return dlm_posix_cancel(ls->ls_dlm, ip->i_no_addr, file, fl);
else if (IS_GETLK(cmd))
return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
else if (fl->fl_type == F_UNLCK)
return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl);
......
......@@ -738,18 +738,11 @@ static int user_plock(struct ocfs2_cluster_connection *conn,
*
* Internally, fs/dlm will pass these to a misc device, which
* a userspace daemon will read and write to.
*
* For now, cancel requests (which happen internally only),
* are turned into unlocks. Most of this function taken from
* gfs2_lock.
*/
if (cmd == F_CANCELLK) {
cmd = F_SETLK;
fl->fl_type = F_UNLCK;
}
if (IS_GETLK(cmd))
if (cmd == F_CANCELLK)
return dlm_posix_cancel(conn->cc_lockspace, ino, file, fl);
else if (IS_GETLK(cmd))
return dlm_posix_get(conn->cc_lockspace, ino, file, fl);
else if (fl->fl_type == F_UNLCK)
return dlm_posix_unlock(conn->cc_lockspace, ino, file, fl);
......
......@@ -11,6 +11,8 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
int cmd, struct file_lock *fl);
int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
struct file_lock *fl);
int dlm_posix_cancel(dlm_lockspace_t *lockspace, u64 number, struct file *file,
struct file_lock *fl);
int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
struct file_lock *fl);
#endif
......@@ -7,6 +7,7 @@
#include <linux/dlm.h>
#include <linux/dlmconstants.h>
#include <uapi/linux/dlm_plock.h>
#include <linux/tracepoint.h>
#include "../../../fs/dlm/dlm_internal.h"
......@@ -585,6 +586,56 @@ TRACE_EVENT(dlm_recv_message,
);
DECLARE_EVENT_CLASS(dlm_plock_template,
TP_PROTO(const struct dlm_plock_info *info),
TP_ARGS(info),
TP_STRUCT__entry(
__field(uint8_t, optype)
__field(uint8_t, ex)
__field(uint8_t, wait)
__field(uint8_t, flags)
__field(uint32_t, pid)
__field(int32_t, nodeid)
__field(int32_t, rv)
__field(uint32_t, fsid)
__field(uint64_t, number)
__field(uint64_t, start)
__field(uint64_t, end)
__field(uint64_t, owner)
),
TP_fast_assign(
__entry->optype = info->optype;
__entry->ex = info->ex;
__entry->wait = info->wait;
__entry->flags = info->flags;
__entry->pid = info->pid;
__entry->nodeid = info->nodeid;
__entry->rv = info->rv;
__entry->fsid = info->fsid;
__entry->number = info->number;
__entry->start = info->start;
__entry->end = info->end;
__entry->owner = info->owner;
),
TP_printk("fsid=%u number=%llx owner=%llx optype=%d ex=%d wait=%d flags=%x pid=%u nodeid=%d rv=%d start=%llx end=%llx",
__entry->fsid, __entry->number, __entry->owner,
__entry->optype, __entry->ex, __entry->wait,
__entry->flags, __entry->pid, __entry->nodeid,
__entry->rv, __entry->start, __entry->end)
);
DEFINE_EVENT(dlm_plock_template, dlm_plock_read,
TP_PROTO(const struct dlm_plock_info *info), TP_ARGS(info));
DEFINE_EVENT(dlm_plock_template, dlm_plock_write,
TP_PROTO(const struct dlm_plock_info *info), TP_ARGS(info));
TRACE_EVENT(dlm_send,
TP_PROTO(int nodeid, int ret),
......
......@@ -22,6 +22,7 @@ enum {
DLM_PLOCK_OP_LOCK = 1,
DLM_PLOCK_OP_UNLOCK,
DLM_PLOCK_OP_GET,
DLM_PLOCK_OP_CANCEL,
};
#define DLM_PLOCK_FL_CLOSE 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment