]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
multiple mounts, single sb
authorYehuda Sadeh-Weinraub <yehuda@yehuda.infit.com>
Wed, 16 Jan 2008 15:02:51 +0000 (17:02 +0200)
committerYehuda Sadeh-Weinraub <yehuda@yehuda.infit.com>
Wed, 16 Jan 2008 15:02:51 +0000 (17:02 +0200)
src/kernel/client.c
src/kernel/dir.c
src/kernel/inode.c
src/kernel/super.c
src/kernel/super.h

index c240af781f0d3fc2ad9e7b8d066c422fe6709e29..ab53c47c7f1672c960626e22b1d78f9bdb61715a 100644 (file)
@@ -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");
index f8932c718f012561272b20254fb64b32179e1daf..285e1616c6e4bcdc0a8f6d72b04201f0352738de 100644 (file)
@@ -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;
index 375b91b26c826b0c082c840a02fd903600a92c20..4788b52f484d8c52defe825d7c22373eb03e6dc8 100644 (file)
@@ -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);
index 9ac781f5eec2662ea0c2416449e83d8e1752bd71..153cb3ee823786aedf33fad7fe2d2699cd6d4063 100644 (file)
@@ -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);
index 30e10debbde0753802148f5ab80e9a7450e0681d..fe5fbfbebc5e2e2f757872bdf5a85501e3323961 100644 (file)
@@ -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 */