diff mbox series

[1/2] xfs: introduce xfs_bmap_split_da_extent

Message ID 20191226134721.43797-2-yukuai3@huawei.com (mailing list archive)
State New, archived
Headers show
Series fix stale data exposure problem | expand

Commit Message

Yu Kuai Dec. 26, 2019, 1:47 p.m. UTC
Add a new function xfs_bmap_split_da_extent to split a delalloc extent
into two delalloc extents.

Signed-off-by: yu kuai <yukuai3@huawei.com>
---
 fs/xfs/libxfs/xfs_bmap.c | 26 ++++++++++++++++++++++++--
 fs/xfs/libxfs/xfs_bmap.h |  1 +
 2 files changed, 25 insertions(+), 2 deletions(-)

Comments

Dave Chinner Jan. 5, 2020, 9:04 p.m. UTC | #1
On Thu, Dec 26, 2019 at 09:47:20PM +0800, yu kuai wrote:
> Add a new function xfs_bmap_split_da_extent to split a delalloc extent
> into two delalloc extents.
> 
> Signed-off-by: yu kuai <yukuai3@huawei.com>
> ---
>  fs/xfs/libxfs/xfs_bmap.c | 26 ++++++++++++++++++++++++--
>  fs/xfs/libxfs/xfs_bmap.h |  1 +
>  2 files changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 4c2e046fbfad..8247054c1e2b 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -6117,7 +6117,7 @@ xfs_bmap_split_extent_at(
>  	/*
>  	 * Convert to a btree if necessary.
>  	 */
> -	if (xfs_bmap_needs_btree(ip, whichfork)) {
> +	if (tp && xfs_bmap_needs_btree(ip, whichfork)) {
>  		int tmp_logflags; /* partial log flag return val */
>  
>  		ASSERT(cur == NULL);

You can't use xfs_bmap_split_extent_at() to split delalloc extents
just by avoiding transactional context.

delalloc extents only exist in the in-core extent list, not in the
on-disk BMBT extent list. xfs_bmap_split_extent_at() is for splitting
on-disk BMBT extents and, as such, it modifies the BMBT directly. It
may not be obvious that the bmbt cursor holds a pointer to the
transaction context, but it does and that's how we log all the
modifications to the BMBT done via the generic btree code.

IOWs, if the inode extent list is in btree format, this code will
not work correctly.

Cheers,

Dave.
diff mbox series

Patch

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 4c2e046fbfad..8247054c1e2b 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -6117,7 +6117,7 @@  xfs_bmap_split_extent_at(
 	/*
 	 * Convert to a btree if necessary.
 	 */
-	if (xfs_bmap_needs_btree(ip, whichfork)) {
+	if (tp && xfs_bmap_needs_btree(ip, whichfork)) {
 		int tmp_logflags; /* partial log flag return val */
 
 		ASSERT(cur == NULL);
@@ -6132,7 +6132,7 @@  xfs_bmap_split_extent_at(
 		xfs_btree_del_cursor(cur, error);
 	}
 
-	if (logflags)
+	if (tp && logflags)
 		xfs_trans_log_inode(tp, ip, logflags);
 	return error;
 }
@@ -6165,6 +6165,28 @@  xfs_bmap_split_extent(
 	return error;
 }
 
+/*
+ * Splits a delalloc extent into two delalloc extents at split_fsb block
+ * such that it is the first block of the current_ext. Caller has to make
+ * sure split_fsb belong to a delalloc extent.
+ * If split_fsb is not the first block of the extent, caller need to sub
+ * the @ip->i_d.di_nextents to prevent crash in log recovery.
+ */
+int
+xfs_bmap_split_da_extent(
+	struct xfs_inode        *ip,
+	xfs_fileoff_t           split_fsb)
+{
+	struct xfs_trans        *tp = NULL;
+	int error;
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	error = xfs_bmap_split_extent_at(tp, ip, split_fsb);
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+	return error;
+}
+
 /* Deferred mapping is only for real extents in the data fork. */
 static bool
 xfs_bmap_is_update_needed(
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index 14d25e0b7d9c..d8d969aa17ef 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -223,6 +223,7 @@  int	xfs_bmap_insert_extents(struct xfs_trans *tp, struct xfs_inode *ip,
 		xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
 		bool *done, xfs_fileoff_t stop_fsb);
 int	xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
+int	xfs_bmap_split_da_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
 int	xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
 		xfs_fileoff_t off, xfs_filblks_t len, xfs_filblks_t prealloc,
 		struct xfs_bmbt_irec *got, struct xfs_iext_cursor *cur,