diff mbox series

[RFC,21/31] btrfs: Carve out btrfs_buffered_iomap_end from the write path

Message ID 9719e5a213073fe0e49370906a76a76f1b85629e.1623567940.git.rgoldwyn@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs buffered iomap support | expand

Commit Message

Goldwyn Rodrigues June 13, 2021, 1:39 p.m. UTC
From: Goldwyn Rodrigues <rgoldwyn@suse.com>

Carve out btrfs_buffered_iomap_end() from the write path to form
iomap_end() function for writes.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/btrfs/file.c | 97 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 59 insertions(+), 38 deletions(-)
diff mbox series

Patch

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 5751bb5e0656..ab2b1790e0bb 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1678,6 +1678,63 @@  static int btrfs_buffered_iomap_begin(struct inode *inode, loff_t pos,
 
 }
 
+static int btrfs_buffered_iomap_end(struct inode *inode, loff_t pos,
+		loff_t length, ssize_t written, struct btrfs_iomap *bi)
+{
+	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+	size_t num_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bi->reserved_bytes);
+	size_t dirty_sectors = 0;
+	int dirty_pages = 0;
+	int sector_offset = pos & (fs_info->sectorsize - 1);
+
+	if (written) {
+		dirty_sectors = round_up(written + sector_offset,
+				fs_info->sectorsize);
+		dirty_sectors = BTRFS_BYTES_TO_BLKS(fs_info, dirty_sectors);
+		dirty_pages = DIV_ROUND_UP(written + offset_in_page(pos),
+				PAGE_SIZE);
+	}
+
+	/* Release excess reservations */
+	if (num_sectors > dirty_sectors) {
+		size_t release_bytes = bi->reserved_bytes -
+			(dirty_sectors << fs_info->sb->s_blocksize_bits);
+		if (bi->metadata_only) {
+			btrfs_delalloc_release_metadata(BTRFS_I(inode),
+					release_bytes, true);
+		} else {
+			u64 p;
+
+			p = round_down(pos,
+					fs_info->sectorsize) +
+				(dirty_pages << PAGE_SHIFT);
+			btrfs_delalloc_release_space(BTRFS_I(inode),
+					bi->data_reserved, p,
+					release_bytes, true);
+		}
+	}
+
+	/*
+	 * If we have not locked the extent range, because the range's
+	 * start offset is >= i_size, we might still have a non-NULL
+	 * cached extent state, acquired while marking the extent range
+	 * as delalloc through btrfs_dirty_pages(). Therefore free any
+	 * possible cached extent state to avoid a memory leak.
+	 */
+	if (bi->extents_locked)
+		unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+				bi->lockstart, bi->lockend,
+				&bi->cached_state);
+	else
+		free_extent_state(bi->cached_state);
+
+	btrfs_delalloc_release_extents(BTRFS_I(inode), bi->reserved_bytes);
+	if (bi->metadata_only)
+		btrfs_check_nocow_unlock(BTRFS_I(inode));
+
+	return 0;
+}
+
 static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 					       struct iov_iter *i)
 {
@@ -1736,7 +1793,6 @@  static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 		size_t dirty_pages;
 		size_t copied;
 		size_t dirty_sectors;
-		size_t num_sectors;
 
 		/*
 		 * Fault pages before locking them in prepare_pages
@@ -1776,7 +1832,6 @@  static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 
 		copied = btrfs_copy_from_user(pos, write_bytes, pages, i);
 
-		num_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bi->reserved_bytes);
 		dirty_sectors = round_up(copied + sector_offset,
 					fs_info->sectorsize);
 		dirty_sectors = BTRFS_BYTES_TO_BLKS(fs_info, dirty_sectors);
@@ -1796,26 +1851,6 @@  static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 						   PAGE_SIZE);
 		}
 
-		release_bytes = bi->reserved_bytes;
-
-		if (num_sectors > dirty_sectors) {
-			/* release everything except the sectors we dirtied */
-			release_bytes -= dirty_sectors << fs_info->sectorsize_bits;
-			if (bi->metadata_only) {
-				btrfs_delalloc_release_metadata(BTRFS_I(inode),
-							release_bytes, true);
-			} else {
-				u64 __pos;
-
-				__pos = round_down(pos,
-						   fs_info->sectorsize) +
-					(dirty_pages << PAGE_SHIFT);
-				btrfs_delalloc_release_space(BTRFS_I(inode),
-						bi->data_reserved, __pos,
-						release_bytes, true);
-			}
-		}
-
 		release_bytes = round_up(copied + sector_offset,
 					fs_info->sectorsize);
 
@@ -1824,27 +1859,13 @@  static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 					&bi->cached_state,
 					bi->metadata_only);
 
-		/*
-		 * If we have not locked the extent range, because the range's
-		 * start offset is >= i_size, we might still have a non-NULL
-		 * cached extent state, acquired while marking the extent range
-		 * as delalloc through btrfs_dirty_pages(). Therefore free any
-		 * possible cached extent state to avoid a memory leak.
-		 */
-		if (bi->extents_locked)
-			unlock_extent_cached(&BTRFS_I(inode)->io_tree,
-					     bi->lockstart, bi->lockend,
-					     &bi->cached_state);
-		else
-			free_extent_state(bi->cached_state);
-		bi->extents_locked = false;
-
-		btrfs_delalloc_release_extents(BTRFS_I(inode), bi->reserved_bytes);
 		if (ret) {
 			btrfs_drop_pages(pages, num_pages);
 			break;
 		}
 
+		btrfs_buffered_iomap_end(inode, pos, write_bytes, copied, bi);
+
 		release_bytes = 0;
 		if (bi->metadata_only)
 			btrfs_check_nocow_unlock(BTRFS_I(inode));