From c67ac7d2b4dc5511f941e27eab1962b49e5f3444 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh-Weinraub Date: Wed, 16 Jan 2008 17:02:51 +0200 Subject: [PATCH] multiple mounts, single sb --- src/kernel/client.c | 59 ++++++++++++++++++++++++++++----------------- src/kernel/dir.c | 32 ++++++++++++++++++------ src/kernel/inode.c | 16 ++++++++++++ src/kernel/super.c | 15 ++++++++++-- src/kernel/super.h | 6 ++++- 5 files changed, 96 insertions(+), 32 deletions(-) diff --git a/src/kernel/client.c b/src/kernel/client.c index c240af781f0d3..ab53c47c7f167 100644 --- a/src/kernel/client.c +++ b/src/kernel/client.c @@ -79,11 +79,11 @@ int parse_open_reply(struct ceph_msg *reply, struct inode *inode) return 0; } -static int open_root_inode(struct ceph_client *client, struct ceph_mount_args *args) +static int open_root_inode(struct ceph_client *client, struct ceph_mount_args *args, struct dentry **pmnt_root) { struct ceph_mds_client *mdsc = &client->mdsc; - struct inode *inode; - struct dentry *root; + struct inode *root_inode, *mnt_inode = NULL; + struct dentry *fs_root; struct ceph_msg *req = 0; struct ceph_mds_request_head *reqhead; struct ceph_mds_reply_info rinfo; @@ -91,7 +91,7 @@ static int open_root_inode(struct ceph_client *client, struct ceph_mount_args *a int err; struct ceph_inode_cap *cap; struct ceph_inode_info *ci; - + /* 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); @@ -111,48 +111,63 @@ static int open_root_inode(struct ceph_client *client, struct ceph_mount_args *a err = -EINVAL; } - /* create root inode */ - inode = iget_locked(client->sb, rinfo.trace_in[rinfo.trace_nr-1].in->ino); - if (inode == NULL) - return -ENOMEM; - if (inode->i_state & I_NEW) - unlock_new_inode(inode); + fs_root = client->sb->s_root; + if (fs_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) { + return err; + } + + fs_root = d_alloc_root(root_inode); + if (fs_root == NULL) { + err = -ENOMEM; + /* fixme: also close? */ + goto out; + } + client->sb->s_root = fs_root; + } else { + root_inode = client->sb->s_root->d_inode; + + BUG_ON (root_inode == NULL); + } - if ((err = ceph_fill_inode(inode, rinfo.trace_in[rinfo.trace_nr-1].in)) < 0) + if ((err = ceph_fill_trace(client->sb, &rinfo, &mnt_inode, pmnt_root)) < 0) goto out; + BUG_ON(*pmnt_root == NULL); + /* fill in cap */ frommds = rinfo.reply->hdr.src.name.num; - cap = ceph_add_cap(inode, frommds, + cap = ceph_add_cap(mnt_inode, frommds, le32_to_cpu(rinfo.head->file_caps), le32_to_cpu(rinfo.head->file_caps_seq)); if (IS_ERR(cap)) { err = PTR_ERR(cap); goto out; } - ci = ceph_inode(inode); - ci->i_nr_by_mode[FILE_MODE_PIN]++; - root = d_alloc_root(inode); - if (root == NULL) { - err = -ENOMEM; - /* fixme: also close? */ + if (*pmnt_root == NULL) { goto out; } - client->sb->s_root = root; + ci = ceph_inode(mnt_inode); + ci->i_nr_by_mode[FILE_MODE_PIN]++; + dout(30, "open_root_inode success.\n"); return 0; out: dout(30, "open_root_inode failure %d\n", err); - iput(inode); + iput(root_inode); + iput(mnt_inode); return err; } /* * mount: join the ceph cluster. */ -int ceph_mount(struct ceph_client *client, struct ceph_mount_args *args) +int ceph_mount(struct ceph_client *client, struct ceph_mount_args *args, struct dentry **pdroot) { struct ceph_msg *mount_msg; int err; @@ -188,7 +203,7 @@ int ceph_mount(struct ceph_client *client, struct ceph_mount_args *args) } dout(30, "mount opening base mountpoint\n"); - if ((err = open_root_inode(client, args)) < 0) + if ((err = open_root_inode(client, args, pdroot)) < 0) return err; dout(10, "mount success\n"); diff --git a/src/kernel/dir.c b/src/kernel/dir.c index f8932c718f012..285e1616c6e4b 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -151,8 +151,8 @@ nextfrag: } else { in=dn->d_inode; } - - if (in->i_ino != fi->rinfo.dir_in[i].in->ino) { + + if (in->i_ino != le64_to_cpu(fi->rinfo.dir_in[i].in->ino)) { if (ceph_fill_inode(in, fi->rinfo.dir_in[i].in) < 0) { dout(30, "ceph_fill_inode badness\n"); iput(in); @@ -241,6 +241,7 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry, struct inode *inode; int err; ino_t ino; + int found = 0; dout(5, "dir_lookup inode %p dentry %p '%s'\n", dir, dentry, dentry->d_name.name); path = ceph_build_dentry_path(dentry, &pathlen); @@ -270,6 +271,8 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry, if (!inode) { inode = new_inode(dir->i_sb); + } else { + found++; } if (!inode) { @@ -280,13 +283,19 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry, return ERR_PTR(err); } d_add(dentry, inode); + + if (found) { + iput(inode); + } + } else { dout(10, "no trace in reply? wtf.\n"); } return NULL; } -static int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *prinfo, struct inode **lastinode) +int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *prinfo, + struct inode **lastinode, struct dentry **lastdentry) { int err = 0; struct qstr dname; @@ -300,6 +309,10 @@ static int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *p *lastinode = NULL; } + if (lastdentry) { + *lastdentry = NULL; + } + dn = sb->s_root; dget(dn); in = dn->d_inode; @@ -372,7 +385,12 @@ static int ceph_fill_trace(struct super_block *sb, struct ceph_mds_reply_info *p } dput(parent); - dput(dn); + + if (lastdentry) { + *lastdentry = dn; + } else { + dput(dn); + } if (lastinode) { *lastinode = in; @@ -414,7 +432,7 @@ static int ceph_dir_mknod(struct inode *dir, struct dentry *dentry, int mode, de err = le32_to_cpu(rinfo.head->result); if (err == 0) { - err = ceph_fill_trace(dir->i_sb, &rinfo, &inode); + err = ceph_fill_trace(dir->i_sb, &rinfo, &inode, NULL); if (err < 0) { goto done; @@ -460,7 +478,7 @@ static int ceph_dir_symlink(struct inode *dir, struct dentry *dentry, const char err = le32_to_cpu(rinfo.head->result); if (err == 0) { - err = ceph_fill_trace(dir->i_sb, &rinfo, &inode); + err = ceph_fill_trace(dir->i_sb, &rinfo, &inode, NULL); if (err < 0) { goto done; @@ -510,7 +528,7 @@ static int ceph_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) err = le32_to_cpu(rinfo.head->result); if (err == 0) { /* inode_dec_link_count(inode); */ - err = ceph_fill_trace(dir->i_sb, &rinfo, &inode); + err = ceph_fill_trace(dir->i_sb, &rinfo, &inode, NULL); if (err < 0) { goto done_mkdir; diff --git a/src/kernel/inode.c b/src/kernel/inode.c index 375b91b26c826..4788b52f484d8 100644 --- a/src/kernel/inode.c +++ b/src/kernel/inode.c @@ -14,6 +14,22 @@ int ceph_inode_debug = 50; const struct inode_operations ceph_symlink_iops; +int ceph_get_inode(struct super_block *sb, unsigned long ino, struct inode **pinode) +{ + BUG_ON(pinode == NULL); + + *pinode = NULL; + + *pinode = iget_locked(sb, ino); + + if (*pinode == NULL) + return -ENOMEM; + if ((*pinode)->i_state & I_NEW) + unlock_new_inode(*pinode); + + return 0; +} + int ceph_fill_inode(struct inode *inode, struct ceph_mds_reply_inode *info) { struct ceph_inode_info *ci = ceph_inode(inode); diff --git a/src/kernel/super.c b/src/kernel/super.c index 9ac781f5eec26..153cb3ee82378 100644 --- a/src/kernel/super.c +++ b/src/kernel/super.c @@ -93,6 +93,7 @@ static struct kmem_cache *ceph_inode_cachep; static struct inode *ceph_alloc_inode(struct super_block *sb) { struct ceph_inode_info *ci; + ci = kmem_cache_alloc(ceph_inode_cachep, GFP_KERNEL); if (!ci) return NULL; @@ -110,12 +111,15 @@ static struct inode *ceph_alloc_inode(struct super_block *sb) ci->i_caps = ci->i_caps_static; atomic_set(&ci->i_cap_count, 0); + dout(30, "ceph_alloc_inode sb=%p inode=%lu\n", sb, (&ci->vfs_inode)->i_ino); return &ci->vfs_inode; } static void ceph_destroy_inode(struct inode *inode) { struct ceph_inode_info *ci = ceph_inode(inode); + + dout(30, "ceph_destroy_inode sb=%p inode=%lu\n", inode->i_sb, inode->i_ino); if (ci->i_caps != ci->i_caps_static) kfree(ci->i_caps); @@ -396,6 +400,7 @@ 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"); @@ -414,11 +419,16 @@ static int ceph_get_sb(struct file_system_type *fs_type, } client = sb->s_fs_info; - if ((err = ceph_mount(client, &mount_args)) < 0) + if ((err = ceph_mount(client, &mount_args, &droot)) < 0) goto out_splat; dout(30, "ceph_get_sb %p finishing\n", sb); - return simple_set_mnt(mnt, sb); + mnt->mnt_sb = sb; + mnt->mnt_root = droot; + + dout(22, "droot inode = %ld\n", droot->d_inode->i_ino); + + return 0; out_splat: up_write(&sb->s_umount); @@ -431,6 +441,7 @@ out: static void ceph_kill_sb(struct super_block *s) { struct ceph_client *client = s->s_fs_info; + dout(1, "kill_sb %p\n", s); kill_anon_super(s); ceph_destroy_client(client); diff --git a/src/kernel/super.h b/src/kernel/super.h index 30e10debbde07..fe5fbfbebc5e2 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -204,10 +204,12 @@ static inline int calc_pages_for(int len, int off) /* client.c */ 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); +extern int ceph_mount(struct ceph_client *client, struct ceph_mount_args *args, + struct dentry **pmnt_root); /* inode.c */ +extern int ceph_get_inode(struct super_block *sb, unsigned long ino, struct inode **pinode); extern int ceph_fill_inode(struct inode *inode, struct ceph_mds_reply_inode *info); extern struct ceph_inode_cap *ceph_find_cap(struct inode *inode, int want); extern struct ceph_inode_cap *ceph_add_cap(struct inode *inode, int mds, u32 cap, u32 seq); @@ -229,6 +231,8 @@ extern int ceph_release(struct inode *inode, struct file *filp); 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); #endif /* _FS_CEPH_CEPH_H */ -- 2.39.5