xfs: Check for extent overflow when punching a hole
authorChandan Babu R <chandanrlinux@gmail.com>
Sat, 23 Jan 2021 00:48:11 +0000 (16:48 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Sat, 23 Jan 2021 00:54:47 +0000 (16:54 -0800)
The extent mapping the file offset at which a hole has to be
inserted will be split into two extents causing extent count to
increase by 1.

Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Signed-off-by: Chandan Babu R <chandanrlinux@gmail.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/libxfs/xfs_inode_fork.h
fs/xfs/xfs_bmap_item.c
fs/xfs/xfs_bmap_util.c

index 7fc2b129a2e79ff998acc4c0ced441cf8d18e205..bcac769a7df6fddf9baca65f294cbfb2388c448c 100644 (file)
@@ -40,6 +40,13 @@ struct xfs_ifork {
  */
 #define XFS_IEXT_ADD_NOSPLIT_CNT       (1)
 
+/*
+ * Punching out an extent from the middle of an existing extent can cause the
+ * extent count to increase by 1.
+ * i.e. | Old extent | Hole | Old extent |
+ */
+#define XFS_IEXT_PUNCH_HOLE_CNT                (1)
+
 /*
  * Fork handling.
  */
index 0534304ed0a7dc9c0ce66b6fbf04df46fa49f69e..2344757ede63c0dfa5ce1d15d11bd380d8d2ce8e 100644 (file)
@@ -471,6 +471,7 @@ xfs_bui_item_recover(
        xfs_exntst_t                    state;
        unsigned int                    bui_type;
        int                             whichfork;
+       int                             iext_delta;
        int                             error = 0;
 
        if (!xfs_bui_validate(mp, buip)) {
@@ -508,12 +509,14 @@ xfs_bui_item_recover(
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, 0);
 
-       if (bui_type == XFS_BMAP_MAP) {
-               error = xfs_iext_count_may_overflow(ip, whichfork,
-                               XFS_IEXT_ADD_NOSPLIT_CNT);
-               if (error)
-                       goto err_cancel;
-       }
+       if (bui_type == XFS_BMAP_MAP)
+               iext_delta = XFS_IEXT_ADD_NOSPLIT_CNT;
+       else
+               iext_delta = XFS_IEXT_PUNCH_HOLE_CNT;
+
+       error = xfs_iext_count_may_overflow(ip, whichfork, iext_delta);
+       if (error)
+               goto err_cancel;
 
        count = bmap->me_len;
        error = xfs_trans_log_finish_bmap_update(tp, budp, bui_type, ip,
index db44bfaabe8812d3c0a53526a13a533acf177809..6ac7a6ac26581afdf3eef9c665aba245af4acd6d 100644 (file)
@@ -891,6 +891,11 @@ xfs_unmap_extent(
 
        xfs_trans_ijoin(tp, ip, 0);
 
+       error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
+                       XFS_IEXT_PUNCH_HOLE_CNT);
+       if (error)
+               goto out_trans_cancel;
+
        error = xfs_bunmapi(tp, ip, startoffset_fsb, len_fsb, 0, 2, done);
        if (error)
                goto out_trans_cancel;
@@ -1168,6 +1173,11 @@ xfs_insert_file_space(
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, 0);
 
+       error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK,
+                       XFS_IEXT_PUNCH_HOLE_CNT);
+       if (error)
+               goto out_trans_cancel;
+
        /*
         * The extent shifting code works on extent granularity. So, if stop_fsb
         * is not the starting block of extent, we need to split the extent at