fs/ceph: Use ERR_CAST
[safe/jmp/linux-2.6] / fs / ceph / inode.c
index ef91723..226f5a5 100644 (file)
@@ -69,7 +69,7 @@ struct inode *ceph_get_snapdir(struct inode *parent)
 
        BUG_ON(!S_ISDIR(parent->i_mode));
        if (IS_ERR(inode))
-               return ERR_PTR(PTR_ERR(inode));
+               return inode;
        inode->i_mode = parent->i_mode;
        inode->i_uid = parent->i_uid;
        inode->i_gid = parent->i_gid;
@@ -619,6 +619,7 @@ static int fill_inode(struct inode *inode,
                        memcpy(ci->i_xattrs.blob->vec.iov_base,
                               iinfo->xattr_data, iinfo->xattr_len);
                ci->i_xattrs.version = le64_to_cpu(info->xattr_version);
+               xattr_blob = NULL;
        }
 
        inode->i_mapping->a_ops = &ceph_aops;
@@ -674,7 +675,8 @@ static int fill_inode(struct inode *inode,
                /* set dir completion flag? */
                if (ci->i_files == 0 && ci->i_subdirs == 0 &&
                    ceph_snap(inode) == CEPH_NOSNAP &&
-                   (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED)) {
+                   (le32_to_cpu(info->cap.caps) & CEPH_CAP_FILE_SHARED) &&
+                   (ci->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
                        dout(" marking %p complete (empty)\n", inode);
                        ci->i_ceph_flags |= CEPH_I_COMPLETE;
                        ci->i_max_offset = 2;
@@ -802,6 +804,37 @@ out_unlock:
 }
 
 /*
+ * Set dentry's directory position based on the current dir's max, and
+ * order it in d_subdirs, so that dcache_readdir behaves.
+ */
+static void ceph_set_dentry_offset(struct dentry *dn)
+{
+       struct dentry *dir = dn->d_parent;
+       struct inode *inode = dn->d_parent->d_inode;
+       struct ceph_dentry_info *di;
+
+       BUG_ON(!inode);
+
+       di = ceph_dentry(dn);
+
+       spin_lock(&inode->i_lock);
+       if ((ceph_inode(inode)->i_ceph_flags & CEPH_I_COMPLETE) == 0) {
+               spin_unlock(&inode->i_lock);
+               return;
+       }
+       di->offset = ceph_inode(inode)->i_max_offset++;
+       spin_unlock(&inode->i_lock);
+
+       spin_lock(&dcache_lock);
+       spin_lock(&dn->d_lock);
+       list_move_tail(&dir->d_subdirs, &dn->d_u.d_child);
+       dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
+            dn->d_u.d_child.prev, dn->d_u.d_child.next);
+       spin_unlock(&dn->d_lock);
+       spin_unlock(&dcache_lock);
+}
+
+/*
  * splice a dentry to an inode.
  * caller must hold directory i_mutex for this to be safe.
  *
@@ -814,6 +847,8 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
 {
        struct dentry *realdn;
 
+       BUG_ON(dn->d_inode);
+
        /* dn must be unhashed */
        if (!d_unhashed(dn))
                d_drop(dn);
@@ -835,44 +870,17 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
                dn = realdn;
        } else {
                BUG_ON(!ceph_dentry(dn));
-
                dout("dn %p attached to %p ino %llx.%llx\n",
                     dn, dn->d_inode, ceph_vinop(dn->d_inode));
        }
        if ((!prehash || *prehash) && d_unhashed(dn))
                d_rehash(dn);
+       ceph_set_dentry_offset(dn);
 out:
        return dn;
 }
 
 /*
- * Set dentry's directory position based on the current dir's max, and
- * order it in d_subdirs, so that dcache_readdir behaves.
- */
-static void ceph_set_dentry_offset(struct dentry *dn)
-{
-       struct dentry *dir = dn->d_parent;
-       struct inode *inode = dn->d_parent->d_inode;
-       struct ceph_dentry_info *di;
-
-       BUG_ON(!inode);
-
-       di = ceph_dentry(dn);
-
-       spin_lock(&inode->i_lock);
-       di->offset = ceph_inode(inode)->i_max_offset++;
-       spin_unlock(&inode->i_lock);
-
-       spin_lock(&dcache_lock);
-       spin_lock(&dn->d_lock);
-       list_move_tail(&dir->d_subdirs, &dn->d_u.d_child);
-       dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
-            dn->d_u.d_child.prev, dn->d_u.d_child.next);
-       spin_unlock(&dn->d_lock);
-       spin_unlock(&dcache_lock);
-}
-
-/*
  * Incorporate results into the local cache.  This is either just
  * one inode, or a directory, dentry, and possibly linked-to inode (e.g.,
  * after a lookup).
@@ -933,21 +941,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
 
        if (!rinfo->head->is_target && !rinfo->head->is_dentry) {
                dout("fill_trace reply is empty!\n");
-               if (rinfo->head->result == 0 && req->r_locked_dir) {
-                       struct ceph_inode_info *ci =
-                               ceph_inode(req->r_locked_dir);
-                       dout(" clearing %p complete (empty trace)\n",
-                            req->r_locked_dir);
-                       spin_lock(&req->r_locked_dir->i_lock);
-                       ci->i_ceph_flags &= ~CEPH_I_COMPLETE;
-                       ci->i_release_count++;
-                       spin_unlock(&req->r_locked_dir->i_lock);
-
-                       if (req->r_dentry)
-                               ceph_invalidate_dentry_lease(req->r_dentry);
-                       if (req->r_old_dentry)
-                               ceph_invalidate_dentry_lease(req->r_old_dentry);
-               }
+               if (rinfo->head->result == 0 && req->r_locked_dir)
+                       ceph_invalidate_dir_request(req);
                return 0;
        }
 
@@ -1024,6 +1019,9 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                        ceph_invalidate_dentry_lease(dn);
 
                        /* take overwritten dentry's readdir offset */
+                       dout("dn %p gets %p offset %lld (old offset %lld)\n",
+                            req->r_old_dentry, dn, ceph_dentry(dn)->offset,
+                            ceph_dentry(req->r_old_dentry)->offset);
                        ceph_dentry(req->r_old_dentry)->offset =
                                ceph_dentry(dn)->offset;
 
@@ -1068,7 +1066,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                                goto done;
                        }
                        req->r_dentry = dn;  /* may have spliced */
-                       ceph_set_dentry_offset(dn);
                        igrab(in);
                } else if (ceph_ino(in) == vino.ino &&
                           ceph_snap(in) == vino.snap) {
@@ -1111,7 +1108,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
                        err = PTR_ERR(dn);
                        goto done;
                }
-               ceph_set_dentry_offset(dn);
                req->r_dentry = dn;  /* may have spliced */
                igrab(in);
                rinfo->head->is_dentry = 1;  /* fool notrace handlers */