From 8b0d8e03f847d9c1677b8a193cd124debbc54633 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 00:28:28 -0500 Subject: dlm: use proper C for dlm/requestqueue stuff (and fix alignment bug) a) don't cast the pointer to dlm_header *, we use it as dlm_message * anyway. b) we copy the message into a queue element, then pass the pointer to copy to dlm_receive_message_saved(); declare it properly to make sure that we have the right alignment. Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/lock.c | 2 +- fs/dlm/requestqueue.c | 12 ++++++------ fs/dlm/requestqueue.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index ff4a198fa67..d9f07a42e3c 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -3802,7 +3802,7 @@ static void dlm_receive_message(struct dlm_ls *ls, struct dlm_message *ms, int nodeid) { if (dlm_locking_stopped(ls)) { - dlm_add_requestqueue(ls, nodeid, (struct dlm_header *) ms); + dlm_add_requestqueue(ls, nodeid, ms); } else { dlm_wait_requestqueue(ls); _receive_message(ls, ms); diff --git a/fs/dlm/requestqueue.c b/fs/dlm/requestqueue.c index 0de04f17cce..daa4183fbb8 100644 --- a/fs/dlm/requestqueue.c +++ b/fs/dlm/requestqueue.c @@ -20,7 +20,7 @@ struct rq_entry { struct list_head list; int nodeid; - char request[0]; + struct dlm_message request; }; /* @@ -30,10 +30,10 @@ 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_header *hd) +void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms) { 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); if (!e) { @@ -42,7 +42,7 @@ void dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_header *hd) } e->nodeid = nodeid; - memcpy(e->request, hd, length); + memcpy(&e->request, ms, ms->m_header.h_length); mutex_lock(&ls->ls_requestqueue_mutex); list_add_tail(&e->list, &ls->ls_requestqueue); @@ -76,7 +76,7 @@ int dlm_process_requestqueue(struct dlm_ls *ls) e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list); 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); list_del(&e->list); @@ -176,7 +176,7 @@ void dlm_purge_requestqueue(struct dlm_ls *ls) mutex_lock(&ls->ls_requestqueue_mutex); 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)) { list_del(&e->list); diff --git a/fs/dlm/requestqueue.h b/fs/dlm/requestqueue.h index aba34fc05ee..10ce449b77d 100644 --- a/fs/dlm/requestqueue.h +++ b/fs/dlm/requestqueue.h @@ -13,7 +13,7 @@ #ifndef __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); void dlm_wait_requestqueue(struct dlm_ls *ls); void dlm_purge_requestqueue(struct dlm_ls *ls); -- cgit v1.2.3 From eef7d739c218cb2546cf95686db77de0d76e4122 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 00:58:46 -0500 Subject: dlm: dlm_process_incoming_buffer() fixes * check that length is large enough to cover the non-variable part of message or rcom resp. (after checking that it's large enough to cover the header, of course). * kill more pointless casts Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/dlm_internal.h | 6 ++++++ fs/dlm/lock.c | 19 +++++++++---------- fs/dlm/lock.h | 2 +- fs/dlm/midcomms.c | 33 ++++++++++++++++++++------------- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index ec61bbaf25d..65499ceaa51 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -403,6 +403,12 @@ struct dlm_rcom { 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 { uint32_t rf_lvblen; uint32_t rf_lsflags; diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index d9f07a42e3c..2a28048252e 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -3822,21 +3822,20 @@ void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms) standard locking activity) or an RCOM (recovery message sent as part of lockspace recovery). */ -void dlm_receive_buffer(struct dlm_header *hd, int nodeid) +void dlm_receive_buffer(union dlm_packet *p, int nodeid) { - struct dlm_message *ms = (struct dlm_message *) hd; - struct dlm_rcom *rc = (struct dlm_rcom *) hd; + struct dlm_header *hd = &p->header; struct dlm_ls *ls; int type = 0; switch (hd->h_cmd) { case DLM_MSG: - dlm_message_in(ms); - type = ms->m_type; + dlm_message_in(&p->message); + type = p->message.m_type; break; case DLM_RCOM: - dlm_rcom_in(rc); - type = rc->rc_type; + dlm_rcom_in(&p->rcom); + type = p->rcom.rc_type; break; default: log_print("invalid h_cmd %d from %u", hd->h_cmd, nodeid); @@ -3856,7 +3855,7 @@ void dlm_receive_buffer(struct dlm_header *hd, int nodeid) hd->h_lockspace, nodeid, hd->h_cmd, type); if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS) - dlm_send_ls_not_ready(nodeid, rc); + dlm_send_ls_not_ready(nodeid, &p->rcom); return; } @@ -3865,9 +3864,9 @@ void dlm_receive_buffer(struct dlm_header *hd, int nodeid) down_read(&ls->ls_recv_active); if (hd->h_cmd == DLM_MSG) - dlm_receive_message(ls, ms, nodeid); + dlm_receive_message(ls, &p->message, nodeid); else - dlm_receive_rcom(ls, rc, nodeid); + dlm_receive_rcom(ls, &p->rcom, nodeid); up_read(&ls->ls_recv_active); dlm_put_lockspace(ls); diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h index 27b6ed30291..05d9c82e646 100644 --- a/fs/dlm/lock.h +++ b/fs/dlm/lock.h @@ -17,7 +17,7 @@ void dlm_print_rsb(struct dlm_rsb *r); void dlm_dump_rsb(struct dlm_rsb *r); void dlm_print_lkb(struct dlm_lkb *lkb); 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); void dlm_put_rsb(struct dlm_rsb *r); void dlm_hold_rsb(struct dlm_rsb *r); diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c index e69926e984d..07ac709f3ed 100644 --- a/fs/dlm/midcomms.c +++ b/fs/dlm/midcomms.c @@ -61,9 +61,9 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, union { unsigned char __buf[DLM_INBUF_LEN]; /* this is to force proper alignment on some arches */ - struct dlm_header dlm; + union dlm_packet p; } __tmp; - struct dlm_header *msg = &__tmp.dlm; + union dlm_packet *p = &__tmp.p; int ret = 0; int err = 0; uint16_t msglen; @@ -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 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); - msglen = le16_to_cpu(msg->h_length); - lockspace = msg->h_lockspace; + msglen = le16_to_cpu(p->header.h_length); + lockspace = p->header.h_lockspace; err = -EINVAL; if (msglen < sizeof(struct dlm_header)) 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; if (msglen > dlm_config.ci_buffer_size) { 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, in the buffer on the stack (which should work for most ordinary messages). */ - if (msglen > DLM_INBUF_LEN && msg == &__tmp.dlm) { - msg = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); - if (msg == NULL) + if (msglen > sizeof(__tmp) && p == &__tmp.p) { + p = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); + if (p == NULL) 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; offset += msglen; offset &= (limit - 1); len -= msglen; - dlm_receive_buffer(msg, nodeid); + dlm_receive_buffer(p, nodeid); } - if (msg != &__tmp.dlm) - kfree(msg); + if (p != &__tmp.p) + kfree(p); return err ? err : ret; } -- cgit v1.2.3 From 163a1859ec6c4c33547bf4613efabf52031566aa Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 02:08:26 -0500 Subject: dlm: do not byteswap rcom_lock Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/dlm_internal.h | 22 +++++++++++----------- fs/dlm/lock.c | 34 +++++++++++++++++++--------------- fs/dlm/rcom.c | 14 +++++++------- fs/dlm/util.c | 45 ++------------------------------------------- 4 files changed, 39 insertions(+), 76 deletions(-) diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 65499ceaa51..e73b988995f 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -416,21 +416,21 @@ struct rcom_config { }; struct rcom_lock { - uint32_t rl_ownpid; - uint32_t rl_lkid; - uint32_t rl_remid; - uint32_t rl_parent_lkid; - uint32_t rl_parent_remid; - uint32_t rl_exflags; - uint32_t rl_flags; - uint32_t rl_lvbseq; - int rl_result; + __le32 rl_ownpid; + __le32 rl_lkid; + __le32 rl_remid; + __le32 rl_parent_lkid; + __le32 rl_parent_remid; + __le32 rl_exflags; + __le32 rl_flags; + __le32 rl_lvbseq; + __le32 rl_result; int8_t rl_rqmode; int8_t rl_grmode; int8_t rl_status; int8_t rl_asts; - uint16_t rl_wait_type; - uint16_t rl_namelen; + __le16 rl_wait_type; + __le16 rl_namelen; char rl_name[DLM_RESNAME_MAXLEN]; char rl_lvb[0]; }; diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 2a28048252e..75176b58ae0 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -4273,12 +4273,12 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, int lvblen; lkb->lkb_nodeid = rc->rc_header.h_nodeid; - lkb->lkb_ownpid = rl->rl_ownpid; - lkb->lkb_remid = rl->rl_lkid; - lkb->lkb_exflags = rl->rl_exflags; - lkb->lkb_flags = rl->rl_flags & 0x0000FFFF; + lkb->lkb_ownpid = le32_to_cpu(rl->rl_ownpid); + lkb->lkb_remid = le32_to_cpu(rl->rl_lkid); + lkb->lkb_exflags = le32_to_cpu(rl->rl_exflags); + lkb->lkb_flags = le32_to_cpu(rl->rl_flags) & 0x0000FFFF; lkb->lkb_flags |= DLM_IFL_MSTCPY; - lkb->lkb_lvbseq = rl->rl_lvbseq; + lkb->lkb_lvbseq = le32_to_cpu(rl->rl_lvbseq); lkb->lkb_rqmode = rl->rl_rqmode; lkb->lkb_grmode = rl->rl_grmode; /* don't set lkb_status because add_lkb wants to itself */ @@ -4299,7 +4299,8 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, The real granted mode of these converting locks cannot be determined until all locks have been rebuilt on the rsb (recover_conversion) */ - if (rl->rl_wait_type == DLM_MSG_CONVERT && middle_conversion(lkb)) { + if (rl->rl_wait_type == cpu_to_le16(DLM_MSG_CONVERT) && + middle_conversion(lkb)) { rl->rl_status = DLM_LKSTS_CONVERT; lkb->lkb_grmode = DLM_LOCK_IV; rsb_set_flag(r, RSB_RECOVER_CONVERT); @@ -4326,13 +4327,14 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc) goto out; } - error = find_rsb(ls, rl->rl_name, rl->rl_namelen, R_MASTER, &r); + error = find_rsb(ls, rl->rl_name, le16_to_cpu(rl->rl_namelen), + R_MASTER, &r); if (error) goto out; lock_rsb(r); - lkb = search_remid(r, rc->rc_header.h_nodeid, rl->rl_lkid); + lkb = search_remid(r, rc->rc_header.h_nodeid, le32_to_cpu(rl->rl_lkid)); if (lkb) { error = -EEXIST; goto out_remid; @@ -4355,15 +4357,16 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc) out_remid: /* this is the new value returned to the lock holder for saving in its process-copy lkb */ - rl->rl_remid = lkb->lkb_id; + rl->rl_remid = cpu_to_le32(lkb->lkb_id); out_unlock: unlock_rsb(r); put_rsb(r); out: if (error) - log_debug(ls, "recover_master_copy %d %x", error, rl->rl_lkid); - rl->rl_result = error; + log_debug(ls, "recover_master_copy %d %x", error, + le32_to_cpu(rl->rl_lkid)); + rl->rl_result = cpu_to_le32(error); return error; } @@ -4374,15 +4377,16 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc) struct dlm_lkb *lkb; int error; - error = find_lkb(ls, rl->rl_lkid, &lkb); + error = find_lkb(ls, le32_to_cpu(rl->rl_lkid), &lkb); if (error) { - log_error(ls, "recover_process_copy no lkid %x", rl->rl_lkid); + log_error(ls, "recover_process_copy no lkid %x", + le32_to_cpu(rl->rl_lkid)); return error; } DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); - error = rl->rl_result; + error = le32_to_cpu(rl->rl_result); r = lkb->lkb_resource; hold_rsb(r); @@ -4401,7 +4405,7 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc) log_debug(ls, "master copy exists %x", lkb->lkb_id); /* fall through */ case 0: - lkb->lkb_remid = rl->rl_remid; + lkb->lkb_remid = le32_to_cpu(rl->rl_remid); break; default: log_error(ls, "dlm_recover_process_copy unknown error %d %x", diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 026824cd3ac..86c1ab99208 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -299,22 +299,22 @@ static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, { memset(rl, 0, sizeof(*rl)); - rl->rl_ownpid = lkb->lkb_ownpid; - rl->rl_lkid = lkb->lkb_id; - rl->rl_exflags = lkb->lkb_exflags; - rl->rl_flags = lkb->lkb_flags; - rl->rl_lvbseq = lkb->lkb_lvbseq; + rl->rl_ownpid = cpu_to_le32(lkb->lkb_ownpid); + rl->rl_lkid = cpu_to_le32(lkb->lkb_id); + rl->rl_exflags = cpu_to_le32(lkb->lkb_exflags); + rl->rl_flags = cpu_to_le32(lkb->lkb_flags); + rl->rl_lvbseq = cpu_to_le32(lkb->lkb_lvbseq); rl->rl_rqmode = lkb->lkb_rqmode; rl->rl_grmode = lkb->lkb_grmode; 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) rl->rl_asts |= AST_BAST; if (lkb->lkb_astaddr) 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); /* FIXME: might we have an lvb without DLM_LKF_VALBLK set ? diff --git a/fs/dlm/util.c b/fs/dlm/util.c index 4d9c1f4e1bd..d3ed6da0b65 100644 --- a/fs/dlm/util.c +++ b/fs/dlm/util.c @@ -131,36 +131,6 @@ void dlm_message_in(struct dlm_message *ms) 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); @@ -185,17 +155,12 @@ void dlm_rcom_out(struct dlm_rcom *rc) rc->rc_seq = cpu_to_le64(rc->rc_seq); 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) + if (type == DLM_RCOM_STATUS_REPLY) rcom_config_out((struct rcom_config *) rc->rc_buf); } void dlm_rcom_in(struct dlm_rcom *rc) { - int type; - header_in(&rc->rc_header); rc->rc_type = le32_to_cpu(rc->rc_type); @@ -204,12 +169,6 @@ void dlm_rcom_in(struct dlm_rcom *rc) rc->rc_seq = le64_to_cpu(rc->rc_seq); 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) + if (rc->rc_type == DLM_RCOM_STATUS_REPLY) rcom_config_in((struct rcom_config *) rc->rc_buf); } - -- cgit v1.2.3 From 93ff2971e99c90d1c4d39d242ef6050d2dc853d3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 02:34:00 -0500 Subject: dlm: do not byteswap rcom_config Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/dlm_internal.h | 6 +++--- fs/dlm/rcom.c | 15 ++++++++------- fs/dlm/util.c | 20 -------------------- 3 files changed, 11 insertions(+), 30 deletions(-) diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index e73b988995f..187a5b5b28b 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -410,9 +410,9 @@ union dlm_packet { }; struct rcom_config { - uint32_t rf_lvblen; - uint32_t rf_lsflags; - uint64_t rf_unused; + __le32 rf_lvblen; + __le32 rf_lsflags; + __le64 rf_unused; }; struct rcom_lock { diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 86c1ab99208..fb0776201d7 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -78,8 +78,8 @@ static void send_rcom(struct dlm_ls *ls, struct dlm_mhandle *mh, static void make_config(struct dlm_ls *ls, struct rcom_config *rf) { - rf->rf_lvblen = ls->ls_lvblen; - rf->rf_lsflags = ls->ls_exflags; + rf->rf_lvblen = cpu_to_le32(ls->ls_lvblen); + rf->rf_lsflags = cpu_to_le32(ls->ls_exflags); } static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) @@ -93,11 +93,12 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) return -EPROTO; } - if (rf->rf_lvblen != ls->ls_lvblen || - rf->rf_lsflags != ls->ls_exflags) { + 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", - ls->ls_lvblen, ls->ls_exflags, - nodeid, rf->rf_lvblen, rf->rf_lsflags); + ls->ls_lvblen, ls->ls_exflags, nodeid, + le32_to_cpu(rf->rf_lvblen), + le32_to_cpu(rf->rf_lsflags)); return -EPROTO; } return 0; @@ -401,7 +402,7 @@ int dlm_send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) rc->rc_result = -ESRCH; rf = (struct rcom_config *) rc->rc_buf; - rf->rf_lvblen = -1; + rf->rf_lvblen = cpu_to_le32(~0U); dlm_rcom_out(rc); dlm_lowcomms_commit_buffer(mh); diff --git a/fs/dlm/util.c b/fs/dlm/util.c index d3ed6da0b65..e36520af7cc 100644 --- a/fs/dlm/util.c +++ b/fs/dlm/util.c @@ -131,22 +131,8 @@ void dlm_message_in(struct dlm_message *ms) ms->m_result = from_dlm_errno(le32_to_cpu(ms->m_result)); } -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) { - int type = rc->rc_type; - header_out(&rc->rc_header); rc->rc_type = cpu_to_le32(rc->rc_type); @@ -154,9 +140,6 @@ void dlm_rcom_out(struct dlm_rcom *rc) rc->rc_id = cpu_to_le64(rc->rc_id); rc->rc_seq = cpu_to_le64(rc->rc_seq); rc->rc_seq_reply = cpu_to_le64(rc->rc_seq_reply); - - if (type == DLM_RCOM_STATUS_REPLY) - rcom_config_out((struct rcom_config *) rc->rc_buf); } void dlm_rcom_in(struct dlm_rcom *rc) @@ -168,7 +151,4 @@ void dlm_rcom_in(struct dlm_rcom *rc) rc->rc_id = le64_to_cpu(rc->rc_id); rc->rc_seq = le64_to_cpu(rc->rc_seq); rc->rc_seq_reply = le64_to_cpu(rc->rc_seq_reply); - - if (rc->rc_type == DLM_RCOM_STATUS_REPLY) - rcom_config_in((struct rcom_config *) rc->rc_buf); } -- cgit v1.2.3 From 4007685c6e6b5c92a07f27cd754bcca394168af2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 03:01:51 -0500 Subject: dlm: use proper type for ->ls_recover_buf Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/dir.c | 2 +- fs/dlm/dlm_internal.h | 2 +- fs/dlm/rcom.c | 11 ++++++----- fs/dlm/recover.c | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c index ff97ba92433..ce30136671b 100644 --- a/fs/dlm/dir.c +++ b/fs/dlm/dir.c @@ -235,7 +235,7 @@ int dlm_recover_directory(struct dlm_ls *ls) * pick namelen/name pairs out of received buffer */ - b = ls->ls_recover_buf + sizeof(struct dlm_rcom); + b = ls->ls_recover_buf->rc_buf; for (;;) { memcpy(&namelen, b, sizeof(uint16_t)); diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 187a5b5b28b..f7fbaec94b1 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -500,7 +500,7 @@ struct dlm_ls { struct rw_semaphore ls_recv_active; /* block dlm_recv */ struct list_head ls_requestqueue;/* queue remote requests */ struct mutex ls_requestqueue_mutex; - char *ls_recover_buf; + struct dlm_rcom *ls_recover_buf; int ls_recover_nodeid; /* for debugging */ uint64_t ls_rcom_seq; spinlock_t ls_rcom_spin; diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index fb0776201d7..3f9b96fd26e 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -129,7 +129,7 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) ls->ls_recover_nodeid = 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); goto out; } @@ -148,7 +148,7 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid) if (error) goto out; - rc = (struct dlm_rcom *) ls->ls_recover_buf; + rc = ls->ls_recover_buf; if (rc->rc_result == -ESRCH) { /* we pretend the remote lockspace exists with 0 status */ @@ -202,14 +202,15 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) { struct dlm_rcom *rc; 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; if (nodeid == dlm_our_nodeid()) { dlm_copy_master_names(ls, last_name, last_len, - ls->ls_recover_buf + len, - dlm_config.ci_buffer_size - len, nodeid); + ls->ls_recover_buf->rc_buf, + max_size, nodeid); goto out; } diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index df075dc300f..80aba5bdd4a 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c @@ -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) { - struct dlm_rcom *rc = (struct dlm_rcom *) ls->ls_recover_buf; + struct dlm_rcom *rc = ls->ls_recover_buf; struct dlm_member *memb; int error = 0, delay; @@ -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) { - 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; for (;;) { -- cgit v1.2.3 From 02ed16b64dc5b7a4f78476bdb64da9bbf88d84b3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 03:03:59 -0500 Subject: dlm: missing length check in check_config() Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/rcom.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 3f9b96fd26e..a312f1d97f8 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -85,6 +85,7 @@ static void make_config(struct dlm_ls *ls, struct rcom_config *rf) static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) { 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) { log_error(ls, "version mismatch: %x nodeid %d: %x", @@ -93,6 +94,12 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) return -EPROTO; } + if (rc->rc_header.h_length < conf_size) { + 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", -- cgit v1.2.3 From cd9df1aac346f1c7f592739d092ff710c27bbcde Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 04:08:09 -0500 Subject: dlm: validate data in dlm_recover_directory() Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/dir.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c index ce30136671b..831050e5bfd 100644 --- a/fs/dlm/dir.c +++ b/fs/dlm/dir.c @@ -220,6 +220,7 @@ int dlm_recover_directory(struct dlm_ls *ls) last_len = 0; for (;;) { + int left; error = dlm_recovery_stopped(ls); if (error) goto out_free; @@ -236,11 +237,20 @@ int dlm_recover_directory(struct dlm_ls *ls) */ b = ls->ls_recover_buf->rc_buf; + left = ls->ls_recover_buf->rc_header.h_length; + left -= sizeof(struct dlm_rcom); for (;;) { - memcpy(&namelen, b, sizeof(uint16_t)); - namelen = be16_to_cpu(namelen); - b += sizeof(uint16_t); + __be16 v; + + 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 this node; namelen of 0 marks end of the @@ -251,6 +261,12 @@ int dlm_recover_directory(struct dlm_ls *ls) if (!namelen) break; + if (namelen > left) + goto out_free; + + if (namelen > DLM_RESNAME_MAXLEN) + goto out_free; + error = -ENOMEM; de = get_free_de(ls, namelen); if (!de) @@ -262,6 +278,7 @@ int dlm_recover_directory(struct dlm_ls *ls) memcpy(de->name, b, namelen); memcpy(last_name, b, namelen); b += namelen; + left -= namelen; add_entry_to_hash(ls, de); count++; -- cgit v1.2.3 From ae773d0b74bf2244887a6d0504372748381ab9c7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 19:55:09 -0500 Subject: dlm: verify that places expecting rcom_lock have packet long enough Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/lock.c | 3 +++ fs/dlm/rcom.c | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 75176b58ae0..6c605fc1061 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -4266,6 +4266,7 @@ static struct dlm_lkb *search_remid(struct dlm_rsb *r, int nodeid, return NULL; } +/* needs at least dlm_rcom + rcom_lock */ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, struct dlm_rsb *r, struct dlm_rcom *rc) { @@ -4315,6 +4316,7 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, the given values and send back our lkid. We send back our lkid by sending back the rcom_lock struct we got but with the remid field filled in. */ +/* needs at least dlm_rcom + rcom_lock */ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc) { struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf; @@ -4370,6 +4372,7 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc) return error; } +/* needs at least dlm_rcom + rcom_lock */ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc) { struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf; diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index a312f1d97f8..ef9d0f91849 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -357,6 +357,7 @@ int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) return error; } +/* needs at least dlm_rcom + rcom_lock */ static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in) { struct dlm_rcom *rc; @@ -448,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) { + int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock); + if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) { log_debug(ls, "ignoring recovery message %x from %d", rc->rc_type, nodeid); @@ -471,6 +474,8 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) break; case DLM_RCOM_LOCK: + if (rc->rc_header.h_length < lock_size) + goto Eshort; receive_rcom_lock(ls, rc); break; @@ -487,13 +492,18 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) break; case DLM_RCOM_LOCK_REPLY: + if (rc->rc_header.h_length < lock_size) + goto Eshort; dlm_recover_process_copy(ls, rc); break; default: log_error(ls, "receive_rcom bad type %d", rc->rc_type); } - out: +out: return; +Eshort: + log_error(ls, "recovery message %x from %d is too short", + rc->rc_type, nodeid); } -- cgit v1.2.3 From a5dd06313dbcec3a2c8a5e4a6f3ddb2a8fc72ec9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 20:22:22 -0500 Subject: dlm: receive_rcom_lock_args() overflow check Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/lock.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 6c605fc1061..0593dd81d46 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -4271,7 +4271,6 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, struct dlm_rsb *r, struct dlm_rcom *rc) { struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf; - int lvblen; lkb->lkb_nodeid = rc->rc_header.h_nodeid; lkb->lkb_ownpid = le32_to_cpu(rl->rl_ownpid); @@ -4288,11 +4287,13 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, lkb->lkb_astaddr = (void *) (long) (rl->rl_asts & AST_COMP); if (lkb->lkb_exflags & DLM_LKF_VALBLK) { + int lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) - + sizeof(struct rcom_lock); + if (lvblen > ls->ls_lvblen) + return -EINVAL; lkb->lkb_lvbptr = dlm_allocate_lvb(ls); if (!lkb->lkb_lvbptr) return -ENOMEM; - lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) - - sizeof(struct rcom_lock); memcpy(lkb->lkb_lvbptr, rl->rl_lvb, lvblen); } -- cgit v1.2.3 From ef58bccab7c7ef34451aa4ceea39545ef126b666 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Jan 2008 23:22:26 -0500 Subject: dlm: make find_rsb() fail gracefully when namelen is too large We *can* get there from receive_request() and dlm_recover_master_copy() with namelen too large if incoming request is invalid; BUG() from DLM_ASSERT() in allocate_rsb() is a bit excessive reaction to that and in case of dlm_recover_master_copy() we would actually oops before that while calculating hash of up to 64Kb worth of data - with data actually being 64 _bytes_ in kmalloc()'ed struct. Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/lock.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 0593dd81d46..6d98cf9d043 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -436,11 +436,15 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen, { struct dlm_rsb *r, *tmp; uint32_t hash, bucket; - int error = 0; + int error = -EINVAL; + + if (namelen > DLM_RESNAME_MAXLEN) + goto out; if (dlm_no_directory(ls)) flags |= R_CREATE; + error = 0; hash = jhash(name, namelen, 0); bucket = hash & (ls->ls_rsbtbl_size - 1); -- cgit v1.2.3 From a9cc9159281d44754f621f75d4efad0076b29db4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 26 Jan 2008 00:02:29 -0500 Subject: dlm: fix overflows when copying from ->m_extra to lvb Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/lock.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 6d98cf9d043..5b82187e022 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -1226,6 +1226,8 @@ static void set_lvb_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb, b = dlm_lvb_operations[lkb->lkb_grmode + 1][lkb->lkb_rqmode + 1]; if (b == 1) { int len = receive_extralen(ms); + if (len > DLM_RESNAME_MAXLEN) + len = DLM_RESNAME_MAXLEN; memcpy(lkb->lkb_lvbptr, ms->m_extra, len); lkb->lkb_lvbseq = ms->m_lvbseq; } @@ -2993,6 +2995,8 @@ static int receive_lvb(struct dlm_ls *ls, struct dlm_lkb *lkb, if (!lkb->lkb_lvbptr) return -ENOMEM; len = receive_extralen(ms); + if (len > DLM_RESNAME_MAXLEN) + len = DLM_RESNAME_MAXLEN; memcpy(lkb->lkb_lvbptr, ms->m_extra, len); } return 0; -- cgit v1.2.3 From 043b19cdc081f586a8f4e1c93ce6c03b63c26284 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 26 Jan 2008 00:03:59 -0500 Subject: dlm: fix dlm_dir_lookup() handling of too long names ... those can happen and BUG() from DLM_ASSERT() in allocate_direntry() is not a good way to handle them. Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/dir.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c index 831050e5bfd..85defeb64df 100644 --- a/fs/dlm/dir.c +++ b/fs/dlm/dir.c @@ -319,6 +319,9 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name, write_unlock(&ls->ls_dirtbl[bucket].lock); + if (namelen > DLM_RESNAME_MAXLEN) + return -EINVAL; + de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_KERNEL); if (!de) return -ENOMEM; -- cgit v1.2.3 From cb79f1998d89821a4dbac47f59a46ee3fbbf3c61 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 26 Jan 2008 16:49:44 -0500 Subject: dlm: dlm/user.c input validation fixes a) in device_write(): add sentinel NUL byte, making sure that lspace.name will be NUL-terminated b) in compat_input() be keep it simple about the amounts of data we are copying. Signed-off-by: Al Viro Signed-off-by: David Teigland --- fs/dlm/user.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 7cbc6826239..c3060458b68 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -82,7 +82,7 @@ struct dlm_lock_result32 { static void compat_input(struct dlm_write_request *kb, struct dlm_write_request32 *kb32, - int max_namelen) + size_t count) { kb->version[0] = kb32->version[0]; kb->version[1] = kb32->version[1]; @@ -94,7 +94,8 @@ static void compat_input(struct dlm_write_request *kb, kb->cmd == DLM_USER_REMOVE_LOCKSPACE) { kb->i.lspace.flags = kb32->i.lspace.flags; 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) { kb->i.purge.nodeid = kb32->i.purge.nodeid; kb->i.purge.pid = kb32->i.purge.pid; @@ -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.lksb = (void *)(long)kb32->i.lock.lksb; 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, - kb->i.lock.namelen); - else - kb->i.lock.namelen = max_namelen; + memcpy(kb->i.lock.name, kb32->i.lock.name, count - + offsetof(struct dlm_write_request32, i.lock.name)); } } @@ -508,7 +506,7 @@ static ssize_t device_write(struct file *file, const char __user *buf, #endif return -EINVAL; - kbuf = kmalloc(count, GFP_KERNEL); + kbuf = kzalloc(count + 1, GFP_KERNEL); if (!kbuf) return -ENOMEM; @@ -526,15 +524,14 @@ static ssize_t device_write(struct file *file, const char __user *buf, if (!kbuf->is64bit) { struct dlm_write_request32 *k32buf; 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); if (!kbuf) return -ENOMEM; if (proc) set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags); - compat_input(kbuf, k32buf, - count - sizeof(struct dlm_write_request32)); + compat_input(kbuf, k32buf, count + 1); kfree(k32buf); } #endif -- cgit v1.2.3 From e5dae548b0b5397e070de793be925cfc5813ad95 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 6 Feb 2008 00:35:45 -0600 Subject: dlm: proper types for asts and basts Use proper types for ast and bast functions, and use consistent type for ast param. Signed-off-by: David Teigland --- fs/dlm/ast.c | 9 ++++----- fs/dlm/dlm_internal.h | 14 ++++++-------- fs/dlm/lock.c | 50 ++++++++++++++++++++++++++++++++------------------ fs/dlm/rcom.c | 4 ++-- 4 files changed, 44 insertions(+), 33 deletions(-) diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c index 6308122890c..8bf31e3fbf0 100644 --- a/fs/dlm/ast.c +++ b/fs/dlm/ast.c @@ -39,7 +39,6 @@ void dlm_add_ast(struct dlm_lkb *lkb, int type) dlm_user_add_ast(lkb, type); return; } - DLM_ASSERT(lkb->lkb_astaddr != DLM_FAKE_USER_AST, dlm_print_lkb(lkb);); spin_lock(&ast_queue_lock); if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) { @@ -58,8 +57,8 @@ static void process_asts(void) struct dlm_ls *ls = NULL; struct dlm_rsb *r = NULL; struct dlm_lkb *lkb; - void (*cast) (long param); - void (*bast) (long param, int mode); + void (*cast) (void *astparam); + void (*bast) (void *astparam, int mode); int type = 0, found, bmode; for (;;) { @@ -83,8 +82,8 @@ static void process_asts(void) if (!found) break; - cast = lkb->lkb_astaddr; - bast = lkb->lkb_bastaddr; + cast = lkb->lkb_astfn; + bast = lkb->lkb_bastfn; bmode = lkb->lkb_bastmode; if ((type & AST_COMP) && cast) diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index f7fbaec94b1..a53c237f310 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -92,8 +92,6 @@ do { \ } \ } -#define DLM_FAKE_USER_AST ERR_PTR(-EINVAL) - struct dlm_direntry { struct list_head list; @@ -146,9 +144,9 @@ struct dlm_recover { struct dlm_args { uint32_t flags; - void *astaddr; - long astparam; - void *bastaddr; + void (*astfn) (void *astparam); + void *astparam; + void (*bastfn) (void *astparam, int mode); int mode; struct dlm_lksb *lksb; unsigned long timeout; @@ -253,9 +251,9 @@ struct dlm_lkb { char *lkb_lvbptr; struct dlm_lksb *lkb_lksb; /* caller's status block */ - void *lkb_astaddr; /* caller's ast function */ - void *lkb_bastaddr; /* caller's bast function */ - long lkb_astparam; /* caller's ast arg */ + void (*lkb_astfn) (void *astparam); + void (*lkb_bastfn) (void *astparam, int mode); + void *lkb_astparam; /* caller's ast arg */ }; diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 5b82187e022..94f8cbd3c0b 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -1781,7 +1781,7 @@ static void grant_pending_locks(struct dlm_rsb *r) */ list_for_each_entry_safe(lkb, s, &r->res_grantqueue, lkb_statequeue) { - if (lkb->lkb_bastaddr && lock_requires_bast(lkb, high, cw)) { + if (lkb->lkb_bastfn && lock_requires_bast(lkb, high, cw)) { if (cw && high == DLM_LOCK_PR) queue_bast(r, lkb, DLM_LOCK_CW); else @@ -1811,7 +1811,7 @@ static void send_bast_queue(struct dlm_rsb *r, struct list_head *head, struct dlm_lkb *gr; list_for_each_entry(gr, head, lkb_statequeue) { - if (gr->lkb_bastaddr && modes_require_bast(gr, lkb)) { + if (gr->lkb_bastfn && modes_require_bast(gr, lkb)) { queue_bast(r, gr, lkb->lkb_rqmode); gr->lkb_highbast = lkb->lkb_rqmode; } @@ -1966,8 +1966,11 @@ static void confirm_master(struct dlm_rsb *r, int error) } static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, - int namelen, unsigned long timeout_cs, void *ast, - void *astarg, void *bast, struct dlm_args *args) + int namelen, unsigned long timeout_cs, + void (*ast) (void *astparam), + void *astparam, + void (*bast) (void *astparam, int mode), + struct dlm_args *args) { int rv = -EINVAL; @@ -2017,9 +2020,9 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, an active lkb cannot be modified before locking the rsb */ args->flags = flags; - args->astaddr = ast; - args->astparam = (long) astarg; - args->bastaddr = bast; + args->astfn = ast; + args->astparam = astparam; + args->bastfn = bast; args->timeout = timeout_cs; args->mode = mode; args->lksb = lksb; @@ -2038,7 +2041,7 @@ static int set_unlock_args(uint32_t flags, void *astarg, struct dlm_args *args) return -EINVAL; args->flags = flags; - args->astparam = (long) astarg; + args->astparam = astarg; return 0; } @@ -2068,9 +2071,9 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, lkb->lkb_exflags = args->flags; lkb->lkb_sbflags = 0; - lkb->lkb_astaddr = args->astaddr; + lkb->lkb_astfn = args->astfn; lkb->lkb_astparam = args->astparam; - lkb->lkb_bastaddr = args->bastaddr; + lkb->lkb_bastfn = args->bastfn; lkb->lkb_rqmode = args->mode; lkb->lkb_lksb = args->lksb; lkb->lkb_lvbptr = args->lksb->sb_lvbptr; @@ -2717,9 +2720,9 @@ static void send_args(struct dlm_rsb *r, struct dlm_lkb *lkb, /* m_result and m_bastmode are set from function args, not from lkb fields */ - if (lkb->lkb_bastaddr) + if (lkb->lkb_bastfn) ms->m_asts |= AST_BAST; - if (lkb->lkb_astaddr) + if (lkb->lkb_astfn) ms->m_asts |= AST_COMP; /* compare with switch in create_message; send_remove() doesn't @@ -3002,6 +3005,16 @@ static int receive_lvb(struct dlm_ls *ls, struct dlm_lkb *lkb, return 0; } +static void fake_bastfn(void *astparam, int mode) +{ + log_print("fake_bastfn should not be called"); +} + +static void fake_astfn(void *astparam) +{ + log_print("fake_astfn should not be called"); +} + static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb, struct dlm_message *ms) { @@ -3010,8 +3023,9 @@ static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb, lkb->lkb_remid = ms->m_lkid; lkb->lkb_grmode = DLM_LOCK_IV; lkb->lkb_rqmode = ms->m_rqmode; - lkb->lkb_bastaddr = (void *) (long) (ms->m_asts & AST_BAST); - lkb->lkb_astaddr = (void *) (long) (ms->m_asts & AST_COMP); + + lkb->lkb_bastfn = (ms->m_asts & AST_BAST) ? &fake_bastfn : NULL; + lkb->lkb_astfn = (ms->m_asts & AST_COMP) ? &fake_astfn : NULL; if (lkb->lkb_exflags & DLM_LKF_VALBLK) { /* lkb was just created so there won't be an lvb yet */ @@ -4291,8 +4305,8 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, lkb->lkb_grmode = rl->rl_grmode; /* don't set lkb_status because add_lkb wants to itself */ - lkb->lkb_bastaddr = (void *) (long) (rl->rl_asts & AST_BAST); - lkb->lkb_astaddr = (void *) (long) (rl->rl_asts & AST_COMP); + lkb->lkb_bastfn = (rl->rl_asts & AST_BAST) ? &fake_bastfn : NULL; + lkb->lkb_astfn = (rl->rl_asts & AST_COMP) ? &fake_astfn : NULL; if (lkb->lkb_exflags & DLM_LKF_VALBLK) { int lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) - @@ -4466,7 +4480,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, lock and that lkb_astparam is the dlm_user_args structure. */ error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs, - DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); + fake_astfn, ua, fake_bastfn, &args); lkb->lkb_flags |= DLM_IFL_USER; ua->old_mode = DLM_LOCK_IV; @@ -4540,7 +4554,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, ua->old_mode = lkb->lkb_grmode; error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs, - DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); + fake_astfn, ua, fake_bastfn, &args); if (error) goto out_put; diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index ef9d0f91849..035e6f9990b 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c @@ -318,9 +318,9 @@ static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, rl->rl_status = lkb->lkb_status; rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type); - if (lkb->lkb_bastaddr) + if (lkb->lkb_bastfn) rl->rl_asts |= AST_BAST; - if (lkb->lkb_astaddr) + if (lkb->lkb_astfn) rl->rl_asts |= AST_COMP; rl->rl_namelen = cpu_to_le16(r->res_length); -- cgit v1.2.3 From d292c0cc489fa642799494bddbd7c94d11f7bbc1 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 6 Feb 2008 23:27:04 -0600 Subject: dlm: eliminate astparam type casting Put lkb_astparam in a union with a dlm_user_args pointer to eliminate a lot of type casting. Signed-off-by: David Teigland --- fs/dlm/debug_fs.c | 6 ++---- fs/dlm/dlm_internal.h | 5 ++++- fs/dlm/lock.c | 14 ++++++-------- fs/dlm/memory.c | 2 +- fs/dlm/netlink.c | 5 ++--- fs/dlm/user.c | 8 +++----- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 12c3bfd5e66..52b11960a17 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c @@ -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) { - struct dlm_user_args *ua; unsigned int waiting = 0; uint64_t xid = 0; if (lkb->lkb_flags & DLM_IFL_USER) { - ua = (struct dlm_user_args *) lkb->lkb_astparam; - if (ua) - xid = ua->xid; + if (lkb->lkb_ua) + xid = lkb->lkb_ua->xid; } if (lkb->lkb_timestamp) diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index a53c237f310..d30ea8b433a 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h @@ -253,7 +253,10 @@ struct dlm_lkb { struct dlm_lksb *lkb_lksb; /* caller's status block */ void (*lkb_astfn) (void *astparam); void (*lkb_bastfn) (void *astparam, int mode); - void *lkb_astparam; /* caller's ast arg */ + union { + void *lkb_astparam; /* caller's ast arg */ + struct dlm_user_args *lkb_ua; + }; }; diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 94f8cbd3c0b..8f250ac8b92 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -4533,7 +4533,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, /* user can change the params on its lock when it converts it, or add an lvb that didn't exist before */ - ua = (struct dlm_user_args *)lkb->lkb_astparam; + ua = lkb->lkb_ua; if (flags & DLM_LKF_VALBLK && !ua->lksb.sb_lvbptr) { ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_KERNEL); @@ -4584,7 +4584,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, if (error) goto out; - ua = (struct dlm_user_args *)lkb->lkb_astparam; + ua = lkb->lkb_ua; if (lvb_in && ua->lksb.sb_lvbptr) memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); @@ -4633,7 +4633,7 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, if (error) goto out; - ua = (struct dlm_user_args *)lkb->lkb_astparam; + ua = lkb->lkb_ua; if (ua_tmp->castparam) ua->castparam = ua_tmp->castparam; ua->user_lksb = ua_tmp->user_lksb; @@ -4671,7 +4671,7 @@ int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid) if (error) goto out; - ua = (struct dlm_user_args *)lkb->lkb_astparam; + ua = lkb->lkb_ua; error = set_unlock_args(flags, ua, &args); if (error) @@ -4710,7 +4710,6 @@ int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid) static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) { - struct dlm_user_args *ua = (struct dlm_user_args *)lkb->lkb_astparam; struct dlm_args args; int error; @@ -4719,7 +4718,7 @@ static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans); mutex_unlock(&ls->ls_orphans_mutex); - set_unlock_args(0, ua, &args); + set_unlock_args(0, lkb->lkb_ua, &args); error = cancel_lock(ls, lkb, &args); if (error == -DLM_ECANCEL) @@ -4732,11 +4731,10 @@ static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) static int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) { - struct dlm_user_args *ua = (struct dlm_user_args *)lkb->lkb_astparam; struct dlm_args args; int error; - set_unlock_args(DLM_LKF_FORCEUNLOCK, ua, &args); + set_unlock_args(DLM_LKF_FORCEUNLOCK, lkb->lkb_ua, &args); error = unlock_lock(ls, lkb, &args); if (error == -DLM_EUNLOCK) diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c index f7783867491..65e41e5569b 100644 --- a/fs/dlm/memory.c +++ b/fs/dlm/memory.c @@ -80,7 +80,7 @@ void dlm_free_lkb(struct dlm_lkb *lkb) { if (lkb->lkb_flags & DLM_IFL_USER) { struct dlm_user_args *ua; - ua = (struct dlm_user_args *)lkb->lkb_astparam; + ua = lkb->lkb_ua; if (ua) { if (ua->lksb.sb_lvbptr) kfree(ua->lksb.sb_lvbptr); diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index 863b87d0dc7..90374b84876 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c @@ -104,7 +104,6 @@ void dlm_netlink_exit(void) static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb) { 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)); @@ -117,8 +116,8 @@ static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb) data->grmode = lkb->lkb_grmode; data->rqmode = lkb->lkb_rqmode; data->timestamp = lkb->lkb_timestamp; - if (ua) - data->xid = ua->xid; + if (lkb->lkb_ua) + data->xid = lkb->lkb_ua->xid; if (r) { data->lockspace_id = r->res_ls->ls_global_id; data->resource_namelen = r->res_length; diff --git a/fs/dlm/user.c b/fs/dlm/user.c index c3060458b68..70b31b91487 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -195,8 +195,8 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) goto out; - DLM_ASSERT(lkb->lkb_astparam, dlm_print_lkb(lkb);); - ua = (struct dlm_user_args *)lkb->lkb_astparam; + DLM_ASSERT(lkb->lkb_ua, dlm_print_lkb(lkb);); + ua = lkb->lkb_ua; proc = ua->proc; if (type == AST_BAST && ua->bastaddr == NULL) @@ -771,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_lkb *lkb; - struct dlm_user_args *ua; DECLARE_WAITQUEUE(wait, current); int error, type=0, bmode=0, removed = 0; @@ -842,8 +841,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, } spin_unlock(&proc->asts_spin); - ua = (struct dlm_user_args *)lkb->lkb_astparam; - error = copy_result_to_user(ua, + error = copy_result_to_user(lkb->lkb_ua, test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags), type, bmode, buf, count); -- cgit v1.2.3 From 30727174b6273c67fa96fb818fe5bdde1ad70e5c Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Sat, 2 Feb 2008 01:53:46 +0800 Subject: dlm: add __init and __exit marks to init and exit functions it moves 365 bytes from .text to .init.text, and 30 bytes from .text to .exit.text, saves memory. Signed-off-by: Denis Cheng Signed-off-by: David Teigland --- fs/dlm/config.c | 2 +- fs/dlm/debug_fs.c | 2 +- fs/dlm/lockspace.c | 2 +- fs/dlm/memory.c | 2 +- fs/dlm/netlink.c | 4 ++-- fs/dlm/user.c | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 2f8e3c81bc1..c3ad1dff3b2 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -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); mutex_init(&clusters_root.subsys.su_mutex); diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 52b11960a17..8fc24f4507a 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c @@ -541,7 +541,7 @@ void dlm_delete_debug_file(struct dlm_ls *ls) debugfs_remove(ls->ls_debug_locks_dentry); } -int dlm_register_debugfs(void) +int __init dlm_register_debugfs(void) { mutex_init(&debug_buf_lock); dlm_root = debugfs_create_dir("dlm", NULL); diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index b180fdc5108..b64e55e0515 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -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; mutex_init(&ls_lock); diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c index 65e41e5569b..54c14c6d06c 100644 --- a/fs/dlm/memory.c +++ b/fs/dlm/memory.c @@ -18,7 +18,7 @@ static struct kmem_cache *lkb_cache; -int dlm_memory_init(void) +int __init dlm_memory_init(void) { int ret = 0; diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index 90374b84876..714593621f4 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c @@ -78,7 +78,7 @@ static struct genl_ops dlm_nl_ops = { .doit = user_cmd, }; -int dlm_netlink_init(void) +int __init dlm_netlink_init(void) { int rv; @@ -95,7 +95,7 @@ int dlm_netlink_init(void) return rv; } -void dlm_netlink_exit(void) +void __exit dlm_netlink_exit(void) { genl_unregister_ops(&family, &dlm_nl_ops); genl_unregister_family(&family); diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 70b31b91487..ebbcf38fd33 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c @@ -902,7 +902,7 @@ static struct miscdevice ctl_device = { .minor = MISC_DYNAMIC_MINOR, }; -int dlm_user_init(void) +int __init dlm_user_init(void) { int error; -- cgit v1.2.3