Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[sfrench/cifs-2.6.git] / fs / ceph / dir.c
index 681a8537b64f821c443a29af4c64a0c8c8a38a36..c241603764fdc560ae72cea19410b49c15e860d2 100644 (file)
@@ -183,7 +183,7 @@ more:
        spin_unlock(&parent->d_lock);
 
        /* make sure a dentry wasn't dropped while we didn't have parent lock */
-       if (!ceph_dir_is_complete(dir)) {
+       if (!ceph_dir_is_complete_ordered(dir)) {
                dout(" lost dir complete on %p; falling back to mds\n", dir);
                dput(dentry);
                err = -EAGAIN;
@@ -261,10 +261,6 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
 
        /* always start with . and .. */
        if (ctx->pos == 0) {
-               /* note dir version at start of readdir so we can tell
-                * if any dentries get dropped */
-               fi->dir_release_count = atomic_read(&ci->i_release_count);
-
                dout("readdir off 0 -> '.'\n");
                if (!dir_emit(ctx, ".", 1, 
                            ceph_translate_ino(inode->i_sb, inode->i_ino),
@@ -289,7 +285,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
        if ((ctx->pos == 2 || fi->dentry) &&
            !ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
            ceph_snap(inode) != CEPH_SNAPDIR &&
-           __ceph_dir_is_complete(ci) &&
+           __ceph_dir_is_complete_ordered(ci) &&
            __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) {
                u32 shared_gen = ci->i_shared_gen;
                spin_unlock(&ci->i_ceph_lock);
@@ -312,6 +308,13 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
 
        /* proceed with a normal readdir */
 
+       if (ctx->pos == 2) {
+               /* note dir version at start of readdir so we can tell
+                * if any dentries get dropped */
+               fi->dir_release_count = atomic_read(&ci->i_release_count);
+               fi->dir_ordered_count = ci->i_ordered_count;
+       }
+
 more:
        /* do we have the correct frag content buffered? */
        if (fi->frag != frag || fi->last_readdir == NULL) {
@@ -446,8 +449,12 @@ more:
         */
        spin_lock(&ci->i_ceph_lock);
        if (atomic_read(&ci->i_release_count) == fi->dir_release_count) {
-               dout(" marking %p complete\n", inode);
-               __ceph_dir_set_complete(ci, fi->dir_release_count);
+               if (ci->i_ordered_count == fi->dir_ordered_count)
+                       dout(" marking %p complete and ordered\n", inode);
+               else
+                       dout(" marking %p complete\n", inode);
+               __ceph_dir_set_complete(ci, fi->dir_release_count,
+                                       fi->dir_ordered_count);
        }
        spin_unlock(&ci->i_ceph_lock);
 
@@ -805,7 +812,9 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
                acls.pagelist = NULL;
        }
        err = ceph_mdsc_do_request(mdsc, dir, req);
-       if (!err && !req->r_reply_info.head->is_dentry)
+       if (!err &&
+           !req->r_reply_info.head->is_target &&
+           !req->r_reply_info.head->is_dentry)
                err = ceph_handle_notrace_create(dir, dentry);
        ceph_mdsc_put_request(req);
 out: