xfs
[Top] [All Lists]

[PATCH] xfs: prevent 32bit overflow in space reservation

To: xfs@xxxxxxxxxxx
Subject: [PATCH] xfs: prevent 32bit overflow in space reservation
From: Dave Chinner <david@xxxxxxxxxxxxx>
Date: Thu, 2 Sep 2010 15:17:43 +1000
From: Dave Chinner <dchinner@xxxxxxxxxx>

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@xxxxxxxxxx>
---
 fs/xfs/xfs_vnodeops.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 66d585c..91dd9c8 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -2299,15 +2299,21 @@ xfs_alloc_file_space(
                        e = allocatesize_fsb;
                }
 
+               /*
+                * we can't allocate more than @nimaps extents at a time,
+                * so prevent a 32bit overflow on the transaction reserve
+                * by trying to reserve > 16TB worth of blocks for the
+                * preallocation.
+                */
+               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;
                }
 
-- 
1.7.1

<Prev in Thread] Current Thread [Next in Thread>