Commit b5eb9513 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm:
  dlm: add __init and __exit marks to init and exit functions
  dlm: eliminate astparam type casting
  dlm: proper types for asts and basts
  dlm: dlm/user.c input validation fixes
  dlm: fix dlm_dir_lookup() handling of too long names
  dlm: fix overflows when copying from ->m_extra to lvb
  dlm: make find_rsb() fail gracefully when namelen is too large
  dlm: receive_rcom_lock_args() overflow check
  dlm: verify that places expecting rcom_lock have packet long enough
  dlm: validate data in dlm_recover_directory()
  dlm: missing length check in check_config()
  dlm: use proper type for ->ls_recover_buf
  dlm: do not byteswap rcom_config
  dlm: do not byteswap rcom_lock
  dlm: dlm_process_incoming_buffer() fixes
  dlm: use proper C for dlm/requestqueue stuff (and fix alignment bug)
parents dde00137 30727174
...@@ -39,7 +39,6 @@ void dlm_add_ast(struct dlm_lkb *lkb, int type) ...@@ -39,7 +39,6 @@ void dlm_add_ast(struct dlm_lkb *lkb, int type)
dlm_user_add_ast(lkb, type); dlm_user_add_ast(lkb, type);
return; return;
} }
DLM_ASSERT(lkb->lkb_astaddr != DLM_FAKE_USER_AST, dlm_print_lkb(lkb););
spin_lock(&ast_queue_lock); spin_lock(&ast_queue_lock);
if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) { if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
...@@ -58,8 +57,8 @@ static void process_asts(void) ...@@ -58,8 +57,8 @@ static void process_asts(void)
struct dlm_ls *ls = NULL; struct dlm_ls *ls = NULL;
struct dlm_rsb *r = NULL; struct dlm_rsb *r = NULL;
struct dlm_lkb *lkb; struct dlm_lkb *lkb;
void (*cast) (long param); void (*cast) (void *astparam);
void (*bast) (long param, int mode); void (*bast) (void *astparam, int mode);
int type = 0, found, bmode; int type = 0, found, bmode;
for (;;) { for (;;) {
...@@ -83,8 +82,8 @@ static void process_asts(void) ...@@ -83,8 +82,8 @@ static void process_asts(void)
if (!found) if (!found)
break; break;
cast = lkb->lkb_astaddr; cast = lkb->lkb_astfn;
bast = lkb->lkb_bastaddr; bast = lkb->lkb_bastfn;
bmode = lkb->lkb_bastmode; bmode = lkb->lkb_bastmode;
if ((type & AST_COMP) && cast) if ((type & AST_COMP) && cast)
......
...@@ -604,7 +604,7 @@ static struct clusters clusters_root = { ...@@ -604,7 +604,7 @@ static struct clusters clusters_root = {
}, },
}; };
int dlm_config_init(void) int __init dlm_config_init(void)
{ {
config_group_init(&clusters_root.subsys.su_group); config_group_init(&clusters_root.subsys.su_group);
mutex_init(&clusters_root.subsys.su_mutex); mutex_init(&clusters_root.subsys.su_mutex);
......
...@@ -162,14 +162,12 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s) ...@@ -162,14 +162,12 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r) static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r)
{ {
struct dlm_user_args *ua;
unsigned int waiting = 0; unsigned int waiting = 0;
uint64_t xid = 0; uint64_t xid = 0;
if (lkb->lkb_flags & DLM_IFL_USER) { if (lkb->lkb_flags & DLM_IFL_USER) {
ua = (struct dlm_user_args *) lkb->lkb_astparam; if (lkb->lkb_ua)
if (ua) xid = lkb->lkb_ua->xid;
xid = ua->xid;
} }
if (lkb->lkb_timestamp) if (lkb->lkb_timestamp)
...@@ -543,7 +541,7 @@ void dlm_delete_debug_file(struct dlm_ls *ls) ...@@ -543,7 +541,7 @@ void dlm_delete_debug_file(struct dlm_ls *ls)
debugfs_remove(ls->ls_debug_locks_dentry); debugfs_remove(ls->ls_debug_locks_dentry);
} }
int dlm_register_debugfs(void) int __init dlm_register_debugfs(void)
{ {
mutex_init(&debug_buf_lock); mutex_init(&debug_buf_lock);
dlm_root = debugfs_create_dir("dlm", NULL); dlm_root = debugfs_create_dir("dlm", NULL);
......
...@@ -220,6 +220,7 @@ int dlm_recover_directory(struct dlm_ls *ls) ...@@ -220,6 +220,7 @@ int dlm_recover_directory(struct dlm_ls *ls)
last_len = 0; last_len = 0;
for (;;) { for (;;) {
int left;
error = dlm_recovery_stopped(ls); error = dlm_recovery_stopped(ls);
if (error) if (error)
goto out_free; goto out_free;
...@@ -235,12 +236,21 @@ int dlm_recover_directory(struct dlm_ls *ls) ...@@ -235,12 +236,21 @@ int dlm_recover_directory(struct dlm_ls *ls)
* pick namelen/name pairs out of received buffer * pick namelen/name pairs out of received buffer
*/ */
b = ls->ls_recover_buf + sizeof(struct dlm_rcom); b = ls->ls_recover_buf->rc_buf;
left = ls->ls_recover_buf->rc_header.h_length;
left -= sizeof(struct dlm_rcom);
for (;;) { for (;;) {
memcpy(&namelen, b, sizeof(uint16_t)); __be16 v;
namelen = be16_to_cpu(namelen);
b += sizeof(uint16_t); error = -EINVAL;
if (left < sizeof(__be16))
goto out_free;
memcpy(&v, b, sizeof(__be16));
namelen = be16_to_cpu(v);
b += sizeof(__be16);
left -= sizeof(__be16);
/* namelen of 0xFFFFF marks end of names for /* namelen of 0xFFFFF marks end of names for
this node; namelen of 0 marks end of the this node; namelen of 0 marks end of the
...@@ -251,6 +261,12 @@ int dlm_recover_directory(struct dlm_ls *ls) ...@@ -251,6 +261,12 @@ int dlm_recover_directory(struct dlm_ls *ls)
if (!namelen) if (!namelen)
break; break;
if (namelen > left)
goto out_free;
if (namelen > DLM_RESNAME_MAXLEN)
goto out_free;
error = -ENOMEM; error = -ENOMEM;
de = get_free_de(ls, namelen); de = get_free_de(ls, namelen);
if (!de) if (!de)
...@@ -262,6 +278,7 @@ int dlm_recover_directory(struct dlm_ls *ls) ...@@ -262,6 +278,7 @@ int dlm_recover_directory(struct dlm_ls *ls)
memcpy(de->name, b, namelen); memcpy(de->name, b, namelen);
memcpy(last_name, b, namelen); memcpy(last_name, b, namelen);
b += namelen; b += namelen;
left -= namelen;
add_entry_to_hash(ls, de); add_entry_to_hash(ls, de);
count++; count++;
...@@ -302,6 +319,9 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name, ...@@ -302,6 +319,9 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name,
write_unlock(&ls->ls_dirtbl[bucket].lock); write_unlock(&ls->ls_dirtbl[bucket].lock);
if (namelen > DLM_RESNAME_MAXLEN)
return -EINVAL;
de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_KERNEL); de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_KERNEL);
if (!de) if (!de)
return -ENOMEM; return -ENOMEM;
......
...@@ -92,8 +92,6 @@ do { \ ...@@ -92,8 +92,6 @@ do { \
} \ } \
} }
#define DLM_FAKE_USER_AST ERR_PTR(-EINVAL)
struct dlm_direntry { struct dlm_direntry {
struct list_head list; struct list_head list;
...@@ -146,9 +144,9 @@ struct dlm_recover { ...@@ -146,9 +144,9 @@ struct dlm_recover {
struct dlm_args { struct dlm_args {
uint32_t flags; uint32_t flags;
void *astaddr; void (*astfn) (void *astparam);
long astparam; void *astparam;
void *bastaddr; void (*bastfn) (void *astparam, int mode);
int mode; int mode;
struct dlm_lksb *lksb; struct dlm_lksb *lksb;
unsigned long timeout; unsigned long timeout;
...@@ -253,9 +251,12 @@ struct dlm_lkb { ...@@ -253,9 +251,12 @@ struct dlm_lkb {
char *lkb_lvbptr; char *lkb_lvbptr;
struct dlm_lksb *lkb_lksb; /* caller's status block */ struct dlm_lksb *lkb_lksb; /* caller's status block */
void *lkb_astaddr; /* caller's ast function */ void (*lkb_astfn) (void *astparam);
void *lkb_bastaddr; /* caller's bast function */ void (*lkb_bastfn) (void *astparam, int mode);
long lkb_astparam; /* caller's ast arg */ union {
void *lkb_astparam; /* caller's ast arg */
struct dlm_user_args *lkb_ua;
};
}; };
...@@ -403,28 +404,34 @@ struct dlm_rcom { ...@@ -403,28 +404,34 @@ struct dlm_rcom {
char rc_buf[0]; char rc_buf[0];
}; };
union dlm_packet {
struct dlm_header header; /* common to other two */
struct dlm_message message;
struct dlm_rcom rcom;
};
struct rcom_config { struct rcom_config {
uint32_t rf_lvblen; __le32 rf_lvblen;
uint32_t rf_lsflags; __le32 rf_lsflags;
uint64_t rf_unused; __le64 rf_unused;
}; };
struct rcom_lock { struct rcom_lock {
uint32_t rl_ownpid; __le32 rl_ownpid;
uint32_t rl_lkid; __le32 rl_lkid;
uint32_t rl_remid; __le32 rl_remid;
uint32_t rl_parent_lkid; __le32 rl_parent_lkid;
uint32_t rl_parent_remid; __le32 rl_parent_remid;
uint32_t rl_exflags; __le32 rl_exflags;
uint32_t rl_flags; __le32 rl_flags;
uint32_t rl_lvbseq; __le32 rl_lvbseq;
int rl_result; __le32 rl_result;
int8_t rl_rqmode; int8_t rl_rqmode;
int8_t rl_grmode; int8_t rl_grmode;
int8_t rl_status; int8_t rl_status;
int8_t rl_asts; int8_t rl_asts;
uint16_t rl_wait_type; __le16 rl_wait_type;
uint16_t rl_namelen; __le16 rl_namelen;
char rl_name[DLM_RESNAME_MAXLEN]; char rl_name[DLM_RESNAME_MAXLEN];
char rl_lvb[0]; char rl_lvb[0];
}; };
...@@ -494,7 +501,7 @@ struct dlm_ls { ...@@ -494,7 +501,7 @@ struct dlm_ls {
struct rw_semaphore ls_recv_active; /* block dlm_recv */ struct rw_semaphore ls_recv_active; /* block dlm_recv */
struct list_head ls_requestqueue;/* queue remote requests */ struct list_head ls_requestqueue;/* queue remote requests */
struct mutex ls_requestqueue_mutex; struct mutex ls_requestqueue_mutex;
char *ls_recover_buf; struct dlm_rcom *ls_recover_buf;
int ls_recover_nodeid; /* for debugging */ int ls_recover_nodeid; /* for debugging */
uint64_t ls_rcom_seq; uint64_t ls_rcom_seq;
spinlock_t ls_rcom_spin; spinlock_t ls_rcom_spin;
......
This diff is collapsed.
...@@ -17,7 +17,7 @@ void dlm_print_rsb(struct dlm_rsb *r); ...@@ -17,7 +17,7 @@ void dlm_print_rsb(struct dlm_rsb *r);
void dlm_dump_rsb(struct dlm_rsb *r); void dlm_dump_rsb(struct dlm_rsb *r);
void dlm_print_lkb(struct dlm_lkb *lkb); 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, struct dlm_message *ms);
void dlm_receive_buffer(struct dlm_header *hd, int nodeid); void dlm_receive_buffer(union dlm_packet *p, int nodeid);
int dlm_modes_compat(int mode1, int mode2); int dlm_modes_compat(int mode1, int mode2);
void dlm_put_rsb(struct dlm_rsb *r); void dlm_put_rsb(struct dlm_rsb *r);
void dlm_hold_rsb(struct dlm_rsb *r); void dlm_hold_rsb(struct dlm_rsb *r);
......
...@@ -191,7 +191,7 @@ static int do_uevent(struct dlm_ls *ls, int in) ...@@ -191,7 +191,7 @@ static int do_uevent(struct dlm_ls *ls, int in)
} }
int dlm_lockspace_init(void) int __init dlm_lockspace_init(void)
{ {
ls_count = 0; ls_count = 0;
mutex_init(&ls_lock); mutex_init(&ls_lock);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
static struct kmem_cache *lkb_cache; static struct kmem_cache *lkb_cache;
int dlm_memory_init(void) int __init dlm_memory_init(void)
{ {
int ret = 0; int ret = 0;
...@@ -80,7 +80,7 @@ void dlm_free_lkb(struct dlm_lkb *lkb) ...@@ -80,7 +80,7 @@ void dlm_free_lkb(struct dlm_lkb *lkb)
{ {
if (lkb->lkb_flags & DLM_IFL_USER) { if (lkb->lkb_flags & DLM_IFL_USER) {
struct dlm_user_args *ua; struct dlm_user_args *ua;
ua = (struct dlm_user_args *)lkb->lkb_astparam; ua = lkb->lkb_ua;
if (ua) { if (ua) {
if (ua->lksb.sb_lvbptr) if (ua->lksb.sb_lvbptr)
kfree(ua->lksb.sb_lvbptr); kfree(ua->lksb.sb_lvbptr);
......
...@@ -61,9 +61,9 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, ...@@ -61,9 +61,9 @@ int dlm_process_incoming_buffer(int nodeid, const void *base,
union { union {
unsigned char __buf[DLM_INBUF_LEN]; unsigned char __buf[DLM_INBUF_LEN];
/* this is to force proper alignment on some arches */ /* this is to force proper alignment on some arches */
struct dlm_header dlm; union dlm_packet p;
} __tmp; } __tmp;
struct dlm_header *msg = &__tmp.dlm; union dlm_packet *p = &__tmp.p;
int ret = 0; int ret = 0;
int err = 0; int err = 0;
uint16_t msglen; uint16_t msglen;
...@@ -75,15 +75,22 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, ...@@ -75,15 +75,22 @@ int dlm_process_incoming_buffer(int nodeid, const void *base,
message may wrap around the end of the buffer back to the message may wrap around the end of the buffer back to the
start, so we need to use a temp buffer and copy_from_cb. */ start, so we need to use a temp buffer and copy_from_cb. */
copy_from_cb(msg, base, offset, sizeof(struct dlm_header), copy_from_cb(p, base, offset, sizeof(struct dlm_header),
limit); limit);
msglen = le16_to_cpu(msg->h_length); msglen = le16_to_cpu(p->header.h_length);
lockspace = msg->h_lockspace; lockspace = p->header.h_lockspace;
err = -EINVAL; err = -EINVAL;
if (msglen < sizeof(struct dlm_header)) if (msglen < sizeof(struct dlm_header))
break; break;
if (p->header.h_cmd == DLM_MSG) {
if (msglen < sizeof(struct dlm_message))
break;
} else {
if (msglen < sizeof(struct dlm_rcom))
break;
}
err = -E2BIG; err = -E2BIG;
if (msglen > dlm_config.ci_buffer_size) { if (msglen > dlm_config.ci_buffer_size) {
log_print("message size %d from %d too big, buf len %d", log_print("message size %d from %d too big, buf len %d",
...@@ -104,26 +111,26 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, ...@@ -104,26 +111,26 @@ int dlm_process_incoming_buffer(int nodeid, const void *base,
in the buffer on the stack (which should work for most in the buffer on the stack (which should work for most
ordinary messages). */ ordinary messages). */
if (msglen > DLM_INBUF_LEN && msg == &__tmp.dlm) { if (msglen > sizeof(__tmp) && p == &__tmp.p) {
msg = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); p = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
if (msg == NULL) if (p == NULL)
return ret; return ret;
} }
copy_from_cb(msg, base, offset, msglen, limit); copy_from_cb(p, base, offset, msglen, limit);
BUG_ON(lockspace != msg->h_lockspace); BUG_ON(lockspace != p->header.h_lockspace);
ret += msglen; ret += msglen;
offset += msglen; offset += msglen;
offset &= (limit - 1); offset &= (limit - 1);
len -= msglen; len -= msglen;
dlm_receive_buffer(msg, nodeid); dlm_receive_buffer(p, nodeid);
} }
if (msg != &__tmp.dlm) if (p != &__tmp.p)
kfree(msg); kfree(p);
return err ? err : ret; return err ? err : ret;
} }
......
...@@ -78,7 +78,7 @@ static struct genl_ops dlm_nl_ops = { ...@@ -78,7 +78,7 @@ static struct genl_ops dlm_nl_ops = {
.doit = user_cmd, .doit = user_cmd,
}; };
int dlm_netlink_init(void) int __init dlm_netlink_init(void)
{ {
int rv; int rv;
...@@ -95,7 +95,7 @@ int dlm_netlink_init(void) ...@@ -95,7 +95,7 @@ int dlm_netlink_init(void)
return rv; return rv;
} }
void dlm_netlink_exit(void) void __exit dlm_netlink_exit(void)
{ {
genl_unregister_ops(&family, &dlm_nl_ops); genl_unregister_ops(&family, &dlm_nl_ops);
genl_unregister_family(&family); genl_unregister_family(&family);
...@@ -104,7 +104,6 @@ void dlm_netlink_exit(void) ...@@ -104,7 +104,6 @@ void dlm_netlink_exit(void)
static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb) static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
{ {
struct dlm_rsb *r = lkb->lkb_resource; struct dlm_rsb *r = lkb->lkb_resource;
struct dlm_user_args *ua = (struct dlm_user_args *) lkb->lkb_astparam;
memset(data, 0, sizeof(struct dlm_lock_data)); memset(data, 0, sizeof(struct dlm_lock_data));
...@@ -117,8 +116,8 @@ static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb) ...@@ -117,8 +116,8 @@ static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
data->grmode = lkb->lkb_grmode; data->grmode = lkb->lkb_grmode;
data->rqmode = lkb->lkb_rqmode; data->rqmode = lkb->lkb_rqmode;
data->timestamp = lkb->lkb_timestamp; data->timestamp = lkb->lkb_timestamp;
if (ua) if (lkb->lkb_ua)
data->xid = ua->xid; data->xid = lkb->lkb_ua->xid;
if (r) { if (r) {
data->lockspace_id = r->res_ls->ls_global_id; data->lockspace_id = r->res_ls->ls_global_id;
data->resource_namelen = r->res_length; data->resource_namelen = r->res_length;
......
...@@ -78,13 +78,14 @@ static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh, ...@@ -78,13 +78,14 @@ static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh,
static void make_config(struct dlm_ls *ls, struct rcom_config *rf) static void make_config(struct dlm_ls *ls, struct rcom_config *rf)
{ {
rf->rf_lvblen = ls->ls_lvblen; rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen);
rf->rf_lsflags = ls->ls_exflags; rf->rf_lsflags = cpu_to_le32(ls->ls_exflags);
} }
static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
{ {
struct rcom_config *rf = (struct rcom_config *) rc->rc_buf; struct rcom_config *rf = (struct rcom_config *) rc->rc_buf;
size_t conf_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) { if ((rc->rc_header.h_version & 0xFFFF0000) != DLM_HEADER_MAJOR) {
log_error(ls, "version mismatch: %x nodeid %d: %x", log_error(ls, "version mismatch: %x nodeid %d: %x",
...@@ -93,11 +94,18 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) ...@@ -93,11 +94,18 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
return -EPROTO; return -EPROTO;
} }
if (rf->rf_lvblen != ls->ls_lvblen || if (rc->rc_header.h_length < conf_size) {
rf->rf_lsflags != ls->ls_exflags) { log_error(ls, "config too short: %d nodeid %d",
rc->rc_header.h_length, nodeid);
return -EPROTO;
}
if (le32_to_cpu(rf->rf_lvblen) != ls->ls_lvblen ||
le32_to_cpu(rf->rf_lsflags) != ls->ls_exflags) {
log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x", log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
ls->ls_lvblen, ls->ls_exflags, ls->ls_lvblen, ls->ls_exflags, nodeid,
nodeid, rf->rf_lvblen, rf->rf_lsflags); le32_to_cpu(rf->rf_lvblen),
le32_to_cpu(rf->rf_lsflags));
return -EPROTO; return -EPROTO;
} }
return 0; return 0;
...@@ -128,7 +136,7 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) ...@@ -128,7 +136,7 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid)
ls->ls_recover_nodeid = nodeid; ls->ls_recover_nodeid = nodeid;
if (nodeid == dlm_our_nodeid()) { if (nodeid == dlm_our_nodeid()) {
rc = (struct dlm_rcom *) ls->ls_recover_buf; rc = ls->ls_recover_buf;
rc->rc_result = dlm_recover_status(ls); rc->rc_result = dlm_recover_status(ls);
goto out; goto out;
} }
...@@ -147,7 +155,7 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) ...@@ -147,7 +155,7 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid)
if (error) if (error)
goto out; goto out;
rc = (struct dlm_rcom *) ls->ls_recover_buf; rc = ls->ls_recover_buf;
if (rc->rc_result == -ESRCH) { if (rc->rc_result == -ESRCH) {
/* we pretend the remote lockspace exists with 0 status */ /* we pretend the remote lockspace exists with 0 status */
...@@ -201,14 +209,15 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) ...@@ -201,14 +209,15 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
{ {
struct dlm_rcom *rc; struct dlm_rcom *rc;
struct dlm_mhandle *mh; struct dlm_mhandle *mh;
int error = 0, len = sizeof(struct dlm_rcom); int error = 0;
int max_size = dlm_config.ci_buffer_size - sizeof(struct dlm_rcom);
ls->ls_recover_nodeid = nodeid; ls->ls_recover_nodeid = nodeid;
if (nodeid == dlm_our_nodeid()) { if (nodeid == dlm_our_nodeid()) {
dlm_copy_master_names(ls, last_name, last_len, dlm_copy_master_names(ls, last_name, last_len,
ls->ls_recover_buf + len, ls->ls_recover_buf->rc_buf,
dlm_config.ci_buffer_size - len, nodeid); max_size, nodeid);
goto out; goto out;
} }
...@@ -299,22 +308,22 @@ static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, ...@@ -299,22 +308,22 @@ static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb,
{ {
memset(rl, 0, sizeof(*rl)); memset(rl, 0, sizeof(*rl));
rl->rl_ownpid = lkb->lkb_ownpid; rl->rl_ownpid = cpu_to_le32(lkb->lkb_ownpid);
rl->rl_lkid = lkb->lkb_id; rl->rl_lkid = cpu_to_le32(lkb->lkb_id);
rl->rl_exflags = lkb->lkb_exflags; rl->rl_exflags = cpu_to_le32(lkb->lkb_exflags);
rl->rl_flags = lkb->lkb_flags; rl->rl_flags = cpu_to_le32(lkb->lkb_flags);
rl->rl_lvbseq = lkb->lkb_lvbseq; rl->rl_lvbseq = cpu_to_le32(lkb->lkb_lvbseq);
rl->rl_rqmode = lkb->lkb_rqmode; rl->rl_rqmode = lkb->lkb_rqmode;
rl->rl_grmode = lkb->lkb_grmode; rl->rl_grmode = lkb->lkb_grmode;
rl->rl_status = lkb->lkb_status; rl->rl_status = lkb->lkb_status;
rl->rl_wait_type = lkb->lkb_wait_type; rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type);
if (lkb->lkb_bastaddr) if (lkb->lkb_bastfn)
rl->rl_asts |= AST_BAST; rl->rl_asts |= AST_BAST;
if (lkb->lkb_astaddr) if (lkb->lkb_astfn)
rl->rl_asts |= AST_COMP; rl->rl_asts |= AST_COMP;
rl->rl_namelen = r->res_length; rl->rl_namelen = cpu_to_le16(r->res_length);
memcpy(rl->rl_name, r->res_name, r->res_length); memcpy(rl->rl_name, r->res_name, r->res_length);
/* FIXME: might we have an lvb without DLM_LKF_VALBLK set ? /* FIXME: might we have an lvb without DLM_LKF_VALBLK set ?
...@@ -348,6 +357,7 @@ int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) ...@@ -348,6 +357,7 @@ int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
return error; return error;
} }
/* needs at least dlm_rcom + rcom_lock */
static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in) static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in)
{ {
struct dlm_rcom *rc; struct dlm_rcom *rc;
...@@ -401,7 +411,7 @@ int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) ...@@ -401,7 +411,7 @@ int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
rc->rc_result = -ESRCH; rc->rc_result = -ESRCH;
rf = (struct rcom_config *) rc->rc_buf; rf = (struct rcom_config *) rc->rc_buf;
rf->rf_lvblen = -1; rf->rf_lvblen = cpu_to_le32(~0U);
dlm_rcom_out(rc); dlm_rcom_out(rc);
dlm_lowcomms_commit_buffer(mh); dlm_lowcomms_commit_buffer(mh);
...@@ -439,6 +449,8 @@ static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc) ...@@ -439,6 +449,8 @@ static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
{ {
int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock);
if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) { if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) {
log_debug(ls, "ignoring recovery message %x from %d", log_debug(ls, "ignoring recovery message %x from %d",
rc->rc_type, nodeid); rc->rc_type, nodeid);
...@@ -462,6 +474,8 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) ...@@ -462,6 +474,8 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
break; break;
case DLM_RCOM_LOCK: case DLM_RCOM_LOCK:
if (rc->rc_header.h_length < lock_size)
goto Eshort;
receive_rcom_lock(ls, rc); receive_rcom_lock(ls, rc);
break; break;
...@@ -478,13 +492,18 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) ...@@ -478,13 +492,18 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
break; break;
case DLM_RCOM_LOCK_REPLY: case DLM_RCOM_LOCK_REPLY:
if (rc->rc_header.h_length < lock_size)
goto Eshort;
dlm_recover_process_copy(ls, rc); dlm_recover_process_copy(ls, rc);
break; break;
default: default:
log_error(ls, "receive_rcom bad type %d", rc->rc_type); log_error(ls, "receive_rcom bad type %d", rc->rc_type);
} }
out: out:
return; return;
Eshort:
log_error(ls, "recovery message %x from %d is too short",
rc->rc_type, nodeid);
} }
...@@ -94,7 +94,7 @@ void dlm_set_recover_status(struct dlm_ls *ls, uint32_t status) ...@@ -94,7 +94,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) static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status)
{ {
struct dlm_rcom *rc = (struct dlm_rcom *) ls->ls_recover_buf; struct dlm_rcom *rc = ls->ls_recover_buf;
struct dlm_member *memb; struct dlm_member *memb;
int error = 0, delay; int error = 0, delay;
...@@ -123,7 +123,7 @@ static int wait_status_all(struct dlm_ls *ls, uint32_t wait_status) ...@@ -123,7 +123,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) static int wait_status_low(struct dlm_ls *ls, uint32_t wait_status)
{ {
struct dlm_rcom *rc = (struct dlm_rcom *) ls->ls_recover_buf; struct dlm_rcom *rc = ls->ls_recover_buf;
int error = 0, delay = 0, nodeid = ls->ls_low_nodeid; int error = 0, delay = 0, nodeid = ls->ls_low_nodeid;
for (;;) { for (;;) {
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
struct rq_entry { struct rq_entry {
struct list_head list; struct list_head list;
int nodeid; int nodeid;
char request[0]; struct dlm_message request;
}; };
/* /*
...@@ -30,10 +30,10 @@ struct rq_entry { ...@@ -30,10 +30,10 @@ struct rq_entry {
* lockspace is enabled on some while still suspended on others. * lockspace is enabled on some while still suspended on others.
*/ */
void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd) void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms)
{ {
struct rq_entry *e; struct rq_entry *e;
int length = hd->h_length; int length = ms->m_header.h_length - sizeof(struct dlm_message);
e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL); e = kmalloc(sizeof(struct rq_entry) + length, GFP_KERNEL);
if (!e) { if (!e) {
...@@ -42,7 +42,7 @@ void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd) ...@@ -42,7 +42,7 @@ void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd)
} }
e->nodeid = nodeid; e->nodeid = nodeid;
memcpy(e->request, hd, length); memcpy(&e->request, ms, ms->m_header.h_length);
mutex_lock(&ls->ls_requestqueue_mutex); mutex_lock(&ls->ls_requestqueue_mutex);
list_add_tail(&e->list, &ls->ls_requestqueue); list_add_tail(&e->list, &ls->ls_requestqueue);
...@@ -76,7 +76,7 @@ int dlm_process_requestqueue(struct dlm_ls *ls) ...@@ -76,7 +76,7 @@ int dlm_process_requestqueue(struct dlm_ls *ls)
e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list); e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list);
mutex_unlock(&ls->ls_requestqueue_mutex); mutex_unlock(&ls->ls_requestqueue_mutex);
dlm_receive_message_saved(ls, (struct dlm_message *)e->request); dlm_receive_message_saved(ls, &e->request);
mutex_lock(&ls->ls_requestqueue_mutex); mutex_lock(&ls->ls_requestqueue_mutex);
list_del(&e->list); list_del(&e->list);
...@@ -176,7 +176,7 @@ void dlm_purge_requestqueue(struct dlm_ls *ls) ...@@ -176,7 +176,7 @@ void dlm_purge_requestqueue(struct dlm_ls *ls)
mutex_lock(&ls->ls_requestqueue_mutex); mutex_lock(&ls->ls_requestqueue_mutex);
list_for_each_entry_safe(e, safe, &ls->ls_requestqueue, list) { list_for_each_entry_safe(e, safe, &ls->ls_requestqueue, list) {
ms = (struct dlm_message *) e->request; ms = &e->request;
if (purge_request(ls, ms, e->nodeid)) { if (purge_request(ls, ms, e->nodeid)) {
list_del(&e->list); list_del(&e->list);
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#ifndef __REQUESTQUEUE_DOT_H__ #ifndef __REQUESTQUEUE_DOT_H__
#define __REQUESTQUEUE_DOT_H__ #define __REQUESTQUEUE_DOT_H__
void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd); void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms);
int dlm_process_requestqueue(struct dlm_ls *ls); int dlm_process_requestqueue(struct dlm_ls *ls);
void dlm_wait_requestqueue(struct dlm_ls *ls); void dlm_wait_requestqueue(struct dlm_ls *ls);
void dlm_purge_requestqueue(struct dlm_ls *ls); void dlm_purge_requestqueue(struct dlm_ls *ls);
......
...@@ -82,7 +82,7 @@ struct dlm_lock_result32 { ...@@ -82,7 +82,7 @@ struct dlm_lock_result32 {
static void compat_input(struct dlm_write_request *kb, static void compat_input(struct dlm_write_request *kb,
struct dlm_write_request32 *kb32, struct dlm_write_request32 *kb32,
int max_namelen) size_t count)
{ {
kb->version[0] = kb32->version[0]; kb->version[0] = kb32->version[0];
kb->version[1] = kb32->version[1]; kb->version[1] = kb32->version[1];
...@@ -94,7 +94,8 @@ static void compat_input(struct dlm_write_request *kb, ...@@ -94,7 +94,8 @@ static void compat_input(struct dlm_write_request *kb,
kb->cmd == DLM_USER_REMOVE_LOCKSPACE) { kb->cmd == DLM_USER_REMOVE_LOCKSPACE) {
kb->i.lspace.flags = kb32->i.lspace.flags; kb->i.lspace.flags = kb32->i.lspace.flags;
kb->i.lspace.minor = kb32->i.lspace.minor; kb->i.lspace.minor = kb32->i.lspace.minor;
strcpy(kb->i.lspace.name, kb32->i.lspace.name); memcpy(kb->i.lspace.name, kb32->i.lspace.name, count -
offsetof(struct dlm_write_request32, i.lspace.name));
} else if (kb->cmd == DLM_USER_PURGE) { } else if (kb->cmd == DLM_USER_PURGE) {
kb->i.purge.nodeid = kb32->i.purge.nodeid; kb->i.purge.nodeid = kb32->i.purge.nodeid;
kb->i.purge.pid = kb32->i.purge.pid; kb->i.purge.pid = kb32->i.purge.pid;
...@@ -112,11 +113,8 @@ static void compat_input(struct dlm_write_request *kb, ...@@ -112,11 +113,8 @@ static void compat_input(struct dlm_write_request *kb,
kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr; kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb; kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN); memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
if (kb->i.lock.namelen <= max_namelen) memcpy(kb->i.lock.name, kb32->i.lock.name, count -
memcpy(kb->i.lock.name, kb32->i.lock.name, offsetof(struct dlm_write_request32, i.lock.name));
kb->i.lock.namelen);
else
kb->i.lock.namelen = max_namelen;
} }
} }
...@@ -197,8 +195,8 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) ...@@ -197,8 +195,8 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
goto out; goto out;
DLM_ASSERT(lkb->lkb_astparam, dlm_print_lkb(lkb);); DLM_ASSERT(lkb->lkb_ua, dlm_print_lkb(lkb););
ua = (struct dlm_user_args *)lkb->lkb_astparam; ua = lkb->lkb_ua;
proc = ua->proc; proc = ua->proc;
if (type == AST_BAST && ua->bastaddr == NULL) if (type == AST_BAST && ua->bastaddr == NULL)
...@@ -508,7 +506,7 @@ static ssize_t device_write(struct file *file, const char __user *buf, ...@@ -508,7 +506,7 @@ static ssize_t device_write(struct file *file, const char __user *buf,
#endif #endif
return -EINVAL; return -EINVAL;
kbuf = kmalloc(count, GFP_KERNEL); kbuf = kzalloc(count + 1, GFP_KERNEL);
if (!kbuf) if (!kbuf)
return -ENOMEM; return -ENOMEM;
...@@ -526,15 +524,14 @@ static ssize_t device_write(struct file *file, const char __user *buf, ...@@ -526,15 +524,14 @@ static ssize_t device_write(struct file *file, const char __user *buf,
if (!kbuf->is64bit) { if (!kbuf->is64bit) {
struct dlm_write_request32 *k32buf; struct dlm_write_request32 *k32buf;
k32buf = (struct dlm_write_request32 *)kbuf; k32buf = (struct dlm_write_request32 *)kbuf;
kbuf = kmalloc(count + (sizeof(struct dlm_write_request) - kbuf = kmalloc(count + 1 + (sizeof(struct dlm_write_request) -
sizeof(struct dlm_write_request32)), GFP_KERNEL); sizeof(struct dlm_write_request32)), GFP_KERNEL);
if (!kbuf) if (!kbuf)
return -ENOMEM; return -ENOMEM;
if (proc) if (proc)
set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags); set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
compat_input(kbuf, k32buf, compat_input(kbuf, k32buf, count + 1);
count - sizeof(struct dlm_write_request32));
kfree(k32buf); kfree(k32buf);
} }
#endif #endif
...@@ -774,7 +771,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, ...@@ -774,7 +771,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
{ {
struct dlm_user_proc *proc = file->private_data; struct dlm_user_proc *proc = file->private_data;
struct dlm_lkb *lkb; struct dlm_lkb *lkb;
struct dlm_user_args *ua;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int error, type=0, bmode=0, removed = 0; int error, type=0, bmode=0, removed = 0;
...@@ -845,8 +841,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, ...@@ -845,8 +841,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
} }
spin_unlock(&proc->asts_spin); spin_unlock(&proc->asts_spin);
ua = (struct dlm_user_args *)lkb->lkb_astparam; error = copy_result_to_user(lkb->lkb_ua,
error = copy_result_to_user(ua,
test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags), test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
type, bmode, buf, count); type, bmode, buf, count);
...@@ -907,7 +902,7 @@ static struct miscdevice ctl_device = { ...@@ -907,7 +902,7 @@ static struct miscdevice ctl_device = {
.minor = MISC_DYNAMIC_MINOR, .minor = MISC_DYNAMIC_MINOR,
}; };
int dlm_user_init(void) int __init dlm_user_init(void)
{ {
int error; int error;
......
...@@ -131,52 +131,8 @@ void dlm_message_in(struct dlm_message *ms) ...@@ -131,52 +131,8 @@ void dlm_message_in(struct dlm_message *ms)
ms->m_result = from_dlm_errno(le32_to_cpu(ms->m_result)); ms->m_result = from_dlm_errno(le32_to_cpu(ms->m_result));
} }
static void rcom_lock_out(struct rcom_lock *rl)
{
rl->rl_ownpid = cpu_to_le32(rl->rl_ownpid);
rl->rl_lkid = cpu_to_le32(rl->rl_lkid);
rl->rl_remid = cpu_to_le32(rl->rl_remid);
rl->rl_parent_lkid = cpu_to_le32(rl->rl_parent_lkid);
rl->rl_parent_remid = cpu_to_le32(rl->rl_parent_remid);
rl->rl_exflags = cpu_to_le32(rl->rl_exflags);
rl->rl_flags = cpu_to_le32(rl->rl_flags);
rl->rl_lvbseq = cpu_to_le32(rl->rl_lvbseq);
rl->rl_result = cpu_to_le32(rl->rl_result);
rl->rl_wait_type = cpu_to_le16(rl->rl_wait_type);
rl->rl_namelen = cpu_to_le16(rl->rl_namelen);
}
static void rcom_lock_in(struct rcom_lock *rl)
{
rl->rl_ownpid = le32_to_cpu(rl->rl_ownpid);
rl->rl_lkid = le32_to_cpu(rl->rl_lkid);
rl->rl_remid = le32_to_cpu(rl->rl_remid);
rl->rl_parent_lkid = le32_to_cpu(rl->rl_parent_lkid);
rl->rl_parent_remid = le32_to_cpu(rl->rl_parent_remid);
rl->rl_exflags = le32_to_cpu(rl->rl_exflags);
rl->rl_flags = le32_to_cpu(rl->rl_flags);
rl->rl_lvbseq = le32_to_cpu(rl->rl_lvbseq);
rl->rl_result = le32_to_cpu(rl->rl_result);
rl->rl_wait_type = le16_to_cpu(rl->rl_wait_type);
rl->rl_namelen = le16_to_cpu(rl->rl_namelen);
}
static void rcom_config_out(struct rcom_config *rf)
{
rf->rf_lvblen = cpu_to_le32(rf->rf_lvblen);
rf->rf_lsflags = cpu_to_le32(rf->rf_lsflags);
}
static void rcom_config_in(struct rcom_config *rf)
{
rf->rf_lvblen = le32_to_cpu(rf->rf_lvblen);
rf->rf_lsflags = le32_to_cpu(rf->rf_lsflags);
}
void dlm_rcom_out(struct dlm_rcom *rc) void dlm_rcom_out(struct dlm_rcom *rc)
{ {
int type = rc->rc_type;
header_out(&rc->rc_header); header_out(&rc->rc_header);
rc->rc_type = cpu_to_le32(rc->rc_type); rc->rc_type = cpu_to_le32(rc->rc_type);
...@@ -184,18 +140,10 @@ void dlm_rcom_out(struct dlm_rcom *rc) ...@@ -184,18 +140,10 @@ void dlm_rcom_out(struct dlm_rcom *rc)
rc->rc_id = cpu_to_le64(rc->rc_id); rc->rc_id = cpu_to_le64(rc->rc_id);
rc->rc_seq = cpu_to_le64(rc->rc_seq); rc->rc_seq = cpu_to_le64(rc->rc_seq);
rc->rc_seq_reply = cpu_to_le64(rc->rc_seq_reply); rc->rc_seq_reply = cpu_to_le64(rc->rc_seq_reply);
if ((type == DLM_RCOM_LOCK) || (type == DLM_RCOM_LOCK_REPLY))
rcom_lock_out((struct rcom_lock *) rc->rc_buf);
else if (type == DLM_RCOM_STATUS_REPLY)
rcom_config_out((struct rcom_config *) rc->rc_buf);
} }
void dlm_rcom_in(struct dlm_rcom *rc) void dlm_rcom_in(struct dlm_rcom *rc)
{ {
int type;
header_in(&rc->rc_header); header_in(&rc->rc_header);
rc->rc_type = le32_to_cpu(rc->rc_type); rc->rc_type = le32_to_cpu(rc->rc_type);
...@@ -203,13 +151,4 @@ void dlm_rcom_in(struct dlm_rcom *rc) ...@@ -203,13 +151,4 @@ void dlm_rcom_in(struct dlm_rcom *rc)
rc->rc_id = le64_to_cpu(rc->rc_id); rc->rc_id = le64_to_cpu(rc->rc_id);
rc->rc_seq = le64_to_cpu(rc->rc_seq); rc->rc_seq = le64_to_cpu(rc->rc_seq);
rc->rc_seq_reply = le64_to_cpu(rc->rc_seq_reply); rc->rc_seq_reply = le64_to_cpu(rc->rc_seq_reply);
type = rc->rc_type;
if ((type == DLM_RCOM_LOCK) || (type == DLM_RCOM_LOCK_REPLY))
rcom_lock_in((struct rcom_lock *) rc->rc_buf);
else if (type == DLM_RCOM_STATUS_REPLY)
rcom_config_in((struct rcom_config *) rc->rc_buf);
} }
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