* transid that last logged this inode
         */
        u64 logged_trans;
+
+       /* trans that last made a change that should be fully fsync'd */
+       u64 log_dirty_trans;
        u64 delalloc_bytes;
        u64 disk_i_size;
        u32 flags;
 
        }
        mutex_unlock(&root->fs_info->trans_mutex);
 
+       root->fs_info->tree_log_batch++;
        filemap_fdatawait(inode->i_mapping);
+       root->fs_info->tree_log_batch++;
 
        /*
         * ok we haven't committed the transaction yet, lets do a commit
        }
 
        ret = btrfs_log_dentry_safe(trans, root, file->f_dentry);
-       if (ret < 0)
+       if (ret < 0) {
                goto out;
+       }
+
+       /* we've logged all the items and now have a consistent
+        * version of the file in the log.  It is possible that
+        * someone will come in and modify the file, but that's
+        * fine because the log is consistent on disk, and we
+        * have references to all of the file's extents
+        *
+        * It is possible that someone will come in and log the
+        * file again, but that will end up using the synchronization
+        * inside btrfs_sync_log to keep things safe.
+        */
+       mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+
        if (ret > 0) {
                ret = btrfs_commit_transaction(trans, root);
        } else {
                btrfs_sync_log(trans, root);
                ret = btrfs_end_transaction(trans, root);
        }
+       mutex_lock(&file->f_dentry->d_inode->i_mutex);
 out:
        return ret > 0 ? EIO : ret;
 }
 
 
        ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
                                         inode, dir->i_ino);
-       BUG_ON(ret);
+       BUG_ON(ret != 0 && ret != -ENOENT);
+       if (ret != -ENOENT)
+               BTRFS_I(dir)->log_dirty_trans = trans->transid;
 
        ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len,
                                           dir, index);
        bi->disk_i_size = 0;
        bi->flags = 0;
        bi->index_cnt = (u64)-1;
+       bi->log_dirty_trans = 0;
        extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
        extent_io_tree_init(&BTRFS_I(inode)->io_tree,
                             inode->i_mapping, GFP_NOFS);
 
        atomic_set(&log->fs_info->tree_log_commit, 1);
 
        while(1) {
+               batch = log->fs_info->tree_log_batch;
                mutex_unlock(&log->fs_info->tree_log_mutex);
                schedule_timeout_uninterruptible(1);
                mutex_lock(&log->fs_info->tree_log_mutex);
-               batch = log->fs_info->tree_log_batch;
 
                while(atomic_read(&log->fs_info->tree_log_writers)) {
                        DEFINE_WAIT(wait);
        mutex_unlock(&BTRFS_I(inode)->log_mutex);
        end_log_trans(root);
 
-       if (ret == 0 || ret == -ENOENT)
-               return 0;
        return ret;
 }
 
                else
                        break;
        }
-       if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
+       if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode) &&
+           BTRFS_I(inode)->log_dirty_trans >= trans->transid) {
                btrfs_release_path(root, path);
                btrfs_release_path(log, dst_path);
+               BTRFS_I(inode)->log_dirty_trans = 0;
                ret = log_directory_changes(trans, root, inode, path, dst_path);
                BUG_ON(ret);
        }