Message ID | 20191226134721.43797-2-yukuai3@huawei.com (mailing list archive) |
---|---|
State | Deferred, archived |
Headers | show |
Series | fix stale data exposure problem | expand |
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 --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,
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(-)