xfs: prevent 32bit overflow in space reservation
If we attempt to preallocate more than 2^32 blocks of space in a single syscall, the transaction block reservation will overflow leading to a hangs in the superblock block accounting code. This is trivially reproduced with xfs_io. Fix the problem by capping the allocation reservation to the maximum number of blocks a single xfs_bmapi() call can allocate (2^21 blocks). Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
9bc08a45fb
commit
72656c46f5
|
@ -2299,15 +2299,22 @@ xfs_alloc_file_space(
|
|||
e = allocatesize_fsb;
|
||||
}
|
||||
|
||||
/*
|
||||
* The transaction reservation is limited to a 32-bit block
|
||||
* count, hence we need to limit the number of blocks we are
|
||||
* trying to reserve to avoid an overflow. We can't allocate
|
||||
* more than @nimaps extents, and an extent is limited on disk
|
||||
* to MAXEXTLEN (21 bits), so use that to enforce the limit.
|
||||
*/
|
||||
resblks = min_t(xfs_fileoff_t, (e - s), (MAXEXTLEN * nimaps));
|
||||
if (unlikely(rt)) {
|
||||
resrtextents = qblocks = (uint)(e - s);
|
||||
resrtextents = qblocks = resblks;
|
||||
resrtextents /= mp->m_sb.sb_rextsize;
|
||||
resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
|
||||
quota_flag = XFS_QMOPT_RES_RTBLKS;
|
||||
} else {
|
||||
resrtextents = 0;
|
||||
resblks = qblocks = \
|
||||
XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
|
||||
resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
|
||||
quota_flag = XFS_QMOPT_RES_REGBLKS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue