fs: dlm: add more midcomms hooks
[linux-block.git] / fs / dlm / midcomms.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /******************************************************************************
3 *******************************************************************************
4 **
5 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
6 **  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
7 **
8 **
9 *******************************************************************************
10 ******************************************************************************/
11
12 /*
13  * midcomms.c
14  *
15  * This is the appallingly named "mid-level" comms layer.
16  *
17  * Its purpose is to take packets from the "real" comms layer,
18  * split them up into packets and pass them to the interested
19  * part of the locking mechanism.
20  *
21  * It also takes messages from the locking layer, formats them
22  * into packets and sends them to the comms layer.
23  */
24
25 #include "dlm_internal.h"
26 #include "lowcomms.h"
27 #include "config.h"
28 #include "lock.h"
29 #include "midcomms.h"
30
31 struct dlm_mhandle *dlm_midcomms_get_mhandle(int nodeid, int len,
32                                              gfp_t allocation, char **ppc)
33 {
34         return dlm_lowcomms_get_buffer(nodeid, len, allocation, ppc);
35 }
36
37 void dlm_midcomms_commit_mhandle(struct dlm_mhandle *mh)
38 {
39         dlm_lowcomms_commit_buffer(mh);
40 }
41
42 void dlm_midcomms_add_member(int nodeid) { }
43
44 void dlm_midcomms_remove_member(int nodeid) { }
45
46 int dlm_midcomms_start(void)
47 {
48         return dlm_lowcomms_start();
49 }
50
51 void dlm_midcomms_shutdown(void)
52 {
53         dlm_lowcomms_shutdown();
54 }
55
56 int dlm_midcomms_close(int nodeid)
57 {
58         return dlm_lowcomms_close(nodeid);
59 }
60
61 /*
62  * Called from the low-level comms layer to process a buffer of
63  * commands.
64  */
65
66 int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len)
67 {
68         const unsigned char *ptr = buf;
69         const struct dlm_header *hd;
70         uint16_t msglen;
71         int ret = 0;
72
73         while (len >= sizeof(struct dlm_header)) {
74                 hd = (struct dlm_header *)ptr;
75
76                 /* no message should be more than DEFAULT_BUFFER_SIZE or
77                  * less than dlm_header size.
78                  *
79                  * Some messages does not have a 8 byte length boundary yet
80                  * which can occur in a unaligned memory access of some dlm
81                  * messages. However this problem need to be fixed at the
82                  * sending side, for now it seems nobody run into architecture
83                  * related issues yet but it slows down some processing.
84                  * Fixing this issue should be scheduled in future by doing
85                  * the next major version bump.
86                  */
87                 msglen = le16_to_cpu(hd->h_length);
88                 if (msglen > DEFAULT_BUFFER_SIZE ||
89                     msglen < sizeof(struct dlm_header)) {
90                         log_print("received invalid length header: %u from node %d, will abort message parsing",
91                                   msglen, nodeid);
92                         return -EBADMSG;
93                 }
94
95                 /* caller will take care that leftover
96                  * will be parsed next call with more data
97                  */
98                 if (msglen > len)
99                         break;
100
101                 switch (hd->h_cmd) {
102                 case DLM_MSG:
103                         if (msglen < sizeof(struct dlm_message)) {
104                                 log_print("dlm msg too small: %u, will skip this message",
105                                           msglen);
106                                 goto skip;
107                         }
108
109                         break;
110                 case DLM_RCOM:
111                         if (msglen < sizeof(struct dlm_rcom)) {
112                                 log_print("dlm rcom msg too small: %u, will skip this message",
113                                           msglen);
114                                 goto skip;
115                         }
116
117                         break;
118                 default:
119                         log_print("unsupported h_cmd received: %u, will skip this message",
120                                   hd->h_cmd);
121                         goto skip;
122                 }
123
124                 dlm_receive_buffer((union dlm_packet *)ptr, nodeid);
125
126 skip:
127                 ret += msglen;
128                 len -= msglen;
129                 ptr += msglen;
130         }
131
132         return ret;
133 }