diff mbox series

[RFC,20/31] btrfs: Carve out btrfs_buffered_iomap_begin() from write path

Message ID bc0e662fb8728a4cec08e6ce4000971819ede942.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 reservation and locking from bufferd write sequence in
btrfs_buffered_iomap_begin().

Shortcomings: page handling with respect to nrptrs is messed up.
However, since we will be passing the responsibility of pages to iomap,
this will not be problem.

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

Patch

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index ccae8ce7ec4f..5751bb5e0656 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1627,6 +1627,57 @@  static void btrfs_iomap_release(struct inode *inode,
 	kfree(bi);
 }
 
+static int btrfs_buffered_iomap_begin(struct inode *inode, loff_t pos,
+		size_t length, struct btrfs_iomap *bi)
+{
+	int ret;
+	size_t write_bytes = length;
+	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+	size_t sector_offset = pos & (fs_info->sectorsize - 1);
+
+	ret = btrfs_check_data_free_space(BTRFS_I(inode),
+			&bi->data_reserved, pos, write_bytes);
+	if (ret < 0) {
+		/*
+		 * If we don't have to COW at the offset, reserve
+		 * metadata only. write_bytes may get smaller than
+		 * requested here.
+		 */
+		if (btrfs_check_nocow_lock(BTRFS_I(inode), pos,
+					&write_bytes) > 0)
+			bi->metadata_only = true;
+		else
+			return ret;
+	}
+
+	bi->reserved_bytes = round_up(write_bytes + sector_offset,
+			fs_info->sectorsize);
+	WARN_ON(bi->reserved_bytes == 0);
+	ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode),
+			bi->reserved_bytes);
+	if (ret) {
+		if (!bi->metadata_only)
+			btrfs_free_reserved_data_space(BTRFS_I(inode),
+					bi->data_reserved, pos,
+					write_bytes);
+		else
+			btrfs_check_nocow_unlock(BTRFS_I(inode));
+		return ret;
+	}
+
+	if (pos < inode->i_size) {
+		bi->lockstart = round_down(pos, fs_info->sectorsize);
+		bi->lockend = round_up(pos + write_bytes, fs_info->sectorsize) - 1;
+		btrfs_lock_and_flush_ordered_range(BTRFS_I(inode),
+				bi->lockstart, bi->lockend,
+				&bi->cached_state);
+		bi->extents_locked = true;
+	}
+
+	return 0;
+
+}
+
 static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 					       struct iov_iter *i)
 {
@@ -1701,50 +1752,15 @@  static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
 		sector_offset = pos & (fs_info->sectorsize - 1);
 
 		extent_changeset_release(bi->data_reserved);
-		ret = btrfs_check_data_free_space(BTRFS_I(inode),
-						  &bi->data_reserved, pos,
-						  write_bytes);
-		if (ret < 0) {
-			/*
-			 * If we don't have to COW at the offset, reserve
-			 * metadata only. write_bytes may get smaller than
-			 * requested here.
-			 */
-			if (btrfs_check_nocow_lock(BTRFS_I(inode), pos,
-						   &write_bytes) > 0)
-				bi->metadata_only = true;
-			else
-				break;
-		}
 
-		num_pages = DIV_ROUND_UP(write_bytes + offset, PAGE_SIZE);
-		WARN_ON(num_pages > nrptrs);
-		bi->reserved_bytes = round_up(write_bytes + sector_offset,
-					 fs_info->sectorsize);
-		WARN_ON(bi->reserved_bytes == 0);
-		ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode),
-				bi->reserved_bytes);
-		if (ret) {
-			if (!bi->metadata_only)
-				btrfs_free_reserved_data_space(BTRFS_I(inode),
-						bi->data_reserved, pos,
-						write_bytes);
-			else
-				btrfs_check_nocow_unlock(BTRFS_I(inode));
-			break;
-		}
-
-		release_bytes = bi->reserved_bytes;
+		ret = btrfs_buffered_iomap_begin(inode, pos, write_bytes,
+				bi);
 
-		if (pos < inode->i_size) {
-			bi->lockstart = round_down(pos, fs_info->sectorsize);
-			bi->lockend = round_up(pos + write_bytes, fs_info->sectorsize) - 1;
-			btrfs_lock_and_flush_ordered_range(BTRFS_I(inode),
-					bi->lockstart, bi->lockend,
-					&bi->cached_state);
-			bi->extents_locked = true;
-		}
+		if (ret < 0)
+			goto out;
 
+		num_pages = DIV_ROUND_UP(write_bytes + offset, PAGE_SIZE);
+		WARN_ON(num_pages > nrptrs);
 		/*
 		 * This is going to setup the pages array with the number of
 		 * pages we want, so we don't really need to worry about the
@@ -1780,6 +1796,8 @@  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;