aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e28f3d4691af..5f06eb1f4384 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7116,21 +7116,41 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
7116 if (ret) 7116 if (ret)
7117 return ERR_PTR(ret); 7117 return ERR_PTR(ret);
7118 7118
7119 em = create_pinned_em(inode, start, ins.offset, start, ins.objectid, 7119 /*
7120 ins.offset, ins.offset, ins.offset, 0); 7120 * Create the ordered extent before the extent map. This is to avoid
7121 if (IS_ERR(em)) { 7121 * races with the fast fsync path that would lead to it logging file
7122 btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1); 7122 * extent items that point to disk extents that were not yet written to.
7123 return em; 7123 * The fast fsync path collects ordered extents into a local list and
7124 } 7124 * then collects all the new extent maps, so we must create the ordered
7125 7125 * extent first and make sure the fast fsync path collects any new
7126 * ordered extents after collecting new extent maps as well.
7127 * The fsync path simply can not rely on inode_dio_wait() because it
7128 * causes deadlock with AIO.
7129 */
7126 ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid, 7130 ret = btrfs_add_ordered_extent_dio(inode, start, ins.objectid,
7127 ins.offset, ins.offset, 0); 7131 ins.offset, ins.offset, 0);
7128 if (ret) { 7132 if (ret) {
7129 btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1); 7133 btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
7130 free_extent_map(em);
7131 return ERR_PTR(ret); 7134 return ERR_PTR(ret);
7132 } 7135 }
7133 7136
7137 em = create_pinned_em(inode, start, ins.offset, start, ins.objectid,
7138 ins.offset, ins.offset, ins.offset, 0);
7139 if (IS_ERR(em)) {
7140 struct btrfs_ordered_extent *oe;
7141
7142 btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
7143 oe = btrfs_lookup_ordered_extent(inode, start);
7144 ASSERT(oe);
7145 if (WARN_ON(!oe))
7146 return em;
7147 set_bit(BTRFS_ORDERED_IOERR, &oe->flags);
7148 set_bit(BTRFS_ORDERED_IO_DONE, &oe->flags);
7149 btrfs_remove_ordered_extent(inode, oe);
7150 /* Once for our lookup and once for the ordered extents tree. */
7151 btrfs_put_ordered_extent(oe);
7152 btrfs_put_ordered_extent(oe);
7153 }
7134 return em; 7154 return em;
7135} 7155}
7136 7156