]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
slfixed slab corruption in mds reply parsing; opendir now opens directories as needed
authorsageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Mon, 17 Dec 2007 21:47:34 +0000 (21:47 +0000)
committersageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Mon, 17 Dec 2007 21:47:34 +0000 (21:47 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@2215 29311d96-e01e-0410-9327-a35deaab8ce9

trunk/ceph/kernel/dir.c
trunk/ceph/kernel/inode.c
trunk/ceph/kernel/mds_client.c
trunk/ceph/kernel/super.c
trunk/ceph/kernel/super.h

index bf86ea2534200e7536106e385e8f3e7f0fc1049e..604309627f135556d84d8af557f42cc304f3c721 100644 (file)
@@ -6,6 +6,67 @@ int ceph_dir_debug = 50;
 const struct inode_operations ceph_dir_iops;
 const struct file_operations ceph_dir_fops;
 
+/*
+ * ugly hack.  
+ * - no locking.  
+ * - should stop at mount root or current's CWD?
+ */
+static int get_dentry_path(struct dentry *dn, char *buf, struct dentry *base)
+{
+       int len;
+       dout(20, "get_dentry_path in dn %p bas %p\n", dn, base);
+       if (dn == base) 
+               return 0;       
+
+       len = get_dentry_path(dn->d_parent, buf, base);
+       dout(20, "get_dentry_path out dn %p bas %p len %d adding %s\n", 
+            dn, base, len, dn->d_name.name);
+
+       buf[len++] = '/';
+       memcpy(buf+len, dn->d_name.name, dn->d_name.len);
+       len += dn->d_name.len;
+       buf[len] = 0;
+       return len;
+}
+
+struct ceph_inode_cap *ceph_open(struct inode *inode, struct file *file, int flags)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc;
+       char path[PATH_MAX];
+       int pathlen;
+       struct ceph_msg *req;
+       struct ceph_mds_request_head *rhead;
+       struct ceph_mds_reply_info rinfo;
+       struct dentry *dentry;
+       int frommds;
+       struct ceph_inode_cap *cap;
+       int err;
+
+       dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
+
+       dout(5, "open inode %p dentry %p name '%s' flags %d\n", inode, dentry, dentry->d_name.name, flags);
+       pathlen = get_dentry_path(dentry, path, inode->i_sb->s_root);
+       dout(5, "path is %s len %d\n", path, pathlen);
+
+       /* stat mds */
+       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, 
+                                      inode->i_sb->s_root->d_inode->i_ino, path, 0, 0);
+       if (IS_ERR(req)) 
+               return ERR_PTR(PTR_ERR(req));
+       rhead = req->front.iov_base;
+       rhead->args.open.flags = cpu_to_le32(flags);
+       if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, -1)) < 0)
+               return ERR_PTR(err);
+       
+       dout(10, "open got and parsed result\n");
+       frommds = rinfo.reply->hdr.src.name.num;
+       cap = ceph_add_cap(inode, frommds, 
+                          le32_to_cpu(rinfo.head->file_caps), 
+                          le32_to_cpu(rinfo.head->file_caps_seq));
+       return cap;
+}
+
 static int ceph_dir_open(struct inode *inode, struct file *file)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
@@ -16,7 +77,9 @@ static int ceph_dir_open(struct inode *inode, struct file *file)
        cap = ceph_find_cap(inode, 0);
        if (!cap) {
                /* open this inode */
-               BUG_ON(1);  // writeme
+               cap = ceph_open(inode, file, O_DIRECTORY);
+               if (IS_ERR(cap))
+                       return PTR_ERR(cap);
        }
        
        fi = kzalloc(sizeof(*fi), GFP_KERNEL);
@@ -51,7 +114,7 @@ static int ceph_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
        int err;
        int i;
        struct qstr dname;
-       struct dentry *dn;
+       struct dentry *parent, *dn;
        struct inode *in;
 
 nextfrag:
@@ -64,7 +127,7 @@ nextfrag:
                if (fi->rinfo.reply) 
                        ceph_mdsc_destroy_reply_info(&fi->rinfo);
                
-               dout(10, "dir_readdir querying mds for frag %u\n", frag);
+               dout(10, "dir_readdir querying mds for ino %lu frag %u\n", filp->f_dentry->d_inode->i_ino, frag);
                req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_READDIR, 
                                               filp->f_dentry->d_inode->i_ino, "", 0, 0);
                if (IS_ERR(req)) 
@@ -76,19 +139,24 @@ nextfrag:
                dout(10, "dir_readdir got and parsed readdir result on frag %u\n", frag);
                
                /* pre-populate dentry cache */
