From d2ffce97124de3d818acd0174dee4ee972087f03 Mon Sep 17 00:00:00 2001 From: sageweil Date: Mon, 19 Nov 2007 17:33:38 +0000 Subject: [PATCH] client reply decoding bits git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@2081 29311d96-e01e-0410-9327-a35deaab8ce9 --- trunk/ceph/include/ceph_fs.h | 18 ++--- trunk/ceph/kernel/mds_client.c | 102 ++++++++++++++++++----------- trunk/ceph/kernel/messenger.h | 11 ++-- trunk/ceph/messages/MClientReply.h | 19 +++--- 4 files changed, 90 insertions(+), 60 deletions(-) diff --git a/trunk/ceph/include/ceph_fs.h b/trunk/ceph/include/ceph_fs.h index 93f3c49e52308..dc6925da6be33 100644 --- a/trunk/ceph/include/ceph_fs.h +++ b/trunk/ceph/include/ceph_fs.h @@ -146,11 +146,6 @@ struct ceph_object_extent { -struct ceph_frag_tree { - -}; - - /********************************************* * message types @@ -328,6 +323,11 @@ struct ceph_client_reply_head { __u64 mdsmap_epoch; }; +struct ceph_frag_tree_head { + __u32 nsplits; + __s32 splits[0]; +}; + struct ceph_client_reply_inode { ceph_ino_t ino; struct ceph_file_layout layout; @@ -337,15 +337,15 @@ struct ceph_client_reply_inode { __u64 size; __u32 rdev; __u32 mask; - char *symlink; + struct ceph_frag_tree_head fragtree; }; -/* followed by symlink string, then dirfragtree */ +/* followed by frag array, then symlink string */ struct ceph_client_reply_dirfrag { __u32 frag; __s32 auth; - unsigned char is_rep; - int ndist; + __u8 is_rep; + __u32 ndist; __u32 dist[]; }; diff --git a/trunk/ceph/kernel/mds_client.c b/trunk/ceph/kernel/mds_client.c index d39090c9a3fa0..961e9ad03b588 100644 --- a/trunk/ceph/kernel/mds_client.c +++ b/trunk/ceph/kernel/mds_client.c @@ -242,7 +242,7 @@ ceph_mdsc_create_request_msg(struct ceph_mds_client *mdsc, int op, 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; @@ -334,7 +334,6 @@ void ceph_mdsc_handle_reply(struct ceph_mds_client *mdsc, struct ceph_msg *msg) 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)) { @@ -365,61 +364,89 @@ done: 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; } @@ -428,12 +455,12 @@ int parse_reply_info_dir(void **p, void *end, struct reply_info *info) __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; @@ -443,19 +470,18 @@ int parse_reply_info_dir(void **p, void *end, struct reply_info *info) 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--; @@ -465,7 +491,7 @@ done: 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; } @@ -473,7 +499,7 @@ bad: 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)); @@ -497,7 +523,7 @@ int parse_reply_info(struct ceph_msg *msg, struct reply_info *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; } diff --git a/trunk/ceph/kernel/messenger.h b/trunk/ceph/kernel/messenger.h index 5b6670073cf84..1aacd77724c0f 100644 --- a/trunk/ceph/kernel/messenger.h +++ b/trunk/ceph/kernel/messenger.h @@ -118,28 +118,28 @@ extern int ceph_msg_send(struct ceph_messenger *msgr, struct ceph_msg *msg); /* 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; @@ -159,7 +159,7 @@ static __inline__ int ceph_decode_addr(void **p, void *end, struct ceph_entity_a } 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); @@ -229,6 +229,7 @@ static __inline__ int ceph_encode_filepath(void **p, void *end, ceph_ino_t ino, ceph_encode_32(p, end, len); memcpy(*p, path, len); *p += len; + return 0; } diff --git a/trunk/ceph/messages/MClientReply.h b/trunk/ceph/messages/MClientReply.h index 0fc839dfb0bc5..83d77a97ed1ec 100644 --- a/trunk/ceph/messages/MClientReply.h +++ b/trunk/ceph/messages/MClientReply.h @@ -53,9 +53,9 @@ class CInode; struct DirStat { // mds distribution hints frag_t frag; - int auth; - set dist; - bool is_rep; + __s32 auth; + set<__s32> dist; + __u8 is_rep; DirStat() {} DirStat(bufferlist::iterator& p) { @@ -65,15 +65,18 @@ struct DirStat { 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 dist; - bool is_rep; + __s32 auth; + set<__s32> dist; + __u8 is_rep; auth = dir->get_dir_auth().first; if (dir->is_auth()) @@ -82,8 +85,8 @@ struct DirStat { ::_encode_simple(frag, bl); ::_encode_simple(auth, bl); - ::_encode_simple(dist, bl); ::_encode_simple(is_rep, bl); + ::_encode_simple(dist, bl); } }; -- 2.39.5