diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-02-18 03:28:03 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-02-18 03:28:03 -0500 |
commit | 3a2f2ac9b96f9a9f5538396a212d3b9fb543bfc5 (patch) | |
tree | 294c2f340b11584e58cea90adfc4182ac8742348 /fs/btrfs/inode.c | |
parent | 4e79e182b419172e35936a47f098509092d69817 (diff) | |
parent | f4eafd8bcd5229e998aa252627703b8462c3b90f (diff) |
Merge branch 'x86/urgent' into x86/asm, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e28f3d4691af..151b7c71b868 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -5717,6 +5717,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) | |||
5717 | char *name_ptr; | 5717 | char *name_ptr; |
5718 | int name_len; | 5718 | int name_len; |
5719 | int is_curr = 0; /* ctx->pos points to the current index? */ | 5719 | int is_curr = 0; /* ctx->pos points to the current index? */ |
5720 | bool emitted; | ||
5720 | 5721 | ||
5721 | /* FIXME, use a real flag for deciding about the key type */ | 5722 | /* FIXME, use a real flag for deciding about the key type */ |
5722 | if (root->fs_info->tree_root == root) | 5723 | if (root->fs_info->tree_root == root) |
@@ -5745,6 +5746,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) | |||
5745 | if (ret < 0) | 5746 | if (ret < 0) |
5746 | goto err; | 5747 | goto err; |
5747 | 5748 | ||
5749 | emitted = false; | ||
5748 | while (1) { | 5750 | while (1) { |
5749 | leaf = path->nodes[0]; | 5751 | leaf = path->nodes[0]; |
5750 | slot = path->slots[0]; | 5752 | slot = path->slots[0]; |
@@ -5824,6 +5826,7 @@ skip: | |||
5824 | 5826 | ||
5825 | if (over) | 5827 | if (over) |
5826 | goto nopos; | 5828 | goto nopos; |
5829 | emitted = true; | ||
5827 | di_len = btrfs_dir_name_len(leaf, di) + | 5830 | di_len = btrfs_dir_name_len(leaf, di) + |
5828 | btrfs_dir_data_len(leaf, di) + sizeof(*di); | 5831 | btrfs_dir_data_len(leaf, di) + sizeof(*di); |
5829 | di_cur += di_len; | 5832 | di_cur += di_len; |
@@ -5836,11 +5839,20 @@ next: | |||
5836 | if (key_type == BTRFS_DIR_INDEX_KEY) { | 5839 | if (key_type == BTRFS_DIR_INDEX_KEY) { |
5837 | if (is_curr) | 5840 | if (is_curr) |
5838 | ctx->pos++; | 5841 | ctx->pos++; |
5839 | ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list); | 5842 | ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted); |
5840 | if (ret) | 5843 | if (ret) |
5841 | goto nopos; | 5844 | goto nopos; |
5842 | } | 5845 | } |
5843 | 5846 | ||
5847 | /* | ||
5848 | * If we haven't emitted any dir entry, we must not touch ctx->pos as | ||
5849 | * it was was set to the termination value in previous call. We assume | ||
5850 | * that "." and ".." were emitted if we reach this point and set the | ||
5851 | * termination value as well for an empty directory. | ||
5852 | */ | ||
5853 | if (ctx->pos > 2 && !emitted) | ||
5854 | goto nopos; | ||
5855 | |||
5844 | /* Reached end of directory/root. Bump pos past the last item. */ | 5856 | /* Reached end of directory/root. Bump pos past the last item. */ |
5845 | ctx->pos++; | 5857 | ctx->pos++; |
5846 | 5858 | ||
@@ -7116,21 +7128,41 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | |||
7116 | if (ret) | 7128 | if (ret) |
7117 | return ERR_PTR(ret); | 7129 | return ERR_PTR(ret); |
7118 | 7130 | ||
7119 | em = create_pinned_em(inode, start, ins.offset, start, ins.objectid, | 7131 | /* |
7120 | ins.offset, ins.offset, ins.offset, 0); | 7132 | * Create the ordered extent before the extent map. This is to avoid |
7121 | if (IS_ERR(em)) { | 7133 | * races with the fast fsync path that would lead to it logging file |
7122 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1); | 7134 | * extent items that point to disk extents that were not yet written to. |
7123 | return em; | 7135 | * The fast fsync path collects ordered extents into a local list and |
7124 | } | 7136 | * then collects all the new extent maps, so we must create the ordered |
7125 | 7137 | * extent first and make sure the fast fsync path collects any new | |
7138 | * ordered extents after collecting new extent maps as well. | ||
7139 | * The fsync path simply can not rely on inode_dio_wait() because it | ||
7140 | * causes deadlock with AIO. | ||
7141 | */ | ||
7126 | ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid, | 7142 | ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid, |
7127 | ins.offset, ins.offset, 0); | 7143 | ins.offset, ins.offset, 0); |
7128 | if (ret) { | 7144 | if (ret) { |
7129 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1); | 7145 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1); |
7130 | free_extent_map(em); | ||
7131 | return ERR_PTR(ret); | 7146 | return ERR_PTR(ret); |
7132 | } | 7147 | } |
7133 | 7148 | ||
7149 | em = create_pinned_em(inode, start, ins.offset, start, ins.objectid, | ||
7150 | ins.offset, ins.offset, ins.offset, 0); | ||
7151 | if (IS_ERR(em)) { | ||
7152 | struct btrfs_ordered_extent *oe; | ||
7153 | |||
7154 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1); | ||
7155 | oe = btrfs_lookup_ordered_extent(inode, start); | ||
7156 | ASSERT(oe); | ||
7157 | if (WARN_ON(!oe)) | ||
7158 | return em; | ||
7159 | set_bit(BTRFS_ORDERED_IOERR, &oe->flags); | ||
7160 | set_bit(BTRFS_ORDERED_IO_DONE, &oe->flags); | ||
7161 | btrfs_remove_ordered_extent(inode, oe); | ||
7162 | /* Once for our lookup and once for the ordered extents tree. */ | ||
7163 | btrfs_put_ordered_extent(oe); | ||
7164 | btrfs_put_ordered_extent(oe); | ||
7165 | } | ||
7134 | return em; | 7166 | return em; |
7135 | } | 7167 | } |
7136 | 7168 | ||