-               if (0) for (i=0; i<fi->rinfo.dir_nr; i++) {
+               parent = filp->f_dentry;
+               for (i=0; i<fi->rinfo.dir_nr; i++) {
                        dname.name = fi->rinfo.dir_dname[i];
                        dname.len = fi->rinfo.dir_dname_len[i];
                        dname.hash = full_name_hash(dname.name, dname.len);
-                       dn = d_alloc(filp->f_dentry, &dname);
-                       if (dn == NULL)
-                               break;
+                       dn = d_alloc(parent, &dname);
+                       if (dn == NULL) {
+                               dout(30, "d_alloc badness\n");
+                               break; 
+                       }
                        in = new_inode(parent->d_sb);
                        if (in == NULL) {
+                               dout(30, "new_inode badness\n");
                                d_delete(dn);
                                break;
                        }
                        if (ceph_fill_inode(in, fi->rinfo.dir_in[i].in) < 0) {
+                               dout(30, "ceph_fill_inode badness\n");
                                iput(in);
                                d_delete(dn);
                                break;
@@ -100,7 +168,7 @@ nextfrag:
        }       
        
        while (off < fi->rinfo.dir_nr) {
-               dout(10, "dir_readdir off %d / %d\n", off, fi->rinfo.dir_nr);
+               dout(10, "dir_readdir off %d / %d name '%s'\n", off, fi->rinfo.dir_nr, fi->rinfo.dir_dname[off]);
                if (filldir(dirent, 
                            fi->rinfo.dir_dname[off], 
                            fi->rinfo.dir_dname_len[off], 
@@ -113,9 +181,9 @@ nextfrag:
                off++;
                filp->f_pos++;
        }
-       // next frag?
+
+       // next frag?  FIXME ***
        
-       // done.
        dout(20, "dir_readdir done.\n");
        return 0;
 }
@@ -143,28 +211,6 @@ const struct file_operations ceph_dir_fops = {
 };
 
 
-/*
- * ugly hack.  
- * - no locking.  
- * - should stop at mount root or current's CWD?
- */
-static int get_dentry_path(struct dentry *dn, char *buf, struct dentry *base)
-{
-       int len;
-       dout(20, "get_dentry_path in dn %p bas %p\n", dn, base);
-       if (dn == base) 
-               return 0;       
-
-       len = get_dentry_path(dn->d_parent, buf, base);
-       dout(20, "get_dentry_path out dn %p bas %p len %d adding %s\n", 
-            dn, base, len, dn->d_name.name);
-
-       buf[len++] = '/';
-       memcpy(buf+len, dn->d_name.name, dn->d_name.len);
-       len += dn->d_name.len;
-       buf[len] = 0;
-       return len;
-}
 
 static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry,
                                      struct nameidata *nameidata)
@@ -187,7 +233,7 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry,
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_STAT, 
                                       dir->i_sb->s_root->d_inode->i_ino, path, 0, 0);
        if (IS_ERR(req)) 
-               return req;
+               return ERR_PTR(PTR_ERR(req));
        if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, -1)) < 0)
                return ERR_PTR(err);
 
@@ -197,7 +243,7 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry,
        if (!inode)
                return ERR_PTR(-EACCES);
        if ((err = ceph_fill_inode(inode, rinfo.trace_in[rinfo.trace_nr-1].in)) < 0) 
-               return err;
+               return ERR_PTR(err);
        d_add(dentry, inode);
        return NULL;
 }
index 5345ca554549286676fb37245831436e8db08efe..2451d047e8b5024e12de7cd5e7d3d5914cee2008 100644 (file)
@@ -103,7 +103,7 @@ struct ceph_inode_cap *ceph_find_cap(struct inode *inode, int want)
 }
 
 
-int ceph_add_cap(struct inode *inode, int mds, u32 cap, u32 seq)
+struct ceph_inode_cap *ceph_add_cap(struct inode *inode, int mds, u32 cap, u32 seq)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        int i;
@@ -118,7 +118,7 @@ int ceph_add_cap(struct inode *inode, int mds, u32 cap, u32 seq)
                        if (ci->i_caps == NULL) {
                                ci->i_caps = o;
                                derr(0, "add_cap enomem\n");
-                               return -ENOMEM;
+                               return ERR_PTR(-ENOMEM);
                        }
                        memcpy(ci->i_caps, o, ci->i_nr_caps*sizeof(*ci->i_caps));
                        if (o != ci->i_caps_static)
@@ -137,7 +137,7 @@ int ceph_add_cap(struct inode *inode, int mds, u32 cap, u32 seq)
             inode, inode->i_ino, i, cap, cap|ci->i_caps[i].caps, seq, mds);
        ci->i_caps[i].caps |= cap;
        ci->i_caps[i].seq = seq;
-       return 0;
+       return &ci->i_caps[i];
 }
 
 
