decode.h 5.8 KB
Newer Older
S
Sage Weil 已提交
1 2 3
#ifndef __CEPH_DECODE_H
#define __CEPH_DECODE_H

4
#include <linux/err.h>
5
#include <linux/bug.h>
S
Sage Weil 已提交
6
#include <linux/time.h>
7
#include <asm/unaligned.h>
S
Sage Weil 已提交
8

9 10
#include "types.h"

S
Sage Weil 已提交
11 12 13 14 15 16
/*
 * in all cases,
 *   void **p     pointer to position pointer
 *   void *end    pointer to end of buffer (last byte + 1)
 */

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
static inline u64 ceph_decode_64(void **p)
{
	u64 v = get_unaligned_le64(*p);
	*p += sizeof(u64);
	return v;
}
static inline u32 ceph_decode_32(void **p)
{
	u32 v = get_unaligned_le32(*p);
	*p += sizeof(u32);
	return v;
}
static inline u16 ceph_decode_16(void **p)
{
	u16 v = get_unaligned_le16(*p);
	*p += sizeof(u16);
	return v;
}
static inline u8 ceph_decode_8(void **p)
{
	u8 v = *(u8 *)*p;
	(*p)++;
	return v;
}
static inline void ceph_decode_copy(void **p, void *pv, size_t n)
{
	memcpy(pv, *p, n);
	*p += n;
}

S
Sage Weil 已提交
47 48 49
/*
 * bounds check input.
 */
50 51 52 53 54
static inline int ceph_has_room(void **p, void *end, size_t n)
{
	return end >= *p && n <= end - *p;
}

S
Sage Weil 已提交
55 56
#define ceph_decode_need(p, end, n, bad)		\
	do {						\
57
		if (!likely(ceph_has_room(p, end, n)))	\
S
Sage Weil 已提交
58 59 60 61 62 63
			goto bad;			\
	} while (0)

#define ceph_decode_64_safe(p, end, v, bad)			\
	do {							\
		ceph_decode_need(p, end, sizeof(u64), bad);	\
64
		v = ceph_decode_64(p);				\
S
Sage Weil 已提交
65 66 67 68
	} while (0)
#define ceph_decode_32_safe(p, end, v, bad)			\
	do {							\
		ceph_decode_need(p, end, sizeof(u32), bad);	\
69
		v = ceph_decode_32(p);				\
S
Sage Weil 已提交
70 71 72 73
	} while (0)
#define ceph_decode_16_safe(p, end, v, bad)			\
	do {							\
		ceph_decode_need(p, end, sizeof(u16), bad);	\
74
		v = ceph_decode_16(p);				\
S
Sage Weil 已提交
75
	} while (0)
S
Sage Weil 已提交
76 77 78 79 80
#define ceph_decode_8_safe(p, end, v, bad)			\
	do {							\
		ceph_decode_need(p, end, sizeof(u8), bad);	\
		v = ceph_decode_8(p);				\
	} while (0)
S
Sage Weil 已提交
81 82 83 84 85 86 87

#define ceph_decode_copy_safe(p, end, pv, n, bad)		\
	do {							\
		ceph_decode_need(p, end, n, bad);		\
		ceph_decode_copy(p, pv, n);			\
	} while (0)

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
/*
 * Allocate a buffer big enough to hold the wire-encoded string, and
 * decode the string into it.  The resulting string will always be
 * terminated with '\0'.  If successful, *p will be advanced
 * past the decoded data.  Also, if lenp is not a null pointer, the
 * length (not including the terminating '\0') will be recorded in
 * *lenp.  Note that a zero-length string is a valid return value.
 *
 * Returns a pointer to the newly-allocated string buffer, or a
 * pointer-coded errno if an error occurs.  Neither *p nor *lenp
 * will have been updated if an error is returned.
 *
 * There are two possible failures:
 *   - converting the string would require accessing memory at or
 *     beyond the "end" pointer provided (-E
 *   - memory could not be allocated for the result
 */
static inline char *ceph_extract_encoded_string(void **p, void *end,
						size_t *lenp, gfp_t gfp)
{
	u32 len;
	void *sp = *p;
	char *buf;

	ceph_decode_32_safe(&sp, end, len, bad);
	if (!ceph_has_room(&sp, end, len))
		goto bad;

	buf = kmalloc(len + 1, gfp);
	if (!buf)
		return ERR_PTR(-ENOMEM);

	if (len)
		memcpy(buf, sp, len);
	buf[len] = '\0';

	*p = (char *) *p + sizeof (u32) + len;
	if (lenp)
		*lenp = (size_t) len;

	return buf;

bad:
	return ERR_PTR(-ERANGE);
}

