diff options
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 26 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.h | 2 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_format.h | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_bmap_util.c | 4 |
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. */ | ||
| 5784 | int | ||
| 5785 | xfs_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 | |||
| 5783 | int | 5809 | int |
| 5784 | xfs_bmap_insert_extents( | 5810 | xfs_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); |
| 230 | int xfs_bmap_can_insert_extents(struct xfs_inode *ip, xfs_fileoff_t off, | ||
| 231 | xfs_fileoff_t shift); | ||
| 230 | int xfs_bmap_insert_extents(struct xfs_trans *tp, struct xfs_inode *ip, | 232 | int 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 | |||
| 1532 | typedef struct xfs_bmbt_rec { | 1534 | typedef 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; |
