From 017d9ef78e3de2b4dd0d137f299b4d3b9d3bd906 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 6 Mar 2008 15:06:03 -0800 Subject: [PATCH] client: refactored most of open_root_inode cruft into fill_trace --- src/TODO | 2 +- src/kernel/client.c | 88 ++++++++--------------------------- src/kernel/dir.c | 1 - src/kernel/inode.c | 100 +++++++++++++++++++--------------------- src/kernel/mds_client.c | 10 ++-- src/kernel/super.c | 12 +---- src/kernel/super.h | 10 ++-- 7 files changed, 75 insertions(+), 148 deletions(-) diff --git a/src/TODO b/src/TODO index a10c057daebd4..5854cb352fd35 100644 --- a/src/TODO +++ b/src/TODO @@ -12,7 +12,7 @@ code cleanup kernel client - some bugs - - caps embedded list_head's don't play nice with realloc() on cap array in ceph_add_cap() + - crash on umount with multiple mount points... - cleanup - roll open_root_inode into fill_trace? - proc.c diff --git a/src/kernel/client.c b/src/kernel/client.c index 1a5875dadcde9..bf452ac258db7 100644 --- a/src/kernel/client.c +++ b/src/kernel/client.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include /* debug level; defined in super.h */ int ceph_debug = 0; @@ -46,96 +48,40 @@ static void put_client_counter(void) spin_unlock(&ceph_client_spinlock); } -static int open_root_inode(struct ceph_client *client, struct ceph_mount_args *args, struct dentry **pmnt_root) +static struct dentry *open_root_dentry(struct ceph_client *client, struct ceph_mount_args *args) { struct ceph_mds_client *mdsc = &client->mdsc; - struct inode *root_inode, *mnt_inode = NULL; struct ceph_mds_request *req = 0; struct ceph_mds_request_head *reqhead; - struct ceph_mds_reply_info *rinfo; - int frommds; int err; - struct ceph_inode_cap *cap; - struct ceph_inode_info *ci; + struct dentry *root; /* 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); + return ERR_PTR(PTR_ERR(req)); req->r_expects_cap = true; reqhead = req->r_request->front.iov_base; reqhead->args.open.flags = O_DIRECTORY; reqhead->args.open.mode = 0; err = ceph_mdsc_do_request(mdsc, req); - rinfo = &req->r_reply_info; - if (err != 0) - goto out; - if (rinfo->trace_nr == 0) { - dout(10, "open_root_inode wtf, mds returns 0 but no trace\n"); - err = -EINVAL; - goto out; - } - - if (client->sb->s_root == NULL) { - /* get the fs root inode. Note that this is not necessarily the root of - the mount */ - err = ceph_get_inode(client->sb, le64_to_cpu(rinfo->trace_in[0].in->ino), &root_inode); - if (err < 0) - goto out; - - client->sb->s_root = d_alloc_root(root_inode); - if (client->sb->s_root == NULL) { - err = -ENOMEM; - /* fixme: also close? */ - goto out2; - } - } else { - root_inode = client->sb->s_root->d_inode; - igrab(root_inode); - BUG_ON (root_inode == NULL); - } - - if ((err = ceph_fill_trace(client->sb, rinfo, &mnt_inode, pmnt_root)) < 0) - goto out2; - if (*pmnt_root == NULL) { - err = -ENOMEM; - goto out2; - } - - /* fill in cap */ - frommds = le32_to_cpu(req->r_reply->hdr.src.name.num); - cap = ceph_add_cap(mnt_inode, req->r_session, - le32_to_cpu(rinfo->head->file_caps), - le32_to_cpu(rinfo->head->file_caps_seq)); - if (IS_ERR(cap)) { - err = PTR_ERR(cap); - goto out2; - } - - ci = ceph_inode(mnt_inode); - ci->i_nr_by_mode[FILE_MODE_PIN]++; - - dout(30, "open_root_inode success, root dentry is %p.\n", client->sb->s_root); - ceph_mdsc_put_request(req); - iput(mnt_inode); - return 0; - -out2: - dout(30, "open_root_inode failure %d\n", err); - iput(root_inode); - iput(mnt_inode); -out: + if (err == 0) { + root = req->r_last_dentry; + dout(30, "open_root_inode success, root dentry is %p.\n", client->sb->s_root); + } else + root = ERR_PTR(err); ceph_mdsc_put_request(req); - return err; + return root; } /* * mount: join the ceph cluster. */ -int ceph_mount(struct ceph_client *client, struct ceph_mount_args *args, struct dentry **pdroot) +int ceph_mount(struct ceph_client *client, struct ceph_mount_args *args, struct vfsmount *mnt) { struct ceph_msg *mount_msg; + struct dentry *root; int err; int attempts = 10; int which; @@ -168,9 +114,11 @@ int ceph_mount(struct ceph_client *client, struct ceph_mount_args *args, struct } dout(30, "mount opening base mountpoint\n"); - if ((err = open_root_inode(client, args, pdroot)) < 0) - return err; - + root = open_root_dentry(client, args); + if (IS_ERR(root)) + return PTR_ERR(root); + mnt->mnt_root = root; + mnt->mnt_sb = client->sb; dout(10, "mount success\n"); return 0; } diff --git a/src/kernel/dir.c b/src/kernel/dir.c index 265d7c96496de..e074d77ac12bf 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -185,7 +185,6 @@ nextfrag: } } - dput(dn); } } diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 5c24c7c8dea07..fbc3c185b393a 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -146,60 +146,61 @@ int ceph_fill_inode(struct inode *inode, struct ceph_mds_reply_inode *info) return 0; } -int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *prinfo, - struct inode **lastinode, struct dentry **lastdentry) +int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) { + struct ceph_mds_reply_info *rinfo = &req->r_reply_info; int err = 0; struct qstr dname; - struct dentry *dn, *parent = NULL; + struct dentry *dn = sb->s_root; + struct dentry *parent = NULL; struct inode *in; int i = 0; - BUG_ON(sb == NULL); - - if (lastinode) - *lastinode = NULL; - - if (lastdentry) - *lastdentry = NULL; - - dn = sb->s_root; - dget(dn); - in = dn->d_inode; - - for (i=0; itrace_nr; i++) - if (ceph_ino(in) == prinfo->trace_in[i].in->ino) - break; - - if (i == prinfo->trace_nr) { - dout(10, "ceph_fill_trace did not locate mounted root!\n"); - return -ENOENT; + if (dn) { + in = dn->d_inode; + } else { + /* first reply (i.e. mount) */ + BUG_ON(i); + err = ceph_get_inode(sb, le64_to_cpu(rinfo->trace_in[0].in->ino), &in); + if (err < 0) + return err; + dn = d_alloc_root(in); + if (dn == NULL) { + derr(0, "d_alloc_root enomem badness on root dentry\n"); + return -ENOMEM; + } } - if ((err = ceph_fill_inode(in, prinfo->trace_in[i].in)) < 0) + err = ceph_fill_inode(in, rinfo->trace_in[0].in); + if (err < 0) return err; - for (++i; itrace_nr; i++) { - dput(parent); - parent = dn; + if (sb->s_root == NULL) { + sb->s_root = dn; + dget(dn); + } - dname.name = prinfo->trace_dname[i]; - dname.len = prinfo->trace_dname_len[i]; + dget(dn); + for (i = 1; i < rinfo->trace_nr; i++) { + dout(10, "fill_trace i=%d/%d dn %p in %p dname '%s'\n", i, rinfo->trace_nr, + dn, dn->d_inode, rinfo->trace_dname[i]); + parent = dn; + dname.name = rinfo->trace_dname[i]; + dname.len = rinfo->trace_dname_len[i]; dname.hash = full_name_hash(dname.name, dname.len); - + dout(10, "fill_trace calling d_lookup on '%s'\n", dname.name); dn = d_lookup(parent, &dname); - dout(30, "calling d_lookup on parent=%p name=%s returned %p\n", parent, dname.name, dn); - if (!dn) { + dout(10, "fill_trace calling d_alloc\n"); dn = d_alloc(parent, &dname); - if (dn == NULL) { - dout(30, "d_alloc badness\n"); - break; + if (!dn) { + derr(0, "d_alloc enomem\n"); + return -ENOMEM; } } - - if (!prinfo->trace_in[i].in) { + if (!rinfo->trace_in[i].in) { + dout(10, "fill_trace enoent\n"); err = -ENOENT; d_delete(dn); dn = NULL; @@ -207,7 +208,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *prinfo, } if ((!dn->d_inode) || - (ceph_ino(dn->d_inode) != prinfo->trace_in[i].in->ino)) { + (ceph_ino(dn->d_inode) != rinfo->trace_in[i].in->ino)) { + dout(10, "fill_trace new_inode\n"); in = new_inode(parent->d_sb); if (in == NULL) { dout(30, "new_inode badness\n"); @@ -215,7 +217,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *prinfo, dn = NULL; break; } - if (ceph_fill_inode(in, prinfo->trace_in[i].in) < 0) { + if (ceph_fill_inode(in, rinfo->trace_in[i].in) < 0) { dout(30, "ceph_fill_inode badness\n"); iput(in); d_delete(dn); @@ -223,32 +225,24 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *prinfo, break; } ceph_touch_dentry(dn); + dout(10, "fill_trace d_add\n"); d_add(dn, in); dout(10, "ceph_fill_trace added dentry %p inode %llx %d/%d\n", - dn, ceph_ino(in), i, prinfo->trace_nr); + dn, ceph_ino(in), i, rinfo->trace_nr); } else { in = dn->d_inode; - if (ceph_fill_inode(in, prinfo->trace_in[i].in) < 0) { + if (ceph_fill_inode(in, rinfo->trace_in[i].in) < 0) { dout(30, "ceph_fill_inode badness\n"); break; } - } - } - dput(parent); - if (lastdentry) - *lastdentry = dn; - else - dput(dn); - - if (lastinode) { - *lastinode = in; - igrab(in); - } - + dout(10, "fill_trace done, last dn %p in %p\n", dn, in); + req->r_last_dentry = dn; + req->r_last_inode = in; + igrab(in); return err; } diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index c30aa6d371788..ba01491f10078 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -331,7 +331,7 @@ void ceph_mdsc_put_request(struct ceph_mds_request *req) put_session(req->r_session); if (req->r_last_inode) iput(req->r_last_inode); - if (req->r_last_dentry) + if (req->r_last_dentry) dput(req->r_last_dentry); drop_request_session_attempt_refs(req); kfree(req); @@ -823,14 +823,10 @@ void ceph_mdsc_handle_reply(struct ceph_mds_client *mdsc, struct ceph_msg *msg) result = le32_to_cpu(rinfo->head->result); dout(10, "handle_reply tid %lld result %d\n", tid, result); - if (result == 0 && - mdsc->client->sb->s_root) { /* mounted? */ - err = ceph_fill_trace(mdsc->client->sb, rinfo, - &req->r_last_inode, - &req->r_last_dentry); + if (result == 0) { + err = ceph_fill_trace(mdsc->client->sb, req); if (err) goto done; - if (req->r_expects_cap) { req->r_cap = ceph_add_cap(req->r_last_inode, req->r_session, le32_to_cpu(rinfo->head->file_caps), diff --git a/src/kernel/super.c b/src/kernel/super.c index 834dcd54a8604..b5fc3094051eb 100644 --- a/src/kernel/super.c +++ b/src/kernel/super.c @@ -435,12 +435,10 @@ static int ceph_get_sb(struct file_system_type *fs_type, struct ceph_client *client; int err; int (*compare_super)(struct super_block *, void *) = ceph_compare_super; - struct dentry *droot; dout(25, "ceph_get_sb\n"); mount_args = kmalloc(sizeof(struct ceph_mount_args), GFP_KERNEL); - err = parse_mount_args(flags, data, dev_name, mount_args); if (err < 0) goto out; @@ -456,16 +454,10 @@ static int ceph_get_sb(struct file_system_type *fs_type, } client = ceph_sb_to_client(sb); - err = ceph_mount(client, mount_args, &droot); + err = ceph_mount(client, mount_args, mnt); if (err < 0) goto out_splat; - - dout(30, "ceph_get_sb %p finishing\n", sb); - mnt->mnt_sb = sb; - mnt->mnt_root = droot; - - dout(22, "droot ino %llx\n", ceph_ino(droot->d_inode)); - + dout(22, "root ino %llx\n", ceph_ino(mnt->mnt_root->d_inode)); return 0; out_splat: diff --git a/src/kernel/super.h b/src/kernel/super.h index 4b2266a6b2bfd..d1055c4c14d97 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -267,8 +267,9 @@ static inline int calc_pages_for(int len, int off) extern struct ceph_client *ceph_create_client(struct ceph_mount_args *args, struct super_block *sb); extern void ceph_destroy_client(struct ceph_client *cl); -extern int ceph_mount(struct ceph_client *client, struct ceph_mount_args *args, - struct dentry **pmnt_root); +extern int ceph_mount(struct ceph_client *client, + struct ceph_mount_args *args, + struct vfsmount *mnt); extern const char *ceph_msg_type_name(int type); @@ -312,10 +313,7 @@ extern int ceph_inode_revalidate(struct dentry *dentry); extern const struct inode_operations ceph_dir_iops; extern const struct file_operations ceph_dir_fops; extern char *ceph_build_dentry_path(struct dentry *dentry, int *len); -extern int ceph_fill_trace(struct super_block *sb, - struct ceph_mds_reply_info *prinfo, - struct inode **lastinode, - struct dentry **lastdentry); +extern int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req); extern int ceph_request_lookup(struct super_block *sb, struct dentry *dentry); extern void ceph_touch_dentry(struct dentry *dentry); -- 2.39.5