hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/fs/dlm/midcomms.c
....@@ -1,12 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /******************************************************************************
23 *******************************************************************************
34 **
45 ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
56 ** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
67 **
7
-** This copyrighted material is made available to anyone wishing to use,
8
-** modify, copy, or redistribute it subject to the terms and conditions
9
-** of the GNU General Public License v.2.
108 **
119 *******************************************************************************
1210 ******************************************************************************/
....@@ -24,114 +22,85 @@
2422 * into packets and sends them to the comms layer.
2523 */
2624
25
+#include <asm/unaligned.h>
26
+
2727 #include "dlm_internal.h"
2828 #include "lowcomms.h"
2929 #include "config.h"
3030 #include "lock.h"
3131 #include "midcomms.h"
3232
33
-
34
-static void copy_from_cb(void *dst, const void *base, unsigned offset,
35
- unsigned len, unsigned limit)
36
-{
37
- unsigned copy = len;
38
-
39
- if ((copy + offset) > limit)
40
- copy = limit - offset;
41
- memcpy(dst, base + offset, copy);
42
- len -= copy;
43
- if (len)
44
- memcpy(dst + copy, base, len);
45
-}
46
-
4733 /*
4834 * Called from the low-level comms layer to process a buffer of
4935 * commands.
50
- *
51
- * Only complete messages are processed here, any "spare" bytes from
52
- * the end of a buffer are saved and tacked onto the front of the next
53
- * message that comes in. I doubt this will happen very often but we
54
- * need to be able to cope with it and I don't want the task to be waiting
55
- * for packets to come in when there is useful work to be done.
5636 */
5737
58
-int dlm_process_incoming_buffer(int nodeid, const void *base,
59
- unsigned offset, unsigned len, unsigned limit)
38
+int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len)
6039 {
61
- union {
62
- unsigned char __buf[DLM_INBUF_LEN];
63
- /* this is to force proper alignment on some arches */
64
- union dlm_packet p;
65
- } __tmp;
66
- union dlm_packet *p = &__tmp.p;
67
- int ret = 0;
68
- int err = 0;
40
+ const unsigned char *ptr = buf;
41
+ const struct dlm_header *hd;
6942 uint16_t msglen;
70
- uint32_t lockspace;
43
+ int ret = 0;
7144
72
- while (len > sizeof(struct dlm_header)) {
45
+ while (len >= sizeof(struct dlm_header)) {
46
+ hd = (struct dlm_header *)ptr;
7347
74
- /* Copy just the header to check the total length. The
75
- message may wrap around the end of the buffer back to the
76
- start, so we need to use a temp buffer and copy_from_cb. */
77
-
78
- copy_from_cb(p, base, offset, sizeof(struct dlm_header),
79
- limit);
80
-
81
- msglen = le16_to_cpu(p->header.h_length);
82
- lockspace = p->header.h_lockspace;
83
-
84
- err = -EINVAL;
85
- if (msglen < sizeof(struct dlm_header))
86
- break;
87
- if (p->header.h_cmd == DLM_MSG) {
88
- if (msglen < sizeof(struct dlm_message))
89
- break;
90
- } else {
91
- if (msglen < sizeof(struct dlm_rcom))
92
- break;
48
+ /* no message should be more than this otherwise we
49
+ * cannot deliver this message to upper layers
50
+ */
51
+ msglen = get_unaligned_le16(&hd->h_length);
52
+ if (msglen > DEFAULT_BUFFER_SIZE ||
53
+ msglen < sizeof(struct dlm_header)) {
54
+ log_print("received invalid length header: %u from node %d, will abort message parsing",
55
+ msglen, nodeid);
56
+ return -EBADMSG;
9357 }
94
- err = -E2BIG;
95
- if (msglen > dlm_config.ci_buffer_size) {
96
- log_print("message size %d from %d too big, buf len %d",
97
- msglen, nodeid, len);
98
- break;
99
- }
100
- err = 0;
10158
102
- /* If only part of the full message is contained in this
103
- buffer, then do nothing and wait for lowcomms to call
104
- us again later with more data. We return 0 meaning
105
- we've consumed none of the input buffer. */
106
-
59
+ /* caller will take care that leftover
60
+ * will be parsed next call with more data
61
+ */
10762 if (msglen > len)
10863 break;
10964
110
- /* Allocate a larger temp buffer if the full message won't fit
111
- in the buffer on the stack (which should work for most
112
- ordinary messages). */
65
+ switch (hd->h_cmd) {
66
+ case DLM_MSG:
67
+ if (msglen < sizeof(struct dlm_message)) {
68
+ log_print("dlm msg too small: %u, will skip this message",
69
+ msglen);
70
+ goto skip;
71
+ }
11372
114
- if (msglen > sizeof(__tmp) && p == &__tmp.p) {
115
- p = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
116
- if (p == NULL)
117
- return ret;
73
+ break;
74
+ case DLM_RCOM:
75
+ if (msglen < sizeof(struct dlm_rcom)) {
76
+ log_print("dlm rcom msg too small: %u, will skip this message",
77
+ msglen);
78
+ goto skip;
79
+ }
80
+
81
+ break;
82
+ default:
83
+ log_print("unsupported h_cmd received: %u, will skip this message",
84
+ hd->h_cmd);
85
+ goto skip;
11886 }
11987
120
- copy_from_cb(p, base, offset, msglen, limit);
88
+ /* for aligned memory access, we just copy current message
89
+ * to begin of the buffer which contains already parsed buffer
90
+ * data and should provide align access for upper layers
91
+ * because the start address of the buffer has a aligned
92
+ * address. This memmove can be removed when the upperlayer
93
+ * is capable of unaligned memory access.
94
+ */
95
+ memmove(buf, ptr, msglen);
96
+ dlm_receive_buffer((union dlm_packet *)buf, nodeid);
12197
122
- BUG_ON(lockspace != p->header.h_lockspace);
123
-
98
+skip:
12499 ret += msglen;
125
- offset += msglen;
126
- offset &= (limit - 1);
127100 len -= msglen;
128
-
129
- dlm_receive_buffer(p, nodeid);
101
+ ptr += msglen;
130102 }
131103
132
- if (p != &__tmp.p)
133
- kfree(p);
134
-
135
- return err ? err : ret;
104
+ return ret;
136105 }
137106