1#ifndef __FS_CEPH_MESSENGER_H
2#define __FS_CEPH_MESSENGER_H
3
4#include <linux/blk_types.h>
5#include <linux/kref.h>
6#include <linux/mutex.h>
7#include <linux/net.h>
8#include <linux/radix-tree.h>
9#include <linux/uio.h>
10#include <linux/workqueue.h>
11
12#include <linux/ceph/types.h>
13#include <linux/ceph/buffer.h>
14
15struct ceph_msg;
16struct ceph_connection;
17
18/*
19 * Ceph defines these callbacks for handling connection events.
20 */
21struct ceph_connection_operations {
22	struct ceph_connection *(*get)(struct ceph_connection *);
23	void (*put)(struct ceph_connection *);
24
25	/* handle an incoming message. */
26	void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m);
27
28	/* authorize an outgoing connection */
29	struct ceph_auth_handshake *(*get_authorizer) (
30				struct ceph_connection *con,
31			       int *proto, int force_new);
32	int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
33	int (*invalidate_authorizer)(struct ceph_connection *con);
34
35	/* there was some error on the socket (disconnect, whatever) */
36	void (*fault) (struct ceph_connection *con);
37
38	/* a remote host as terminated a message exchange session, and messages
39	 * we sent (or they tried to send us) may be lost. */
40	void (*peer_reset) (struct ceph_connection *con);
41
42	struct ceph_msg * (*alloc_msg) (struct ceph_connection *con,
43					struct ceph_msg_header *hdr,
44					int *skip);
45	int (*sign_message) (struct ceph_connection *con, struct ceph_msg *msg);
46
47	int (*check_message_signature) (struct ceph_connection *con,
48					struct ceph_msg *msg);
49};
50
51/* use format string %s%d */
52#define ENTITY_NAME(n) ceph_entity_type_name((n).type), le64_to_cpu((n).num)
53
54struct ceph_messenger {
55	struct ceph_entity_inst inst;    /* my name+address */
56	struct ceph_entity_addr my_enc_addr;
57
58	atomic_t stopping;
59	bool nocrc;
60	bool tcp_nodelay;
61
62	/*
63	 * the global_seq counts connections i (attempt to) initiate
64	 * in order to disambiguate certain connect race conditions.
65	 */
66	u32 global_seq;
67	spinlock_t global_seq_lock;
68
69	u64 supported_features;
70	u64 required_features;
71};
72
73enum ceph_msg_data_type {
74	CEPH_MSG_DATA_NONE,	/* message contains no data payload */
75	CEPH_MSG_DATA_PAGES,	/* data source/destination is a page array */
76	CEPH_MSG_DATA_PAGELIST,	/* data source/destination is a pagelist */
77#ifdef CONFIG_BLOCK
78	CEPH_MSG_DATA_BIO,	/* data source/destination is a bio list */
79#endif /* CONFIG_BLOCK */
80};
81
82static __inline__ bool ceph_msg_data_type_valid(enum ceph_msg_data_type type)
83{
84	switch (type) {
85	case CEPH_MSG_DATA_NONE:
86	case CEPH_MSG_DATA_PAGES:
87	case CEPH_MSG_DATA_PAGELIST:
88#ifdef CONFIG_BLOCK
89	case CEPH_MSG_DATA_BIO:
90#endif /* CONFIG_BLOCK */
91		return true;
92	default:
93		return false;
94	}
95}
96
97struct ceph_msg_data {
98	struct list_head		links;	/* ceph_msg->data */
99	enum ceph_msg_data_type		type;
100	union {
101#ifdef CONFIG_BLOCK
102		struct {
103			struct bio	*bio;
104			size_t		bio_length;
105		};
106#endif /* CONFIG_BLOCK */
107		struct {
108			struct page	**pages;	/* NOT OWNER. */
109			size_t		length;		/* total # bytes */
110			unsigned int	alignment;	/* first page */
111		};
112		struct ceph_pagelist	*pagelist;
113	};
114};
115
116struct ceph_msg_data_cursor {
117	size_t			total_resid;	/* across all data items */
118	struct list_head	*data_head;	/* = &ceph_msg->data */
119
120	struct ceph_msg_data	*data;		/* current data item */
121	size_t			resid;		/* bytes not yet consumed */
122	bool			last_piece;	/* current is last piece */
123	bool			need_crc;	/* crc update needed */
124	union {
125#ifdef CONFIG_BLOCK
126		struct {				/* bio */
127			struct bio	*bio;		/* bio from list */
128			struct bvec_iter bvec_iter;
129		};
130#endif /* CONFIG_BLOCK */
131		struct {				/* pages */
132			unsigned int	page_offset;	/* offset in page */
133			unsigned short	page_index;	/* index in array */
134			unsigned short	page_count;	/* pages in array */
135		};
136		struct {				/* pagelist */
137			struct page	*page;		/* page from list */
138			size_t		offset;		/* bytes from list */
139		};
140	};
141};
142
143/*
144 * a single message.  it contains a header (src, dest, message type, etc.),
145 * footer (crc values, mainly), a "front" message body, and possibly a
146 * data payload (stored in some number of pages).
147 */
148struct ceph_msg {
149	struct ceph_msg_header hdr;	/* header */
150	union {
151		struct ceph_msg_footer footer;		/* footer */
152		struct ceph_msg_footer_old old_footer;	/* old format footer */
153	};
154	struct kvec front;              /* unaligned blobs of message */
155	struct ceph_buffer *middle;
156
157	size_t				data_length;
158	struct list_head		data;
159	struct ceph_msg_data_cursor	cursor;
160
161	struct ceph_connection *con;
162	struct list_head list_head;	/* links for connection lists */
163
164	struct kref kref;
165	bool more_to_follow;
166	bool needs_out_seq;
167	int front_alloc_len;
168	unsigned long ack_stamp;        /* tx: when we were acked */
169
170	struct ceph_msgpool *pool;
171};
172
173/* ceph connection fault delay defaults, for exponential backoff */
174#define BASE_DELAY_INTERVAL	(HZ/2)
175#define MAX_DELAY_INTERVAL	(5 * 60 * HZ)
176
177/*
178 * A single connection with another host.
179 *
180 * We maintain a queue of outgoing messages, and some session state to
181 * ensure that we can preserve the lossless, ordered delivery of
182 * messages in the case of a TCP disconnect.
183 */
184struct ceph_connection {
185	void *private;
186
187	const struct ceph_connection_operations *ops;
188
189	struct ceph_messenger *msgr;
190
191	atomic_t sock_state;
192	struct socket *sock;
193	struct ceph_entity_addr peer_addr; /* peer address */
194	struct ceph_entity_addr peer_addr_for_me;
195
196	unsigned long flags;
197	unsigned long state;
198	const char *error_msg;  /* error message, if any */
199
200	struct ceph_entity_name peer_name; /* peer name */
201
202	u64 peer_features;
203	u32 connect_seq;      /* identify the most recent connection
204				 attempt for this connection, client */
205	u32 peer_global_seq;  /* peer's global seq for this connection */
206
207	int auth_retry;       /* true if we need a newer authorizer */
208	void *auth_reply_buf;   /* where to put the authorizer reply */
209	int auth_reply_buf_len;
210
211	struct mutex mutex;
212
213	/* out queue */
214	struct list_head out_queue;
215	struct list_head out_sent;   /* sending or sent but unacked */
216	u64 out_seq;		     /* last message queued for send */
217
218	u64 in_seq, in_seq_acked;  /* last message received, acked */
219
220	/* connection negotiation temps */
221	char in_banner[CEPH_BANNER_MAX_LEN];
222	struct ceph_msg_connect out_connect;
223	struct ceph_msg_connect_reply in_reply;
224	struct ceph_entity_addr actual_peer_addr;
225
226	/* message out temps */
227	struct ceph_msg_header out_hdr;
228	struct ceph_msg *out_msg;        /* sending message (== tail of
229					    out_sent) */
230	bool out_msg_done;
231
232	struct kvec out_kvec[8],         /* sending header/footer data */
233		*out_kvec_cur;
234	int out_kvec_left;   /* kvec's left in out_kvec */
235	int out_skip;        /* skip this many bytes */
236	int out_kvec_bytes;  /* total bytes left */
237	int out_more;        /* there is more data after the kvecs */
238	__le64 out_temp_ack; /* for writing an ack */
239
240	/* message in temps */
241	struct ceph_msg_header in_hdr;
242	struct ceph_msg *in_msg;
243	u32 in_front_crc, in_middle_crc, in_data_crc;  /* calculated crc */
244
245	char in_tag;         /* protocol control byte */
246	int in_base_pos;     /* bytes read */
247	__le64 in_temp_ack;  /* for reading an ack */
248
249	struct delayed_work work;	    /* send|recv work */
250	unsigned long       delay;          /* current delay interval */
251};
252
253
254extern const char *ceph_pr_addr(const struct sockaddr_storage *ss);
255extern int ceph_parse_ips(const char *c, const char *end,
256			  struct ceph_entity_addr *addr,
257			  int max_count, int *count);
258
259
260extern int ceph_msgr_init(void);
261extern void ceph_msgr_exit(void);
262extern void ceph_msgr_flush(void);
263
264extern void ceph_messenger_init(struct ceph_messenger *msgr,
265			struct ceph_entity_addr *myaddr,
266			u64 supported_features,
267			u64 required_features,
268			bool nocrc,
269			bool tcp_nodelay);
270
271extern void ceph_con_init(struct ceph_connection *con, void *private,
272			const struct ceph_connection_operations *ops,
273			struct ceph_messenger *msgr);
274extern void ceph_con_open(struct ceph_connection *con,
275			  __u8 entity_type, __u64 entity_num,
276			  struct ceph_entity_addr *addr);
277extern bool ceph_con_opened(struct ceph_connection *con);
278extern void ceph_con_close(struct ceph_connection *con);
279extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg);
280
281extern void ceph_msg_revoke(struct ceph_msg *msg);
282extern void ceph_msg_revoke_incoming(struct ceph_msg *msg);
283
284extern void ceph_con_keepalive(struct ceph_connection *con);
285
286extern void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages,
287				size_t length, size_t alignment);
288extern void ceph_msg_data_add_pagelist(struct ceph_msg *msg,
289				struct ceph_pagelist *pagelist);
290#ifdef CONFIG_BLOCK
291extern void ceph_msg_data_add_bio(struct ceph_msg *msg, struct bio *bio,
292				size_t length);
293#endif /* CONFIG_BLOCK */
294
295extern struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags,
296				     bool can_fail);
297
298extern struct ceph_msg *ceph_msg_get(struct ceph_msg *msg);
299extern void ceph_msg_put(struct ceph_msg *msg);
300
301extern void ceph_msg_dump(struct ceph_msg *msg);
302
303#endif
304