aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c26
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h2
-rw-r--r--fs/xfs/libxfs/xfs_format.h2
-rw-r--r--fs/xfs/xfs_bmap_util.c4
4 files changed, 34 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 01628f0c9a0c..7205268b30bc 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -5780,6 +5780,32 @@ del_cursor:
5780 return error; 5780 return error;
5781} 5781}
5782 5782
5783/* Make sure we won't be right-shifting an extent past the maximum bound. */
5784int
5785xfs_bmap_can_insert_extents(
5786 struct xfs_inode *ip,
5787 xfs_fileoff_t off,
5788 xfs_fileoff_t shift)
5789{
5790 struct xfs_bmbt_irec got;
5791 int is_empty;
5792 int error = 0;
5793
5794 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
5795
5796 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
5797 return -EIO;
5798
5799 xfs_ilock(ip, XFS_ILOCK_EXCL);
5800 error = xfs_bmap_last_extent(NULL, ip, XFS_DATA_FORK, &got, &is_empty);
5801 if (!error && !is_empty && got.br_startoff >= off &&
5802 ((got.br_startoff + shift) & BMBT_STARTOFF_MASK) < got.br_startoff)
5803 error = -EINVAL;
5804 xfs_iunlock(ip, XFS_ILOCK_EXCL);
5805
5806 return error;
5807}
5808
5783int 5809int
5784xfs_bmap_insert_extents( 5810xfs_bmap_insert_extents(
5785 struct xfs_trans *tp, 5811 struct xfs_trans *tp,
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index 99dddbd0fcc6..9b49ddf99c41 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -227,6 +227,8 @@ int xfs_bmap_collapse_extents(struct xfs_trans *tp, struct xfs_inode *ip,
227 xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, 227 xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
228 bool *done, xfs_fsblock_t *firstblock, 228 bool *done, xfs_fsblock_t *firstblock,
229 struct xfs_defer_ops *dfops); 229 struct xfs_defer_ops *dfops);
230int xfs_bmap_can_insert_extents(struct xfs_inode *ip, xfs_fileoff_t off,
231 xfs_fileoff_t shift);
230int xfs_bmap_insert_extents(struct xfs_trans *tp, struct xfs_inode *ip, 232int xfs_bmap_insert_extents(struct xfs_trans *tp, struct xfs_inode *ip,
231 xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, 233 xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
232 bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, 234 bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 7b4a43deb83e..059bc44c27e8 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1529,6 +1529,8 @@ typedef struct xfs_bmdr_block {
1529#define BMBT_STARTBLOCK_BITLEN 52 1529#define BMBT_STARTBLOCK_BITLEN 52
1530#define BMBT_BLOCKCOUNT_BITLEN 21 1530#define BMBT_BLOCKCOUNT_BITLEN 21
1531 1531
1532#define BMBT_STARTOFF_MASK ((1ULL << BMBT_STARTOFF_BITLEN) - 1)
1533
1532typedef struct xfs_bmbt_rec { 1534typedef struct xfs_bmbt_rec {
1533 __be64 l0, l1; 1535 __be64 l0, l1;
1534} xfs_bmbt_rec_t; 1536} xfs_bmbt_rec_t;
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index c195b9d857af..bb417156e3bf 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1383,6 +1383,10 @@ xfs_insert_file_space(
1383 1383
1384 trace_xfs_insert_file_space(ip); 1384 trace_xfs_insert_file_space(ip);
1385 1385
1386 error = xfs_bmap_can_insert_extents(ip, stop_fsb, shift_fsb);
1387 if (error)
1388 return error;
1389
1386 error = xfs_prepare_shift(ip, offset); 1390 error = xfs_prepare_shift(ip, offset);
1387 if (error) 1391 if (error)
1388 return error; 1392 return error;