index a41c8dca8d2e0d25cf140904d2115b495ec3fa73..d8132f84eab2f31390a9b0f6664e2e5911c68f3a 100644 (file)
@@ -432,7 +432,11 @@ int parse_reply_info_trace(void **p, void *end, struct ceph_mds_reply_info *info
        
        /* alloc one longer shared array */
        info->trace_nr = numi;
-       info->trace_in = kmalloc(numi * (2*sizeof(void*)+sizeof(*info->trace_in)), GFP_KERNEL);
+       info->trace_in = kmalloc(numi * (sizeof(*info->trace_in) +
+                                        sizeof(*info->trace_dir) +
+                                        sizeof(*info->trace_dname) +
+                                        sizeof(*info->trace_dname_len)),
+                                GFP_KERNEL);
        if (info->trace_in == NULL)
                return -ENOMEM;
        info->trace_dir = (void*)(info->trace_in + numi);
@@ -489,11 +493,14 @@ int parse_reply_info_dir(void **p, void *end, struct ceph_mds_reply_info *info)
 
        /* alloc large array */
        info->dir_nr = num;
-       info->dir_in = kmalloc(3 * num * sizeof(void*), GFP_KERNEL);
+       info->dir_in = kmalloc(num * (sizeof(*info->dir_in) + 
+                                     sizeof(*info->dir_dname) + 
+                                     sizeof(*info->dir_dname_len)), 
+                              GFP_KERNEL);
        if (info->dir_in == NULL)
                return -ENOMEM;
-       info->dir_dname = (void*)(info->trace_in + num);
-       info->dir_dname_len = (void*)(info->trace_in + num*2);
+       info->dir_dname = (void*)(info->dir_in + num);
+       info->dir_dname_len = (void*)(info->dir_dname + num);
 
        while (num) {
                /* dentry, inode */
index c72632402b25ed8efa13958cd1b5e2ba308db9d5..db5c463eb02ec7e409d475cb8f32dee5274b6bee 100644 (file)
@@ -347,12 +347,13 @@ static int parse_mount_args(int flags, char *options, const char *dev_name, stru
        return 0;
 }
 
-int parse_open_reply(struct ceph_mds_client *mdsc, struct ceph_msg *reply, struct inode *inode)
+int parse_open_reply(struct ceph_msg *reply, struct inode *inode)
 {
        struct ceph_mds_reply_head *head;
        struct ceph_mds_reply_info rinfo;
        int frommds = reply->hdr.src.name.num;
        int err;
+       struct ceph_inode_cap *cap;
 
        /* parse reply */
        head = reply->front.iov_base;
@@ -367,10 +368,11 @@ int parse_open_reply(struct ceph_mds_client *mdsc, struct ceph_msg *reply, struc
                return err;
 
        /* fill in cap */
-       if ((err = ceph_add_cap(inode, frommds, 
-                               le32_to_cpu(head->file_caps), 
-                               le32_to_cpu(head->file_caps_seq))) < 0)
-               return err;
+       cap = ceph_add_cap(inode, frommds, 
+                          le32_to_cpu(head->file_caps), 
+                          le32_to_cpu(head->file_caps_seq));
+       if (IS_ERR(cap))
+               return PTR_ERR(cap);
 
        ceph_mdsc_destroy_reply_info(&rinfo);
        return 0;
@@ -387,6 +389,7 @@ static int open_root_inode(struct super_block *sb, struct ceph_mount_args *args)
        struct ceph_mds_reply_info rinfo;
        int frommds;
        int err;
+       struct ceph_inode_cap *cap;
        
        /* open dir */
        dout(30, "open_root_inode opening '%s'\n", args->path);
@@ -406,10 +409,13 @@ static int open_root_inode(struct super_block *sb, struct ceph_mount_args *args)
        
        /* fill in cap */
        frommds = rinfo.reply->hdr.src.name.num;
-       if ((err = ceph_add_cap(inode, frommds, 
-                               le32_to_cpu(rinfo.head->file_caps), 
-                               le32_to_cpu(rinfo.head->file_caps_seq))) < 0) 
+       cap = ceph_add_cap(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;
+       }
 
        root = d_alloc_root(inode);
        if (root == NULL) {
index 6fe39c841d127b3326ed475a7a84aaac559ad284..41d386f205400a7ea98431fd24fabd841de53916 100644 (file)
@@ -100,7 +100,7 @@ struct ceph_file_info {
 /* inode.c */
 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 int ceph_add_cap(struct inode *inode, int mds, u32 cap, u32 seq);
+extern struct ceph_inode_cap *ceph_add_cap(struct inode *inode, int mds, u32 cap, u32 seq);
 extern int ceph_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
                              struct kstat *stat);