1 #ifndef __CEPH_DECODE_H
2 #define __CEPH_DECODE_H
6 #include <linux/time.h>
7 #include <asm/unaligned.h>
9 #include <linux/ceph/types.h>
11 /* This seemed to be the easiest place to define these */
14 #define U8_MAX ((u8)(~0U))
15 #define U16_MAX ((u16)(~0U))
16 #define U32_MAX ((u32)(~0U))
17 #define U64_MAX ((u64)(~0ULL))
19 #define S8_MAX ((s8)(U8_MAX >> 1))
20 #define S16_MAX ((s16)(U16_MAX >> 1))
21 #define S32_MAX ((s32)(U32_MAX >> 1))
22 #define S64_MAX ((s64)(U64_MAX >> 1LL))
24 #define S8_MIN ((s8)(-S8_MAX - 1))
25 #define S16_MIN ((s16)(-S16_MAX - 1))
26 #define S32_MIN ((s32)(-S32_MAX - 1))
27 #define S64_MIN ((s64)(-S64_MAX - 1LL))
32 * void **p pointer to position pointer
33 * void *end pointer to end of buffer (last byte + 1)
36 static inline u64 ceph_decode_64(void **p)
38 u64 v = get_unaligned_le64(*p);
42 static inline u32 ceph_decode_32(void **p)
44 u32 v = get_unaligned_le32(*p);
48 static inline u16 ceph_decode_16(void **p)
50 u16 v = get_unaligned_le16(*p);
54 static inline u8 ceph_decode_8(void **p)
60 static inline void ceph_decode_copy(void **p, void *pv, size_t n)
69 static inline int ceph_has_room(void **p, void *end, size_t n)
71 return end >= *p && n <= end - *p;
74 #define ceph_decode_need(p, end, n, bad) \
76 if (!likely(ceph_has_room(p, end, n))) \
80 #define ceph_decode_64_safe(p, end, v, bad) \
82 ceph_decode_need(p, end, sizeof(u64), bad); \
83 v = ceph_decode_64(p); \
85 #define ceph_decode_32_safe(p, end, v, bad) \
87 ceph_decode_need(p, end, sizeof(u32), bad); \
88 v = ceph_decode_32(p); \
90 #define ceph_decode_16_safe(p, end, v, bad) \
92 ceph_decode_need(p, end, sizeof(u16), bad); \
93 v = ceph_decode_16(p); \
95 #define ceph_decode_8_safe(p, end, v, bad) \
97 ceph_decode_need(p, end, sizeof(u8), bad); \
98 v = ceph_decode_8(p); \
101 #define ceph_decode_copy_safe(p, end, pv, n, bad) \
103 ceph_decode_need(p, end, n, bad); \
104 ceph_decode_copy(p, pv, n); \
108 * Allocate a buffer big enough to hold the wire-encoded string, and
109 * decode the string into it. The resulting string will always be
110 * terminated with '\0'. If successful, *p will be advanced
111 * past the decoded data. Also, if lenp is not a null pointer, the
112 * length (not including the terminating '\0') will be recorded in
113 * *lenp. Note that a zero-length string is a valid return value.
115 * Returns a pointer to the newly-allocated string buffer, or a
116 * pointer-coded errno if an error occurs. Neither *p nor *lenp
117 * will have been updated if an error is returned.
119 * There are two possible failures:
120 * - converting the string would require accessing memory at or
121 * beyond the "end" pointer provided (-ERANGE)
122 * - memory could not be allocated for the result (-ENOMEM)
124 static inline char *ceph_extract_encoded_string(void **p, void *end,
125 size_t *lenp, gfp_t gfp)
131 ceph_decode_32_safe(&sp, end, len, bad);
132 if (!ceph_has_room(&sp, end, len))
135 buf = kmalloc(len + 1, gfp);
137 return ERR_PTR(-ENOMEM);
140 memcpy(buf, sp, len);
143 *p = (char *) *p + sizeof (u32) + len;
145 *lenp = (size_t) len;
150 return ERR_PTR(-ERANGE);
154 * struct ceph_timespec <-> struct timespec
156 static inline void ceph_decode_timespec(struct timespec *ts,
157 const struct ceph_timespec *tv)
159 ts->tv_sec = (__kernel_time_t)le32_to_cpu(tv->tv_sec);
160 ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
162 static inline void ceph_encode_timespec(struct ceph_timespec *tv,
163 const struct timespec *ts)
165 tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
166 tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
170 * sockaddr_storage <-> ceph_sockaddr
172 static inline void ceph_encode_addr(struct ceph_entity_addr *a)
174 __be16 ss_family = htons(a->in_addr.ss_family);
175 a->in_addr.ss_family = *(__u16 *)&ss_family;
177 static inline void ceph_decode_addr(struct ceph_entity_addr *a)
179 __be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
180 a->in_addr.ss_family = ntohs(ss_family);
181 WARN_ON(a->in_addr.ss_family == 512);
187 static inline void ceph_encode_64(void **p, u64 v)
189 put_unaligned_le64(v, (__le64 *)*p);
192 static inline void ceph_encode_32(void **p, u32 v)
194 put_unaligned_le32(v, (__le32 *)*p);
197 static inline void ceph_encode_16(void **p, u16 v)
199 put_unaligned_le16(v, (__le16 *)*p);
202 static inline void ceph_encode_8(void **p, u8 v)
207 static inline void ceph_encode_copy(void **p, const void *s, int len)
214 * filepath, string encoders
216 static inline void ceph_encode_filepath(void **p, void *end,
217 u64 ino, const char *path)
219 u32 len = path ? strlen(path) : 0;
220 BUG_ON(*p + 1 + sizeof(ino) + sizeof(len) + len > end);
222 ceph_encode_64(p, ino);
223 ceph_encode_32(p, len);
225 memcpy(*p, path, len);
229 static inline void ceph_encode_string(void **p, void *end,
230 const char *s, u32 len)
232 BUG_ON(*p + sizeof(len) + len > end);
233 ceph_encode_32(p, len);
239 #define ceph_encode_need(p, end, n, bad) \
241 if (!likely(ceph_has_room(p, end, n))) \
245 #define ceph_encode_64_safe(p, end, v, bad) \
247 ceph_encode_need(p, end, sizeof(u64), bad); \
248 ceph_encode_64(p, v); \
250 #define ceph_encode_32_safe(p, end, v, bad) \
252 ceph_encode_need(p, end, sizeof(u32), bad); \
253 ceph_encode_32(p, v); \
255 #define ceph_encode_16_safe(p, end, v, bad) \
257 ceph_encode_need(p, end, sizeof(u16), bad); \
258 ceph_encode_16(p, v); \
260 #define ceph_encode_8_safe(p, end, v, bad) \
262 ceph_encode_need(p, end, sizeof(u8), bad); \
263 ceph_encode_8(p, v); \
266 #define ceph_encode_copy_safe(p, end, pv, n, bad) \
268 ceph_encode_need(p, end, n, bad); \
269 ceph_encode_copy(p, pv, n); \
271 #define ceph_encode_string_safe(p, end, s, n, bad) \
273 ceph_encode_need(p, end, n, bad); \
274 ceph_encode_string(p, end, s, n); \