From c010a0aefc2d68a61403f8379fce0883bc784f01 Mon Sep 17 00:00:00 2001 From: sageweil Date: Thu, 6 Dec 2007 00:49:16 +0000 Subject: [PATCH] wow, it mounts git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@2182 29311d96-e01e-0410-9327-a35deaab8ce9 --- trunk/ceph/kernel/client.c | 2 +- trunk/ceph/kernel/mds_client.c | 116 +++++++++++++++++++++------------ trunk/ceph/kernel/mds_client.h | 37 ++++++++++- trunk/ceph/kernel/messenger.h | 6 ++ trunk/ceph/kernel/super.c | 91 +++++++++++++++++++++----- trunk/ceph/kernel/super.h | 5 +- 6 files changed, 192 insertions(+), 65 deletions(-) diff --git a/trunk/ceph/kernel/client.c b/trunk/ceph/kernel/client.c index 45f3d098da5a9..010cf24cec240 100644 --- a/trunk/ceph/kernel/client.c +++ b/trunk/ceph/kernel/client.c @@ -88,7 +88,7 @@ fail: } /* - * try to mount + * mount: join the ceph cluster. */ static int mount(struct ceph_client *client, struct ceph_mount_args *args) { diff --git a/trunk/ceph/kernel/mds_client.c b/trunk/ceph/kernel/mds_client.c index 161d1f9d15a32..36f63feac85ac 100644 --- a/trunk/ceph/kernel/mds_client.c +++ b/trunk/ceph/kernel/mds_client.c @@ -42,7 +42,7 @@ static struct ceph_mds_request * register_request(struct ceph_mds_client *mdsc, struct ceph_msg *msg, int mds) { struct ceph_mds_request *req; - struct ceph_client_request_head *head = msg->front.iov_base; + struct ceph_mds_request_head *head = msg->front.iov_base; req = kmalloc(sizeof(*req), GFP_KERNEL); req->r_tid = head->tid = ++mdsc->last_tid; @@ -252,19 +252,19 @@ void ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client) struct ceph_msg * -ceph_mdsc_create_request_msg(struct ceph_mds_client *mdsc, int op, - ceph_ino_t ino1, const char *path1, - ceph_ino_t ino2, const char *path2) +ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, + ceph_ino_t ino1, const char *path1, + ceph_ino_t ino2, const char *path2) { struct ceph_msg *req; - struct ceph_client_request_head *head; + struct ceph_mds_request_head *head; void *p, *end; int pathlen = 2*(sizeof(ino1) + sizeof(__u32)); if (path1) pathlen += strlen(path1); if (path2) pathlen += strlen(path2); req = ceph_msg_new(CEPH_MSG_CLIENT_REQUEST, - sizeof(struct ceph_client_request_head) + pathlen, + sizeof(struct ceph_mds_request_head) + pathlen, 0, 0); if (IS_ERR(req)) return req; @@ -356,17 +356,18 @@ retry: return reply; } +/* int ceph_mdsc_do(struct ceph_mds_client *mdsc, int op, ceph_ino_t ino1, const char *path1, ceph_ino_t ino2, const char *path2) { struct ceph_msg *req, *reply; - struct ceph_client_reply_head *head; + struct ceph_mds_reply_head *head; int ret; dout(30, "mdsc do op %d on %llx/%s %llx/%s\n", op, ino1, path1 ? path1:"", ino2, path2 ? path2:""); - req = ceph_mdsc_create_request_msg(mdsc, op, ino1, path1, ino2, path2); + req = ceph_mdsc_create_request(mdsc, op, ino1, path1, ino2, path2); if (IS_ERR(req)) return PTR_ERR(req); @@ -379,13 +380,14 @@ int ceph_mdsc_do(struct ceph_mds_client *mdsc, int op, ceph_msg_put(reply); return ret; } +*/ 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; + struct ceph_mds_reply_head *head = msg->front.iov_base; __u64 tid; /* extract tid */ @@ -418,42 +420,22 @@ done: } -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 parse_reply_info_in(void **p, void *end, struct ceph_mds_reply_info_in *info) { 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) + info->in = *p; + *p += sizeof(struct ceph_mds_reply_inode) + + sizeof(__u32)*le32_to_cpu(info->in->fragtree.nsplits); + if ((err == ceph_decode_32(p, end, &info->symlink_len)) < 0) return err; - in->symlink = *p; - *p += in->symlink_len; + info->symlink = *p; + *p += info->symlink_len; if (unlikely(*p > end)) return -EINVAL; return 0; } -struct reply_info { - int trace_nr; - struct reply_info_in *trace_in; - struct ceph_client_reply_dirfrag **trace_dir; - char **trace_dname; - __u32 *trace_dname_len; - - struct ceph_client_reply_dirfrag *dir_dir; - int dir_nr; - 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) +int parse_reply_info_trace(void **p, void *end, struct ceph_mds_reply_info *info) { __u32 numi; int err = -EINVAL; @@ -487,7 +469,7 @@ int parse_reply_info_trace(void **p, void *end, struct reply_info *info) goto bad; /* dir */ info->trace_dir[numi] = *p; - *p += sizeof(struct ceph_client_reply_dirfrag) + + *p += sizeof(struct ceph_mds_reply_dirfrag) + sizeof(__u32)*le32_to_cpu(info->trace_dir[numi]->ndist); if (unlikely(*p > end)) goto bad; @@ -503,7 +485,7 @@ bad: return err; } -int parse_reply_info_dir(void **p, void *end, struct reply_info *info) +int parse_reply_info_dir(void **p, void *end, struct ceph_mds_reply_info *info) { __u32 num, i = 0; int err = -EINVAL; @@ -549,7 +531,7 @@ bad: } -int parse_reply_info(struct ceph_msg *msg, struct reply_info *info) +int ceph_mdsc_parse_reply_info(struct ceph_msg *msg, struct ceph_mds_reply_info *info) { void *p, *end; __u32 len; @@ -558,7 +540,7 @@ int parse_reply_info(struct ceph_msg *msg, struct reply_info *info) memset(info, 0, sizeof(*info)); /* trace */ - p = msg->front.iov_base + sizeof(struct ceph_client_reply_head); + p = msg->front.iov_base + sizeof(struct ceph_mds_reply_head); end = p + msg->front.iov_len; if ((err = ceph_decode_32(&p, end, &len)) < 0) goto bad; @@ -581,12 +563,62 @@ bad: return err; } -void destroy_reply_info(struct reply_info *info) +void ceph_mdsc_destroy_reply_info(struct ceph_mds_reply_info *info) { if (info->trace_in) kfree(info->trace_in); if (info->dir_in) kfree(info->dir_in); } + +void ceph_mdsc_fill_inode(struct inode *inode, struct ceph_mds_reply_inode *info) +{ + struct ceph_inode_info *ci = CEPH_I(inode); + int mask = le32_to_cpu(info->mask); + int i; + + /* vfs inode */ + inode->i_ino = le64_to_cpu(info->ino); + inode->i_mode = le32_to_cpu(info->mode) | S_IFDIR; + inode->i_uid = le32_to_cpu(info->uid); + inode->i_gid = le32_to_cpu(info->gid); + inode->i_nlink = le32_to_cpu(info->nlink); + inode->i_size = le64_to_cpu(info->size); + inode->i_rdev = le32_to_cpu(info->rdev); + + dout(30, "mdsc fill_inode ino=%lx by %d.%d sz=%llu\n", inode->i_ino, + inode->i_uid, inode->i_gid, inode->i_size); + + ceph_decode_timespec(&inode->i_atime, &info->atime); + ceph_decode_timespec(&inode->i_mtime, &info->mtime); + ceph_decode_timespec(&inode->i_ctime, &info->ctime); + + /* ceph inode */ + ci->i_layout = info->layout; /* swab? */ + + if (le32_to_cpu(info->fragtree.nsplits) == 0) { + ci->i_fragtree = ci->i_fragtree_static; + } else { + //ci->i_fragtree = kmalloc(...); + BUG_ON(1); // write me + } + ci->i_fragtree->nsplits = le32_to_cpu(info->fragtree.nsplits); + for (i=0; ii_fragtree->nsplits; i++) + ci->i_fragtree->splits[i] = le32_to_cpu(info->fragtree.splits[i]); + + ci->i_frag_map_nr = 1; + ci->i_frag_map = ci->i_frag_map_static; + ci->i_frag_map[0].frag = 0; + ci->i_frag_map[0].mds = 0; /* fixme */ + + ci->i_nr_caps = 0; + ci->i_caps = ci->i_caps_static; + ci->i_wr_size = 0; + ci->i_wr_mtime.tv_sec = 0; + ci->i_wr_mtime.tv_usec = 0; +} + + + void ceph_mdsc_handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg) { struct ceph_mds_request *req; diff --git a/trunk/ceph/kernel/mds_client.h b/trunk/ceph/kernel/mds_client.h index 7d3cf97f179e4..feac145ba4ae8 100644 --- a/trunk/ceph/kernel/mds_client.h +++ b/trunk/ceph/kernel/mds_client.h @@ -44,6 +44,9 @@ struct ceph_mds_request { }; +/* + * mds client state + */ struct ceph_mds_client { spinlock_t lock; @@ -61,13 +64,43 @@ struct ceph_mds_client { struct completion map_waiters; }; +/* + * for mds reply parsing + */ +struct ceph_mds_reply_info_in { + struct ceph_mds_reply_inode *in; + __u32 symlink_len; + char *symlink; +}; + +struct ceph_mds_reply_info { + int trace_nr; + struct ceph_mds_reply_info_in *trace_in; + struct ceph_mds_reply_dirfrag **trace_dir; + char **trace_dname; + __u32 *trace_dname_len; + + struct ceph_mds_reply_dirfrag *dir_dir; + int dir_nr; + struct ceph_mds_reply_info_in *dir_in; + char **dir_dname; + __u32 *dir_dname_len; +}; + + + extern void ceph_mdsc_init(struct ceph_mds_client *mdsc, struct ceph_client *client); -struct ceph_msg *ceph_mdsc_do_request(struct ceph_mds_client *mdsc, struct ceph_msg *msg, int mds); -int ceph_mdsc_do(struct ceph_mds_client *mdsc, int op, ceph_ino_t ino1, const char *path1, ceph_ino_t ino2, const char *path2); extern void ceph_mdsc_handle_map(struct ceph_mds_client *mdsc, struct ceph_msg *msg); extern void ceph_mdsc_handle_session(struct ceph_mds_client *mdsc, struct ceph_msg *msg); extern void ceph_mdsc_handle_reply(struct ceph_mds_client *mdsc, struct ceph_msg *msg); extern void ceph_mdsc_handle_forward(struct ceph_mds_client *mdsc, struct ceph_msg *msg); +extern struct ceph_msg *ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, ceph_ino_t ino1, const char *path1, ceph_ino_t ino2, const char *path2); +struct ceph_msg *ceph_mdsc_do_request(struct ceph_mds_client *mdsc, struct ceph_msg *msg, int mds); + + +extern int ceph_mdsc_parse_reply_info(struct ceph_msg *msg, struct ceph_mds_reply_info *info); +extern void ceph_mdsc_fill_inode(struct inode *inode, struct ceph_mds_reply_inode *i); + #endif diff --git a/trunk/ceph/kernel/messenger.h b/trunk/ceph/kernel/messenger.h index 8a6168a5381d0..b8c81a3b3d9c0 100644 --- a/trunk/ceph/kernel/messenger.h +++ b/trunk/ceph/kernel/messenger.h @@ -238,6 +238,12 @@ static __inline__ int ceph_encode_filepath(void **p, void *end, ceph_ino_t ino, return 0; } +static void __inline__ ceph_decode_timespec(struct timespec *ts, struct ceph_timeval *tv) +{ + ts->tv_sec = le32_to_cpu(tv->tv_sec); + ts->tv_nsec = 1000*le32_to_cpu(tv->tv_usec); +} + diff --git a/trunk/ceph/kernel/super.c b/trunk/ceph/kernel/super.c index 224fe97a294a8..b5477214f3457 100644 --- a/trunk/ceph/kernel/super.c +++ b/trunk/ceph/kernel/super.c @@ -326,10 +326,70 @@ static int parse_mount_args(int flags, char *options, const char *dev_name, stru } +static int open_root_inode(struct super_block *sb, struct ceph_mount_args *args) +{ + struct ceph_super_info *sbinfo = ceph_sbinfo(sb); + struct ceph_mds_client *mdsc = &sbinfo->sb_client->mdsc; + struct inode *inode; + struct dentry *root; + struct ceph_msg *req, *reply; + struct ceph_mds_reply_head *head; + struct ceph_mds_reply_info rinfo; + struct ceph_mds_reply_info_in *rootinfo; + int err; + + /* open dir */ + dout(30, "open_root_inode opening '%s'\n", args->path); + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, 1, args->path, 0, 0); + if (IS_ERR(req)) + return PTR_ERR(req); + reply = ceph_mdsc_do_request(mdsc, req, -1); + if (IS_ERR(reply)) + return PTR_ERR(reply); + + /* parse reply */ + head = reply->front.iov_base; + err = le32_to_cpu(head->result); + dout(30, "open_root_inode open result=%d\n", err); + if (err < 0) { + dout(30, "open_root_inode mds reports %d", err); + goto out; + } + if ((err = ceph_mdsc_parse_reply_info(reply, &rinfo)) < 0) { + dout(30, "open_root_inode problem parsing reply %d", err); + goto out; + } + BUG_ON(rinfo.trace_nr == 0); + rootinfo = &rinfo.trace_in[rinfo.trace_nr-1]; + + /* construct root inode */ + inode = new_inode(sb); + if (!inode) { + err = -ENOMEM; + goto out; + } + dout(30, "open_root_inode filling inode\n"); + ceph_mdsc_fill_inode(inode, rootinfo->in); + root = d_alloc_root(inode); + if (!root) { + err = -ENOMEM; + goto out2; + } + sb->s_root = root; + dout(30, "open_root_inode success.\n"); + return 0; + +out2: + iput(inode); /* ? */ +out: + ceph_msg_put(reply); + return err; +} + static int ceph_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - struct super_block *s; + struct super_block *sb; struct ceph_mount_args mount_args; struct ceph_super_info *sbinfo; int err; @@ -345,12 +405,12 @@ static int ceph_get_sb(struct file_system_type *fs_type, compare_super = 0; /* superblock */ - s = sget(fs_type, compare_super, ceph_set_super, &mount_args); - if (IS_ERR(s)) { - err = PTR_ERR(s); + sb = sget(fs_type, compare_super, ceph_set_super, &mount_args); + if (IS_ERR(sb)) { + err = PTR_ERR(sb); goto out; } - sbinfo = ceph_sbinfo(s); + sbinfo = ceph_sbinfo(sb); /* client */ if (!sbinfo->sb_client) { @@ -364,21 +424,18 @@ static int ceph_get_sb(struct file_system_type *fs_type, } /* open root */ - dout(30, "ceph_get_sb opening base mountpoing\n"); - err = ceph_mdsc_do(&sbinfo->sb_client->mdsc, CEPH_MDS_OP_OPEN, - CEPH_INO_ROOT, mount_args.path, 0, 0); - if (err < 0) - return err; - - /* construct root inode */ - dout(30, "ceph_get_sb constructing root inode\n"); + dout(30, "ceph_get_sb opening base mountpoint\n"); + if ((err = open_root_inode(sb, &mount_args)) < 0) + goto out_splat; - dout(30, "ceph_get_sb success\n"); - return 0; + dout(30, "ceph_get_sb finishing\n"); + return simple_set_mnt(mnt, sb); out_splat: - up_write(&s->s_umount); - deactivate_super(s); + if (sbinfo->sb_client) + ceph_put_client(sbinfo->sb_client); + up_write(&sb->s_umount); + deactivate_super(sb); out: dout(25, "ceph_get_sb fail %d\n", err); return err; diff --git a/trunk/ceph/kernel/super.h b/trunk/ceph/kernel/super.h index 4da42ac81aa06..7940296e5428d 100644 --- a/trunk/ceph/kernel/super.h +++ b/trunk/ceph/kernel/super.h @@ -57,10 +57,9 @@ struct ceph_inode_frag_map_item { struct ceph_inode_info { struct ceph_file_layout i_layout; - int i_dir_auth; - struct ceph_frag_tree_head *i_fragtree, i_fragtree_static; + struct ceph_frag_tree_head *i_fragtree, i_fragtree_static[1]; int i_frag_map_nr; - struct ceph_inode_frag_map_item *i_frag_map; + struct ceph_inode_frag_map_item *i_frag_map, i_frag_map_static[1]; int i_nr_caps; struct ceph_inode_cap *i_caps; -- 2.39.5