req = ceph_msg_new(CEPH_MSG_CLIENT_REQUEST,
sizeof(struct ceph_client_request_head) +
- sizeof(ino1)*2 + sizeof(__u32)*2 + strlen(path) + strlen(path2)
+ sizeof(ino1)*2 + sizeof(__u32)*2 + strlen(path1) + strlen(path2),
0, 0);
if (IS_ERR(req))
return req;
struct ceph_mds_request *req;
struct ceph_client_reply_head *head = msg->front.iov_base;
__u64 tid;
- int result;
/* extract tid */
if (msg->front.iov_len < sizeof(*head)) {
return;
}
+
+struct reply_info_in {
+ struct ceph_client_reply_inode *in;
+ __u32 symlink_len;
+ char *symlink;
+};
+
+int parse_reply_info_in(void **p, void *end, struct reply_info_in *in)
+{
+ int err;
+ in->in = *p;
+ *p += sizeof(struct ceph_client_reply_inode) +
+ sizeof(__u32)*le32_to_cpu(in->in->fragtree.nsplits);
+ if ((err == ceph_decode_32(p, end, &in->symlink_len)) < 0)
+ return err;
+ in->symlink = *p;
+ *p += in->symlink_len;
+ if (unlikely(*p > end))
+ return -EINVAL;
+ return 0;
+}
+
struct reply_info {
int trace_nr;
- struct ceph_client_reply_inode **trace_in;
- struct ceph_client_reply_dir **trace_dir;
+ struct reply_info_in *trace_in;
+ struct ceph_client_reply_dirfrag **trace_dir;
char **trace_dname;
__u32 *trace_dname_len;
- struct ceph_client_reply_dir *dir_dir;
+ struct ceph_client_reply_dirfrag *dir_dir;
int dir_nr;
- struct ceph_client_reply_inode **dir_in;
+ struct reply_info_in *dir_in;
char **dir_dname;
__u32 *dir_dname_len;
};
int parse_reply_info_trace(void **p, void *end, struct reply_info *info)
{
- __u32 numi, i = 0;
+ __u32 numi;
int err = -EINVAL;
- if ((err = ceph_decode_32(&p, end, &numi)) < 0)
+ if ((err = ceph_decode_32(p, end, &numi)) < 0)
goto bad;
if (numi == 0)
goto done; /* hrm, this shouldn't actually happen, but.. */
/* alloc one longer shared array */
info->trace_nr = numi;
- info->trace_in = kmalloc(4 * numi * sizeof(void*), GFP_KERNEL);
+ info->trace_in = kmalloc(numi * (2*sizeof(void*)+sizeof(*info->trace_in)), GFP_KERNEL);
if (info->trace_in == NULL)
return -ENOMEM;
- info->trace_dir = info->trace_in + numi;
- info->trace_dname = info->trace_in + numi*2;
- info->trace_dname_len = info->trace_in + numi*3;
+ info->trace_dir = (void*)(info->trace_in + numi);
+ info->trace_dname = (void*)(info->trace_dir + numi);
+ info->trace_dname_len = (void*)(info->trace_dname + numi);
while (1) {
/* inode */
- info->trace_in[numi-1] = p;
- p += sizeof(struct ceph_client_reply_inode);
+ if ((err = parse_reply_info_in(p, end, &info->trace_in[numi-1])) < 0)
+ goto bad;
if (--numi == 0)
break;
-
- if ((err == ceph_decode_32(&p, end, &info->trace_dname_len[numi])) < 0)
+ /* dentry */
+ if ((err == ceph_decode_32(p, end, &info->trace_dname_len[numi])) < 0)
+ goto bad;
+ info->trace_dname[numi] = *p;
+ *p += info->trace_dname_len[numi];
+ if (*p > end)
goto bad;
- info->trace_dname[numi] = p;
- p += info->trace_dname_len[numi];
- if (p > end)
+ /* dir */
+ info->trace_dir[numi] = *p;
+ *p += sizeof(struct ceph_client_reply_dirfrag) +
+ sizeof(__u32)*le32_to_cpu(info->trace_dir[numi]->ndist);
+ if (unlikely(*p > end))
goto bad;
}
done:
- if (p != end)
- return bad;
+ if (*p != end)
+ return -EINVAL;
return 0;
bad:
- derr(1, "problem parsing trace %d %s\n", err, strerror(err));
+ derr(1, "problem parsing trace %d\n", err);
return err;
}
__u32 num, i = 0;
int err = -EINVAL;
- info->dir_dir = p;
- p += sizeof(*info->dir_dir);
- if (p > end)
+ info->dir_dir = *p;
+ *p += sizeof(*info->dir_dir) + sizeof(__u32)*info->dir_dir->ndist;
+ if (*p > end)
goto bad;
- if ((err = ceph_decode_32(&p, end, &num)) < 0)
+ if ((err = ceph_decode_32(p, end, &num)) < 0)
goto bad;
if (num == 0)
goto done;
info->dir_in = kmalloc(3 * num * sizeof(void*), GFP_KERNEL);
if (info->dir_in == NULL)
return -ENOMEM;
- info->dir_dname = info->trace_in + num;
- info->dir_dname_len = info->trace_in + num*2;
+ info->dir_dname = (void*)(info->trace_in + num);
+ info->dir_dname_len = (void*)(info->trace_in + num*2);
while (num) {
- if ((err == ceph_decode_32(&p, end, &info->dir_dname_len[i])) < 0)
+ /* dentry, inode */
+ if ((err == ceph_decode_32(p, end, &info->dir_dname_len[i])) < 0)
goto bad;
- info->dir_dname[i] = p;
- p += info->dir_dname_len[i];
- if (p > end)
+ info->dir_dname[i] = *p;
+ *p += info->dir_dname_len[i];
+ if (*p > end)
goto bad;
- info->dir_in[i] = p;
- p += sizeof(struct ceph_reply_inode_info);
- if (p > end)
+ if ((err = parse_reply_info_in(p, end, &info->dir_in[i])) < 0)
goto bad;
i++;
num--;
return 0;
bad:
- derr(1, "problem parsing dir contents %d %s\n", err, strerror(err));
+ derr(1, "problem parsing dir contents %d\n", err);
return err;
}
int parse_reply_info(struct ceph_msg *msg, struct reply_info *info)
{
void *p, *end;
- __u32 len, numi = 0;
+ __u32 len;
int err = -EINVAL;
memset(info, 0, sizeof(*info));
return 0;
bad:
- derr(1, "problem parsing reply info %d %s\n", err, strerror(err));
+ derr(1, "problem parsing reply info %d\n", err);
return err;
}
/* encoding/decoding helpers */
static __inline__ int ceph_decode_64(void **p, void *end, __u64 *v) {
- if (*p + sizeof(*v) > end)
+ if (unlikely(*p + sizeof(*v) > end))
return -EINVAL;
*v = le64_to_cpu(*(__u64*)p);
p += sizeof(*v);
return 0;
}
static __inline__ int ceph_decode_32(void **p, void *end, __u32 *v) {
- if (*p + sizeof(*v) > end)
+ if (unlikely(*p + sizeof(*v) > end))
return -EINVAL;
*v = le32_to_cpu(*(__u32*)p);
p += sizeof(*v);
return 0;
}
static __inline__ int ceph_decode_16(void **p, void *end, __u16 *v) {
- if (*p + sizeof(*v) > end)
+ if (unlikely(*p + sizeof(*v) > end))
return -EINVAL;
*v = le16_to_cpu(*(__u16*)p);
p += sizeof(*v);
return 0;
}
static __inline__ int ceph_decode_copy(void **p, void *end, void *v, int len) {
- if (*p + len > end)
+ if (unlikely(*p + len > end))
return -EINVAL;
memcpy(v, *p, len);
*p += len;
}
static __inline__ int ceph_decode_name(void **p, void *end, struct ceph_entity_name *v) {
- if (*p + sizeof(*v) > end)
+ if (unlikely(*p + sizeof(*v) > end))
return -EINVAL;
v->type = le32_to_cpu(*(__u32*)p);
p += sizeof(__u32);
ceph_encode_32(p, end, len);
memcpy(*p, path, len);
*p += len;
+ return 0;
}
struct DirStat {
// mds distribution hints
frag_t frag;
- int auth;
- set<int> dist;
- bool is_rep;
+ __s32 auth;
+ set<__s32> dist;
+ __u8 is_rep;
DirStat() {}
DirStat(bufferlist::iterator& p) {
void _decode(bufferlist::iterator& p) {
::_decode_simple(frag, p);
::_decode_simple(auth, p);
- ::_decode_simple(dist, p);
::_decode_simple(is_rep, p);
+ ::_decode_simple(dist, p);
}
static void _encode(bufferlist& bl, CDir *dir, int whoami) {
+ /*
+ * note: encoding matches struct ceph_client_reply_dirfrag
+ */
frag_t frag = dir->get_frag();
- int auth;
- set<int> dist;
- bool is_rep;
+ __s32 auth;
+ set<__s32> dist;
+ __u8 is_rep;
auth = dir->get_dir_auth().first;
if (dir->is_auth())
::_encode_simple(frag, bl);
::_encode_simple(auth, bl);
- ::_encode_simple(dist, bl);
::_encode_simple(is_rep, bl);
+ ::_encode_simple(dist, bl);
}
};