linux/include/linux/ceph/decode.h
<<
>>
Prefs
   1#ifndef __CEPH_DECODE_H
   2#define __CEPH_DECODE_H
   3
   4#include <linux/err.h>
   5#include <linux/bug.h>
   6#include <linux/time.h>
   7#include <asm/unaligned.h>
   8
   9#include <linux/ceph/types.h>
  10
  11/*
  12 * in all cases,
  13 *   void **p     pointer to position pointer
  14 *   void *end    pointer to end of buffer (last byte + 1)
  15 */
  16
  17static inline u64 ceph_decode_64(void **p)
  18{
  19        u64 v = get_unaligned_le64(*p);
  20        *p += sizeof(u64);
  21        return v;
  22}
  23static inline u32 ceph_decode_32(void **p)
  24{
  25        u32 v = get_unaligned_le32(*p);
  26        *p += sizeof(u32);
  27        return v;
  28}
  29static inline u16 ceph_decode_16(void **p)
  30{
  31        u16 v = get_unaligned_le16(*p);
  32        *p += sizeof(u16);
  33        return v;
  34}
  35static inline u8 ceph_decode_8(void **p)
  36{
  37        u8 v = *(u8 *)*p;
  38        (*p)++;
  39        return v;
  40}
  41static inline void ceph_decode_copy(void **p, void *pv, size_t n)
  42{
  43        memcpy(pv, *p, n);
  44        *p += n;
  45}
  46
  47/*
  48 * bounds check input.
  49 */
  50static inline int ceph_has_room(void **p, void *end, size_t n)
  51{
  52        return end >= *p && n <= end - *p;
  53}
  54
  55#define ceph_decode_need(p, end, n, bad)                        \
  56        do {                                                    \
  57                if (!likely(ceph_has_room(p, end, n)))          \
  58                        goto bad;                               \
  59        } while (0)
  60
  61#define ceph_decode_64_safe(p, end, v, bad)                     \
  62        do {                                                    \
  63                ceph_decode_need(p, end, sizeof(u64), bad);     \
  64                v = ceph_decode_64(p);                          \
  65        } while (0)
  66#define ceph_decode_32_safe(p, end, v, bad)                     \
  67        do {                                                    \
  68                ceph_decode_need(p, end, sizeof(u32), bad);     \
  69                v = ceph_decode_32(p);                          \
  70        } while (0)
  71#define ceph_decode_16_safe(p, end, v, bad)                     \
  72        do {                                                    \
  73                ceph_decode_need(p, end, sizeof(u16), bad);     \
  74                v = ceph_decode_16(p);                          \
  75        } while (0)
  76#define ceph_decode_8_safe(p, end, v, bad)                      \
  77        do {                                                    \
  78                ceph_decode_need(p, end, sizeof(u8), bad);      \
  79                v = ceph_decode_8(p);                           \
  80        } while (0)
  81
  82#define ceph_decode_copy_safe(p, end, pv, n, bad)               \
  83        do {                                                    \
  84                ceph_decode_need(p, end, n, bad);               \
  85                ceph_decode_copy(p, pv, n);                     \
  86        } while (0)
  87
  88/*
  89 * Allocate a buffer big enough to hold the wire-encoded string, and
  90 * decode the string into it.  The resulting string will always be
  91 * terminated with '\0'.  If successful, *p will be advanced
  92 * past the decoded data.  Also, if lenp is not a null pointer, the
  93 * length (not including the terminating '\0') will be recorded in
  94 * *lenp.  Note that a zero-length string is a valid return value.
  95 *
  96 * Returns a pointer to the newly-allocated string buffer, or a
  97 * pointer-coded errno if an error occurs.  Neither *p nor *lenp
  98 * will have been updated if an error is returned.
  99 *
 100 * There are two possible failures:
 101 *   - converting the string would require accessing memory at or
 102 *     beyond the "end" pointer provided (-ERANGE)
 103 *   - memory could not be allocated for the result (-ENOMEM)
 104 */
 105static inline char *ceph_extract_encoded_string(void **p, void *end,
 106                                                size_t *lenp, gfp_t gfp)
 107{
 108        u32 len;
 109        void *sp = *p;
 110        char *buf;
 111
 112        ceph_decode_32_safe(&sp, end, len, bad);
 113        if (!ceph_has_room(&sp, end, len))
 114                goto bad;
 115
 116        buf = kmalloc(len + 1, gfp);
 117        if (!buf)
 118                return ERR_PTR(-ENOMEM);
 119
 120        if (len)
 121                memcpy(buf, sp, len);
 122        buf[len] = '\0';
 123
 124        *p = (char *) *p + sizeof (u32) + len;
 125        if (lenp)
 126                *lenp = (size_t) len;
 127
 128        return buf;
 129
 130bad:
 131        return ERR_PTR(-ERANGE);
 132}
 133
 134/*
 135 * struct ceph_timespec <-> struct timespec
 136 */
 137static inline void ceph_decode_timespec(struct timespec *ts,
 138                                        const struct ceph_timespec *tv)
 139{
 140        ts->tv_sec = (__kernel_time_t)le32_to_cpu(tv->tv_sec);
 141        ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
 142}
 143static inline void ceph_encode_timespec(struct ceph_timespec *tv,
 144                                        const struct timespec *ts)
 145{
 146        tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
 147        tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
 148}
 149
 150/*
 151 * sockaddr_storage <-> ceph_sockaddr
 152 */
 153static inline void ceph_encode_addr(struct ceph_entity_addr *a)
 154{
 155        __be16 ss_family = htons(a->in_addr.ss_family);
 156        a->in_addr.ss_family = *(__u16 *)&ss_family;
 157}
 158static inline void ceph_decode_addr(struct ceph_entity_addr *a)
 159{
 160        __be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
 161        a->in_addr.ss_family = ntohs(ss_family);
 162        WARN_ON(a->in_addr.ss_family == 512);
 163}
 164
 165/*
 166 * encoders
 167 */
 168static inline void ceph_encode_64(void **p, u64 v)
 169{
 170        put_unaligned_le64(v, (__le64 *)*p);
 171        *p += sizeof(u64);
 172}
 173static inline void ceph_encode_32(void **p, u32 v)
 174{
 175        put_unaligned_le32(v, (__le32 *)*p);
 176        *p += sizeof(u32);
 177}
 178static inline void ceph_encode_16(void **p, u16 v)
 179{
 180        put_unaligned_le16(v, (__le16 *)*p);
 181        *p += sizeof(u16);
 182}
 183static inline void ceph_encode_8(void **p, u8 v)
 184{
 185        *(u8 *)*p = v;
 186        (*p)++;
 187}
 188static inline void ceph_encode_copy(void **p, const void *s, int len)
 189{
 190        memcpy(*p, s, len);
 191        *p += len;
 192}
 193
 194/*
 195 * filepath, string encoders
 196 */
 197static inline void ceph_encode_filepath(void **p, void *end,
 198                                        u64 ino, const char *path)
 199{
 200        u32 len = path ? strlen(path) : 0;
 201        BUG_ON(*p + 1 + sizeof(ino) + sizeof(len) + len > end);
 202        ceph_encode_8(p, 1);
 203        ceph_encode_64(p, ino);
 204        ceph_encode_32(p, len);
 205        if (len)
 206                memcpy(*p, path, len);
 207        *p += len;
 208}
 209
 210static inline void ceph_encode_string(void **p, void *end,
 211                                      const char *s, u32 len)
 212{
 213        BUG_ON(*p + sizeof(len) + len > end);
 214        ceph_encode_32(p, len);
 215        if (len)
 216                memcpy(*p, s, len);
 217        *p += len;
 218}
 219
 220#define ceph_encode_need(p, end, n, bad)                        \
 221        do {                                                    \
 222                if (!likely(ceph_has_room(p, end, n)))          \
 223                        goto bad;                               \
 224        } while (0)
 225
 226#define ceph_encode_64_safe(p, end, v, bad)                     \
 227        do {                                                    \
 228                ceph_encode_need(p, end, sizeof(u64), bad);     \
 229                ceph_encode_64(p, v);                           \
 230        } while (0)
 231#define ceph_encode_32_safe(p, end, v, bad)                     \
 232        do {                                                    \
 233                ceph_encode_need(p, end, sizeof(u32), bad);     \
 234                ceph_encode_32(p, v);                           \
 235        } while (0)
 236#define ceph_encode_16_safe(p, end, v, bad)                     \
 237        do {                                                    \
 238                ceph_encode_need(p, end, sizeof(u16), bad);     \
 239                ceph_encode_16(p, v);                           \
 240        } while (0)
 241#define ceph_encode_8_safe(p, end, v, bad)                      \
 242        do {                                                    \
 243                ceph_encode_need(p, end, sizeof(u8), bad);      \
 244                ceph_encode_8(p, v);                            \
 245        } while (0)
 246
 247#define ceph_encode_copy_safe(p, end, pv, n, bad)               \
 248        do {                                                    \
 249                ceph_encode_need(p, end, n, bad);               \
 250                ceph_encode_copy(p, pv, n);                     \
 251        } while (0)
 252#define ceph_encode_string_safe(p, end, s, n, bad)              \
 253        do {                                                    \
 254                ceph_encode_need(p, end, n, bad);               \
 255                ceph_encode_string(p, end, s, n);               \
 256        } while (0)
 257
 258
 259#endif
 260