xref: /OK3568_Linux_fs/kernel/include/linux/ceph/decode.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef __CEPH_DECODE_H
3*4882a593Smuzhiyun #define __CEPH_DECODE_H
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <linux/err.h>
6*4882a593Smuzhiyun #include <linux/bug.h>
7*4882a593Smuzhiyun #include <linux/slab.h>
8*4882a593Smuzhiyun #include <linux/time.h>
9*4882a593Smuzhiyun #include <asm/unaligned.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/ceph/types.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun  * in all cases,
15*4882a593Smuzhiyun  *   void **p     pointer to position pointer
16*4882a593Smuzhiyun  *   void *end    pointer to end of buffer (last byte + 1)
17*4882a593Smuzhiyun  */
18*4882a593Smuzhiyun 
ceph_decode_64(void ** p)19*4882a593Smuzhiyun static inline u64 ceph_decode_64(void **p)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	u64 v = get_unaligned_le64(*p);
22*4882a593Smuzhiyun 	*p += sizeof(u64);
23*4882a593Smuzhiyun 	return v;
24*4882a593Smuzhiyun }
ceph_decode_32(void ** p)25*4882a593Smuzhiyun static inline u32 ceph_decode_32(void **p)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	u32 v = get_unaligned_le32(*p);
28*4882a593Smuzhiyun 	*p += sizeof(u32);
29*4882a593Smuzhiyun 	return v;
30*4882a593Smuzhiyun }
ceph_decode_16(void ** p)31*4882a593Smuzhiyun static inline u16 ceph_decode_16(void **p)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	u16 v = get_unaligned_le16(*p);
34*4882a593Smuzhiyun 	*p += sizeof(u16);
35*4882a593Smuzhiyun 	return v;
36*4882a593Smuzhiyun }
ceph_decode_8(void ** p)37*4882a593Smuzhiyun static inline u8 ceph_decode_8(void **p)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	u8 v = *(u8 *)*p;
40*4882a593Smuzhiyun 	(*p)++;
41*4882a593Smuzhiyun 	return v;
42*4882a593Smuzhiyun }
ceph_decode_copy(void ** p,void * pv,size_t n)43*4882a593Smuzhiyun static inline void ceph_decode_copy(void **p, void *pv, size_t n)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	memcpy(pv, *p, n);
46*4882a593Smuzhiyun 	*p += n;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun /*
50*4882a593Smuzhiyun  * bounds check input.
51*4882a593Smuzhiyun  */
ceph_has_room(void ** p,void * end,size_t n)52*4882a593Smuzhiyun static inline bool ceph_has_room(void **p, void *end, size_t n)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	return end >= *p && n <= end - *p;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #define ceph_decode_need(p, end, n, bad)			\
58*4882a593Smuzhiyun 	do {							\
59*4882a593Smuzhiyun 		if (!likely(ceph_has_room(p, end, n)))		\
60*4882a593Smuzhiyun 			goto bad;				\
61*4882a593Smuzhiyun 	} while (0)
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #define ceph_decode_64_safe(p, end, v, bad)			\
64*4882a593Smuzhiyun 	do {							\
65*4882a593Smuzhiyun 		ceph_decode_need(p, end, sizeof(u64), bad);	\
66*4882a593Smuzhiyun 		v = ceph_decode_64(p);				\
67*4882a593Smuzhiyun 	} while (0)
68*4882a593Smuzhiyun #define ceph_decode_32_safe(p, end, v, bad)			\
69*4882a593Smuzhiyun 	do {							\
70*4882a593Smuzhiyun 		ceph_decode_need(p, end, sizeof(u32), bad);	\
71*4882a593Smuzhiyun 		v = ceph_decode_32(p);				\
72*4882a593Smuzhiyun 	} while (0)
73*4882a593Smuzhiyun #define ceph_decode_16_safe(p, end, v, bad)			\
74*4882a593Smuzhiyun 	do {							\
75*4882a593Smuzhiyun 		ceph_decode_need(p, end, sizeof(u16), bad);	\
76*4882a593Smuzhiyun 		v = ceph_decode_16(p);				\
77*4882a593Smuzhiyun 	} while (0)
78*4882a593Smuzhiyun #define ceph_decode_8_safe(p, end, v, bad)			\
79*4882a593Smuzhiyun 	do {							\
80*4882a593Smuzhiyun 		ceph_decode_need(p, end, sizeof(u8), bad);	\
81*4882a593Smuzhiyun 		v = ceph_decode_8(p);				\
82*4882a593Smuzhiyun 	} while (0)
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #define ceph_decode_copy_safe(p, end, pv, n, bad)		\
85*4882a593Smuzhiyun 	do {							\
86*4882a593Smuzhiyun 		ceph_decode_need(p, end, n, bad);		\
87*4882a593Smuzhiyun 		ceph_decode_copy(p, pv, n);			\
88*4882a593Smuzhiyun 	} while (0)
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun  * Allocate a buffer big enough to hold the wire-encoded string, and
92*4882a593Smuzhiyun  * decode the string into it.  The resulting string will always be
93*4882a593Smuzhiyun  * terminated with '\0'.  If successful, *p will be advanced
94*4882a593Smuzhiyun  * past the decoded data.  Also, if lenp is not a null pointer, the
95*4882a593Smuzhiyun  * length (not including the terminating '\0') will be recorded in
96*4882a593Smuzhiyun  * *lenp.  Note that a zero-length string is a valid return value.
97*4882a593Smuzhiyun  *
98*4882a593Smuzhiyun  * Returns a pointer to the newly-allocated string buffer, or a
99*4882a593Smuzhiyun  * pointer-coded errno if an error occurs.  Neither *p nor *lenp
100*4882a593Smuzhiyun  * will have been updated if an error is returned.
101*4882a593Smuzhiyun  *
102*4882a593Smuzhiyun  * There are two possible failures:
103*4882a593Smuzhiyun  *   - converting the string would require accessing memory at or
104*4882a593Smuzhiyun  *     beyond the "end" pointer provided (-ERANGE)
105*4882a593Smuzhiyun  *   - memory could not be allocated for the result (-ENOMEM)
106*4882a593Smuzhiyun  */
ceph_extract_encoded_string(void ** p,void * end,size_t * lenp,gfp_t gfp)107*4882a593Smuzhiyun static inline char *ceph_extract_encoded_string(void **p, void *end,
108*4882a593Smuzhiyun 						size_t *lenp, gfp_t gfp)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun 	u32 len;
111*4882a593Smuzhiyun 	void *sp = *p;
112*4882a593Smuzhiyun 	char *buf;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	ceph_decode_32_safe(&sp, end, len, bad);
115*4882a593Smuzhiyun 	if (!ceph_has_room(&sp, end, len))
116*4882a593Smuzhiyun 		goto bad;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	buf = kmalloc(len + 1, gfp);
119*4882a593Smuzhiyun 	if (!buf)
120*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	if (len)
123*4882a593Smuzhiyun 		memcpy(buf, sp, len);
124*4882a593Smuzhiyun 	buf[len] = '\0';
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	*p = (char *) *p + sizeof (u32) + len;
127*4882a593Smuzhiyun 	if (lenp)
128*4882a593Smuzhiyun 		*lenp = (size_t) len;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	return buf;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun bad:
133*4882a593Smuzhiyun 	return ERR_PTR(-ERANGE);
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun  * skip helpers
138*4882a593Smuzhiyun  */
139*4882a593Smuzhiyun #define ceph_decode_skip_n(p, end, n, bad)			\
140*4882a593Smuzhiyun 	do {							\
141*4882a593Smuzhiyun 		ceph_decode_need(p, end, n, bad);		\
142*4882a593Smuzhiyun                 *p += n;					\
143*4882a593Smuzhiyun 	} while (0)
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun #define ceph_decode_skip_64(p, end, bad)			\
146*4882a593Smuzhiyun ceph_decode_skip_n(p, end, sizeof(u64), bad)
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun #define ceph_decode_skip_32(p, end, bad)			\
149*4882a593Smuzhiyun ceph_decode_skip_n(p, end, sizeof(u32), bad)
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun #define ceph_decode_skip_16(p, end, bad)			\
152*4882a593Smuzhiyun ceph_decode_skip_n(p, end, sizeof(u16), bad)
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun #define ceph_decode_skip_8(p, end, bad)				\
155*4882a593Smuzhiyun ceph_decode_skip_n(p, end, sizeof(u8), bad)
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun #define ceph_decode_skip_string(p, end, bad)			\
158*4882a593Smuzhiyun 	do {							\
159*4882a593Smuzhiyun 		u32 len;					\
160*4882a593Smuzhiyun 								\
161*4882a593Smuzhiyun 		ceph_decode_32_safe(p, end, len, bad);		\
162*4882a593Smuzhiyun 		ceph_decode_skip_n(p, end, len, bad);		\
163*4882a593Smuzhiyun 	} while (0)
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun #define ceph_decode_skip_set(p, end, type, bad)			\
166*4882a593Smuzhiyun 	do {							\
167*4882a593Smuzhiyun 		u32 len;					\
168*4882a593Smuzhiyun 								\
169*4882a593Smuzhiyun 		ceph_decode_32_safe(p, end, len, bad);		\
170*4882a593Smuzhiyun 		while (len--)					\
171*4882a593Smuzhiyun 			ceph_decode_skip_##type(p, end, bad);	\
172*4882a593Smuzhiyun 	} while (0)
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun #define ceph_decode_skip_map(p, end, ktype, vtype, bad)		\
175*4882a593Smuzhiyun 	do {							\
176*4882a593Smuzhiyun 		u32 len;					\
177*4882a593Smuzhiyun 								\
178*4882a593Smuzhiyun 		ceph_decode_32_safe(p, end, len, bad);		\
179*4882a593Smuzhiyun 		while (len--) {					\
180*4882a593Smuzhiyun 			ceph_decode_skip_##ktype(p, end, bad);	\
181*4882a593Smuzhiyun 			ceph_decode_skip_##vtype(p, end, bad);	\
182*4882a593Smuzhiyun 		}						\
183*4882a593Smuzhiyun 	} while (0)
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun #define ceph_decode_skip_map_of_map(p, end, ktype1, ktype2, vtype2, bad) \
186*4882a593Smuzhiyun 	do {							\
187*4882a593Smuzhiyun 		u32 len;					\
188*4882a593Smuzhiyun 								\
189*4882a593Smuzhiyun 		ceph_decode_32_safe(p, end, len, bad);		\
190*4882a593Smuzhiyun 		while (len--) {					\
191*4882a593Smuzhiyun 			ceph_decode_skip_##ktype1(p, end, bad);	\
192*4882a593Smuzhiyun 			ceph_decode_skip_map(p, end, ktype2, vtype2, bad); \
193*4882a593Smuzhiyun 		}						\
194*4882a593Smuzhiyun 	} while (0)
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun /*
197*4882a593Smuzhiyun  * struct ceph_timespec <-> struct timespec64
198*4882a593Smuzhiyun  */
ceph_decode_timespec64(struct timespec64 * ts,const struct ceph_timespec * tv)199*4882a593Smuzhiyun static inline void ceph_decode_timespec64(struct timespec64 *ts,
200*4882a593Smuzhiyun 					  const struct ceph_timespec *tv)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	/*
203*4882a593Smuzhiyun 	 * This will still overflow in year 2106.  We could extend
204*4882a593Smuzhiyun 	 * the protocol to steal two more bits from tv_nsec to
205*4882a593Smuzhiyun 	 * add three more 136 year epochs after that the way ext4
206*4882a593Smuzhiyun 	 * does if necessary.
207*4882a593Smuzhiyun 	 */
208*4882a593Smuzhiyun 	ts->tv_sec = (time64_t)le32_to_cpu(tv->tv_sec);
209*4882a593Smuzhiyun 	ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
210*4882a593Smuzhiyun }
ceph_encode_timespec64(struct ceph_timespec * tv,const struct timespec64 * ts)211*4882a593Smuzhiyun static inline void ceph_encode_timespec64(struct ceph_timespec *tv,
212*4882a593Smuzhiyun 					  const struct timespec64 *ts)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
215*4882a593Smuzhiyun 	tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun /*
219*4882a593Smuzhiyun  * sockaddr_storage <-> ceph_sockaddr
220*4882a593Smuzhiyun  */
221*4882a593Smuzhiyun #define CEPH_ENTITY_ADDR_TYPE_NONE	0
222*4882a593Smuzhiyun #define CEPH_ENTITY_ADDR_TYPE_LEGACY	__cpu_to_le32(1)
223*4882a593Smuzhiyun 
ceph_encode_banner_addr(struct ceph_entity_addr * a)224*4882a593Smuzhiyun static inline void ceph_encode_banner_addr(struct ceph_entity_addr *a)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	__be16 ss_family = htons(a->in_addr.ss_family);
227*4882a593Smuzhiyun 	a->in_addr.ss_family = *(__u16 *)&ss_family;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	/* Banner addresses require TYPE_NONE */
230*4882a593Smuzhiyun 	a->type = CEPH_ENTITY_ADDR_TYPE_NONE;
231*4882a593Smuzhiyun }
ceph_decode_banner_addr(struct ceph_entity_addr * a)232*4882a593Smuzhiyun static inline void ceph_decode_banner_addr(struct ceph_entity_addr *a)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	__be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
235*4882a593Smuzhiyun 	a->in_addr.ss_family = ntohs(ss_family);
236*4882a593Smuzhiyun 	WARN_ON(a->in_addr.ss_family == 512);
237*4882a593Smuzhiyun 	a->type = CEPH_ENTITY_ADDR_TYPE_LEGACY;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun extern int ceph_decode_entity_addr(void **p, void *end,
241*4882a593Smuzhiyun 				   struct ceph_entity_addr *addr);
242*4882a593Smuzhiyun /*
243*4882a593Smuzhiyun  * encoders
244*4882a593Smuzhiyun  */
ceph_encode_64(void ** p,u64 v)245*4882a593Smuzhiyun static inline void ceph_encode_64(void **p, u64 v)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	put_unaligned_le64(v, (__le64 *)*p);
248*4882a593Smuzhiyun 	*p += sizeof(u64);
249*4882a593Smuzhiyun }
ceph_encode_32(void ** p,u32 v)250*4882a593Smuzhiyun static inline void ceph_encode_32(void **p, u32 v)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	put_unaligned_le32(v, (__le32 *)*p);
253*4882a593Smuzhiyun 	*p += sizeof(u32);
254*4882a593Smuzhiyun }
ceph_encode_16(void ** p,u16 v)255*4882a593Smuzhiyun static inline void ceph_encode_16(void **p, u16 v)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	put_unaligned_le16(v, (__le16 *)*p);
258*4882a593Smuzhiyun 	*p += sizeof(u16);
259*4882a593Smuzhiyun }
ceph_encode_8(void ** p,u8 v)260*4882a593Smuzhiyun static inline void ceph_encode_8(void **p, u8 v)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	*(u8 *)*p = v;
263*4882a593Smuzhiyun 	(*p)++;
264*4882a593Smuzhiyun }
ceph_encode_copy(void ** p,const void * s,int len)265*4882a593Smuzhiyun static inline void ceph_encode_copy(void **p, const void *s, int len)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	memcpy(*p, s, len);
268*4882a593Smuzhiyun 	*p += len;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun /*
272*4882a593Smuzhiyun  * filepath, string encoders
273*4882a593Smuzhiyun  */
ceph_encode_filepath(void ** p,void * end,u64 ino,const char * path)274*4882a593Smuzhiyun static inline void ceph_encode_filepath(void **p, void *end,
275*4882a593Smuzhiyun 					u64 ino, const char *path)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun 	u32 len = path ? strlen(path) : 0;
278*4882a593Smuzhiyun 	BUG_ON(*p + 1 + sizeof(ino) + sizeof(len) + len > end);
279*4882a593Smuzhiyun 	ceph_encode_8(p, 1);
280*4882a593Smuzhiyun 	ceph_encode_64(p, ino);
281*4882a593Smuzhiyun 	ceph_encode_32(p, len);
282*4882a593Smuzhiyun 	if (len)
283*4882a593Smuzhiyun 		memcpy(*p, path, len);
284*4882a593Smuzhiyun 	*p += len;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
ceph_encode_string(void ** p,void * end,const char * s,u32 len)287*4882a593Smuzhiyun static inline void ceph_encode_string(void **p, void *end,
288*4882a593Smuzhiyun 				      const char *s, u32 len)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun 	BUG_ON(*p + sizeof(len) + len > end);
291*4882a593Smuzhiyun 	ceph_encode_32(p, len);
292*4882a593Smuzhiyun 	if (len)
293*4882a593Smuzhiyun 		memcpy(*p, s, len);
294*4882a593Smuzhiyun 	*p += len;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun /*
298*4882a593Smuzhiyun  * version and length starting block encoders/decoders
299*4882a593Smuzhiyun  */
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun /* current code version (u8) + compat code version (u8) + len of struct (u32) */
302*4882a593Smuzhiyun #define CEPH_ENCODING_START_BLK_LEN 6
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun /**
305*4882a593Smuzhiyun  * ceph_start_encoding - start encoding block
306*4882a593Smuzhiyun  * @struct_v: current (code) version of the encoding
307*4882a593Smuzhiyun  * @struct_compat: oldest code version that can decode it
308*4882a593Smuzhiyun  * @struct_len: length of struct encoding
309*4882a593Smuzhiyun  */
ceph_start_encoding(void ** p,u8 struct_v,u8 struct_compat,u32 struct_len)310*4882a593Smuzhiyun static inline void ceph_start_encoding(void **p, u8 struct_v, u8 struct_compat,
311*4882a593Smuzhiyun 				       u32 struct_len)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	ceph_encode_8(p, struct_v);
314*4882a593Smuzhiyun 	ceph_encode_8(p, struct_compat);
315*4882a593Smuzhiyun 	ceph_encode_32(p, struct_len);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun /**
319*4882a593Smuzhiyun  * ceph_start_decoding - start decoding block
320*4882a593Smuzhiyun  * @v: current version of the encoding that the code supports
321*4882a593Smuzhiyun  * @name: name of the struct (free-form)
322*4882a593Smuzhiyun  * @struct_v: out param for the encoding version
323*4882a593Smuzhiyun  * @struct_len: out param for the length of struct encoding
324*4882a593Smuzhiyun  *
325*4882a593Smuzhiyun  * Validates the length of struct encoding, so unsafe ceph_decode_*
326*4882a593Smuzhiyun  * variants can be used for decoding.
327*4882a593Smuzhiyun  */
ceph_start_decoding(void ** p,void * end,u8 v,const char * name,u8 * struct_v,u32 * struct_len)328*4882a593Smuzhiyun static inline int ceph_start_decoding(void **p, void *end, u8 v,
329*4882a593Smuzhiyun 				      const char *name, u8 *struct_v,
330*4882a593Smuzhiyun 				      u32 *struct_len)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	u8 struct_compat;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	ceph_decode_need(p, end, CEPH_ENCODING_START_BLK_LEN, bad);
335*4882a593Smuzhiyun 	*struct_v = ceph_decode_8(p);
336*4882a593Smuzhiyun 	struct_compat = ceph_decode_8(p);
337*4882a593Smuzhiyun 	if (v < struct_compat) {
338*4882a593Smuzhiyun 		pr_warn("got struct_v %d struct_compat %d > %d of %s\n",
339*4882a593Smuzhiyun 			*struct_v, struct_compat, v, name);
340*4882a593Smuzhiyun 		return -EINVAL;
341*4882a593Smuzhiyun 	}
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	*struct_len = ceph_decode_32(p);
344*4882a593Smuzhiyun 	ceph_decode_need(p, end, *struct_len, bad);
345*4882a593Smuzhiyun 	return 0;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun bad:
348*4882a593Smuzhiyun 	return -ERANGE;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun #define ceph_encode_need(p, end, n, bad)			\
352*4882a593Smuzhiyun 	do {							\
353*4882a593Smuzhiyun 		if (!likely(ceph_has_room(p, end, n)))		\
354*4882a593Smuzhiyun 			goto bad;				\
355*4882a593Smuzhiyun 	} while (0)
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun #define ceph_encode_64_safe(p, end, v, bad)			\
358*4882a593Smuzhiyun 	do {							\
359*4882a593Smuzhiyun 		ceph_encode_need(p, end, sizeof(u64), bad);	\
360*4882a593Smuzhiyun 		ceph_encode_64(p, v);				\
361*4882a593Smuzhiyun 	} while (0)
362*4882a593Smuzhiyun #define ceph_encode_32_safe(p, end, v, bad)			\
363*4882a593Smuzhiyun 	do {							\
364*4882a593Smuzhiyun 		ceph_encode_need(p, end, sizeof(u32), bad);	\
365*4882a593Smuzhiyun 		ceph_encode_32(p, v);				\
366*4882a593Smuzhiyun 	} while (0)
367*4882a593Smuzhiyun #define ceph_encode_16_safe(p, end, v, bad)			\
368*4882a593Smuzhiyun 	do {							\
369*4882a593Smuzhiyun 		ceph_encode_need(p, end, sizeof(u16), bad);	\
370*4882a593Smuzhiyun 		ceph_encode_16(p, v);				\
371*4882a593Smuzhiyun 	} while (0)
372*4882a593Smuzhiyun #define ceph_encode_8_safe(p, end, v, bad)			\
373*4882a593Smuzhiyun 	do {							\
374*4882a593Smuzhiyun 		ceph_encode_need(p, end, sizeof(u8), bad);	\
375*4882a593Smuzhiyun 		ceph_encode_8(p, v);				\
376*4882a593Smuzhiyun 	} while (0)
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun #define ceph_encode_copy_safe(p, end, pv, n, bad)		\
379*4882a593Smuzhiyun 	do {							\
380*4882a593Smuzhiyun 		ceph_encode_need(p, end, n, bad);		\
381*4882a593Smuzhiyun 		ceph_encode_copy(p, pv, n);			\
382*4882a593Smuzhiyun 	} while (0)
383*4882a593Smuzhiyun #define ceph_encode_string_safe(p, end, s, n, bad)		\
384*4882a593Smuzhiyun 	do {							\
385*4882a593Smuzhiyun 		ceph_encode_need(p, end, n, bad);		\
386*4882a593Smuzhiyun 		ceph_encode_string(p, end, s, n);		\
387*4882a593Smuzhiyun 	} while (0)
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun #endif
391