Merge branch 'foreign/liubo/replace-lockup' into for-chris-4.6
[cascardo/linux.git] / fs / btrfs / inode.c
index f8be740..d4381f5 100644 (file)
@@ -4212,11 +4212,20 @@ static int truncate_space_check(struct btrfs_trans_handle *trans,
 {
        int ret;
 
+       /*
+        * This is only used to apply pressure to the enospc system, we don't
+        * intend to use this reservation at all.
+        */
        bytes_deleted = btrfs_csum_bytes_to_leaves(root, bytes_deleted);
+       bytes_deleted *= root->nodesize;
        ret = btrfs_block_rsv_add(root, &root->fs_info->trans_block_rsv,
                                  bytes_deleted, BTRFS_RESERVE_NO_FLUSH);
-       if (!ret)
+       if (!ret) {
+               trace_btrfs_space_reservation(root->fs_info, "transaction",
+                                             trans->transid,
+                                             bytes_deleted, 1);
                trans->bytes_reserved += bytes_deleted;
+       }
        return ret;
 
 }
@@ -5722,6 +5731,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
        char *name_ptr;
        int name_len;
        int is_curr = 0;        /* ctx->pos points to the current index? */
+       bool emitted;
 
        /* FIXME, use a real flag for deciding about the key type */
        if (root->fs_info->tree_root == root)
@@ -5750,6 +5760,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
        if (ret < 0)
                goto err;
 
+       emitted = false;
        while (1) {
                leaf = path->nodes[0];
                slot = path->slots[0];
@@ -5829,6 +5840,7 @@ skip:
 
                        if (over)
                                goto nopos;
+                       emitted = true;
                        di_len = btrfs_dir_name_len(leaf, di) +
                                 btrfs_dir_data_len(leaf, di) + sizeof(*di);
                        di_cur += di_len;
@@ -5841,11 +5853,20 @@ next:
        if (key_type == BTRFS_DIR_INDEX_KEY) {
                if (is_curr)
                        ctx->pos++;
-               ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
+               ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
                if (ret)
                        goto nopos;
        }
 
+       /*
+        * If we haven't emitted any dir entry, we must not touch ctx->pos as
+        * it was was set to the termination value in previous call. We assume
+        * that "." and ".." were emitted if we reach this point and set the
+        * termination value as well for an empty directory.
+        */
+       if (ctx->pos > 2 && !emitted)
+               goto nopos;
+
        /* Reached end of directory/root. Bump pos past the last item. */
        ctx->pos++;