summaryrefslogtreecommitdiff
path: root/fs/dlm/midcomms.c
blob: aadb3781bebe27d54c0a11f4454136c7cdf9dbdc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
**
**
*******************************************************************************
******************************************************************************/

/*
 * midcomms.c
 *
 * This is the appallingly named "mid-level" comms layer.
 *
 * Its purpose is to take packets from the "real" comms layer,
 * split them up into packets and pass them to the interested
 * part of the locking mechanism.
 *
 * It also takes messages from the locking layer, formats them
 * into packets and sends them to the comms layer.
 */

#include "dlm_internal.h"
#include "lowcomms.h"
#include "config.h"
#include "lock.h"
#include "midcomms.h"

struct dlm_mhandle *dlm_midcomms_get_mhandle(int nodeid, int len,
					     gfp_t allocation, char **ppc)
{
	return (struct dlm_mhandle *)dlm_lowcomms_new_msg(nodeid, len,
							  allocation, ppc,
							  NULL, NULL);
}

void dlm_midcomms_commit_mhandle(struct dlm_mhandle *mh)
{
	dlm_lowcomms_commit_msg((struct dlm_msg *)mh);
	dlm_lowcomms_put_msg((struct dlm_msg *)mh);
}

void dlm_midcomms_add_member(int nodeid) { }

void dlm_midcomms_remove_member(int nodeid) { }

int dlm_midcomms_start(void)
{
	return dlm_lowcomms_start();
}

void dlm_midcomms_shutdown(void)
{
	dlm_lowcomms_shutdown();
}

int dlm_midcomms_close(int nodeid)
{
	return dlm_lowcomms_close(nodeid);
}

/*
 * Called from the low-level comms layer to process a buffer of
 * commands.
 */

int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len)
{
	const unsigned char *ptr = buf;
	const struct dlm_header *hd;
	uint16_t msglen;
	int ret = 0;

	while (len >= sizeof(struct dlm_header)) {
		hd = (struct dlm_header *)ptr;

		/* no message should be more than DEFAULT_BUFFER_SIZE or
		 * less than dlm_header size.
		 *
		 * Some messages does not have a 8 byte length boundary yet
		 * which can occur in a unaligned memory access of some dlm
		 * messages. However this problem need to be fixed at the
		 * sending side, for now it seems nobody run into architecture
		 * related issues yet but it slows down some processing.
		 * Fixing this issue should be scheduled in future by doing
		 * the next major version bump.
		 */
		msglen = le16_to_cpu(hd->h_length);
		if (msglen > DEFAULT_BUFFER_SIZE ||
		    msglen < sizeof(struct dlm_header)) {
			log_print("received invalid length header: %u from node %d, will abort message parsing",
				  msglen, nodeid);
			return -EBADMSG;
		}

		/* caller will take care that leftover
		 * will be parsed next call with more data
		 */
		if (msglen > len)
			break;

		switch (hd->h_cmd) {
		case DLM_MSG:
			if (msglen < sizeof(struct dlm_message)) {
				log_print("dlm msg too small: %u, will skip this message",
					  msglen);
				goto skip;
			}

			break;
		case DLM_RCOM:
			if (msglen < sizeof(struct dlm_rcom)) {
				log_print("dlm rcom msg too small: %u, will skip this message",
					  msglen);
				goto skip;
			}

			break;
		default:
			log_print("unsupported h_cmd received: %u, will skip this message",
				  hd->h_cmd);
			goto skip;
		}

		dlm_receive_buffer((union dlm_packet *)ptr, nodeid);

skip:
		ret += msglen;
		len -= msglen;
		ptr += msglen;
	}

	return ret;
}