diff mbox series

btrfs: Increment i_size after dio write completes

Message ID 20200921191930.e7phg6zpw4v4snin@fiona
State New
Headers show
Series btrfs: Increment i_size after dio write completes | expand

Commit Message

Goldwyn Rodrigues Sept. 21, 2020, 7:19 p.m. UTC
i_size is incremented when btrfs creates new extents during the start of
a DIO write. If there is a failure until the endio, we will have a file
with incremented filesize but no data. Increment the filesize after the
successful completion of a DIO write.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>

Comments

Josef Bacik Oct. 5, 2020, 1:14 p.m. UTC | #1
On 9/21/20 3:19 PM, Goldwyn Rodrigues wrote:
> i_size is incremented when btrfs creates new extents during the start of
> a DIO write. If there is a failure until the endio, we will have a file
> with incremented filesize but no data. Increment the filesize after the
> successful completion of a DIO write.
> 
> Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
> 

We can't update the i_size outside of the i_mutex, this isn't ok.  Thanks,

Josef
diff mbox series

Patch

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 18d171b2d544..0f297e9679eb 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7309,13 +7309,6 @@  static int btrfs_get_blocks_direct_write(struct extent_map **map,
 	len = min(len, em->len - (start - em->start));
 
 skip_cow:
-	/*
-	 * Need to update the i_size under the extent lock so buffered
-	 * readers will get the updated i_size when we unlock.
-	 */
-	if (start + len > i_size_read(inode))
-		i_size_write(inode, start + len);
-
 	dio_data->reserve -= len;
 out:
 	return ret;
@@ -7542,10 +7535,16 @@  static void btrfs_dio_private_put(struct btrfs_dio_private *dip)
 		return;
 
 	if (bio_op(dip->dio_bio) == REQ_OP_WRITE) {
-		__endio_write_update_ordered(BTRFS_I(dip->inode),
-					     dip->logical_offset,
-					     dip->bytes,
-					     !dip->dio_bio->bi_status);
+		u64 offset = dip->logical_offset;
+		u64 length = dip->bytes;
+		bool uptodate = !dip->dio_bio->bi_status;
+
+		/* Increment the filesize iff the DIO write is successful */
+		if (uptodate && i_size_read(dip->inode) < offset + length)
+			i_size_write(dip->inode, offset + length);
+
+		__endio_write_update_ordered(BTRFS_I(dip->inode), offset,
+				length, uptodate);
 	} else {
 		unlock_extent(&BTRFS_I(dip->inode)->io_tree,
 			      dip->logical_offset,