S
Sage Weil 已提交
134 135 136
/*
 * struct ceph_timespec <-> struct timespec
 */
137
static inline void ceph_decode_timespec(struct timespec *ts,
138
					const struct ceph_timespec *tv)
139 140 141 142 143
{
	ts->tv_sec = le32_to_cpu(tv->tv_sec);
	ts->tv_nsec = le32_to_cpu(tv->tv_nsec);
}
static inline void ceph_encode_timespec(struct ceph_timespec *tv,
144
					const struct timespec *ts)
145 146 147 148
{
	tv->tv_sec = cpu_to_le32(ts->tv_sec);
	tv->tv_nsec = cpu_to_le32(ts->tv_nsec);
}
S
Sage Weil 已提交
149

150 151 152 153 154
/*
 * sockaddr_storage <-> ceph_sockaddr
 */
static inline void ceph_encode_addr(struct ceph_entity_addr *a)
{
Y
Yehuda Sadeh 已提交
155 156
	__be16 ss_family = htons(a->in_addr.ss_family);
	a->in_addr.ss_family = *(__u16 *)&ss_family;
157 158 159
}
static inline void ceph_decode_addr(struct ceph_entity_addr *a)
{
Y
Yehuda Sadeh 已提交
160 161
	__be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
	a->in_addr.ss_family = ntohs(ss_family);
162
	WARN_ON(a->in_addr.ss_family == 512);
163 164
}

S
Sage Weil 已提交
165 166 167
/*
 * encoders
 */
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
static inline void ceph_encode_64(void **p, u64 v)
{
	put_unaligned_le64(v, (__le64 *)*p);
	*p += sizeof(u64);
}
static inline void ceph_encode_32(void **p, u32 v)
{
	put_unaligned_le32(v, (__le32 *)*p);
	*p += sizeof(u32);
}
static inline void ceph_encode_16(void **p, u16 v)
{
	put_unaligned_le16(v, (__le16 *)*p);
	*p += sizeof(u16);
}
static inline void ceph_encode_8(void **p, u8 v)
{
	*(u8 *)*p = v;
	(*p)++;
}
188 189 190 191 192
static inline void ceph_encode_copy(void **p, const void *s, int len)
{
	memcpy(*p, s, len);
	*p += len;
}
S
Sage Weil 已提交
193 194 195 196 197 198 199 200

/*
 * filepath, string encoders
 */
static inline void ceph_encode_filepath(void **p, void *end,
					u64 ino, const char *path)
{
	u32 len = path ? strlen(path) : 0;
201
	BUG_ON(*p + 1 + sizeof(ino) + sizeof(len) + len > end);
202
	ceph_encode_8(p, 1);
S
Sage Weil 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
	ceph_encode_64(p, ino);
	ceph_encode_32(p, len);
	if (len)
		memcpy(*p, path, len);
	*p += len;
}

static inline void ceph_encode_string(void **p, void *end,
				      const char *s, u32 len)
{
	BUG_ON(*p + sizeof(len) + len > end);
	ceph_encode_32(p, len);
	if (len)
		memcpy(*p, s, len);
	*p += len;
}

S
Sage Weil 已提交
220 221
#define ceph_encode_need(p, end, n, bad)		\
	do {						\
222
		if (!likely(ceph_has_room(p, end, n)))	\
S
Sage Weil 已提交
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
			goto bad;			\
	} while (0)

#define ceph_encode_64_safe(p, end, v, bad)			\
	do {							\
		ceph_encode_need(p, end, sizeof(u64), bad);	\
		ceph_encode_64(p, v);				\
	} while (0)
#define ceph_encode_32_safe(p, end, v, bad)			\
	do {							\
		ceph_encode_need(p, end, sizeof(u32), bad);	\
		ceph_encode_32(p, v);			\
	} while (0)
#define ceph_encode_16_safe(p, end, v, bad)			\
	do {							\
		ceph_encode_need(p, end, sizeof(u16), bad);	\
		ceph_encode_16(p, v);			\
	} while (0)

#define ceph_encode_copy_safe(p, end, pv, n, bad)		\
	do {							\
		ceph_encode_need(p, end, n, bad);		\
		ceph_encode_copy(p, pv, n);			\
	} while (0)
247 248 249 250 251
#define ceph_encode_string_safe(p, end, s, n, bad)		\
	do {							\
		ceph_encode_need(p, end, n, bad);		\
		ceph_encode_string(p, end, s, n);		\
	} while (0)
S
Sage Weil 已提交
252

S
Sage Weil 已提交
253 254

#endif