diff options
author | Dave Chinner <david@fromorbit.com> | 2010-03-03 20:46:25 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-03-05 12:01:59 -0500 |
commit | 8babd8a2e75cccff3167a61176c2a3e977e13799 (patch) | |
tree | 3d438e7ed84ad1f06a1a67fbb62725c92c6ad224 /fs/xfs/xfs_mount.c | |
parent | 3ed3a4343b79a79d10e31f85f2d1afabcead76c6 (diff) |
xfs: Increase the default size of the reserved blocks pool
The current default size of the reserved blocks pool is easy to deplete
with certain workloads, in particular workloads that do lots of concurrent
delayed allocation extent conversions. If enough transactions are running
in parallel and the entire pool is consumed then subsequent calls to
xfs_trans_reserve() will fail with ENOSPC. Also add a rate limited
warning so we know if this starts happening again.
This is an updated version of an old patch from Lachlan McIlroy.
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index c207fef6770b..e79b56b4bca6 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -1097,13 +1097,15 @@ xfs_default_resblks(xfs_mount_t *mp) | |||
1097 | __uint64_t resblks; | 1097 | __uint64_t resblks; |
1098 | 1098 | ||
1099 | /* | 1099 | /* |
1100 | * We default to 5% or 1024 fsbs of space reserved, whichever is smaller. | 1100 | * We default to 5% or 8192 fsbs of space reserved, whichever is |
1101 | * This may drive us straight to ENOSPC on mount, but that implies | 1101 | * smaller. This is intended to cover concurrent allocation |
1102 | * we were already there on the last unmount. Warn if this occurs. | 1102 | * transactions when we initially hit enospc. These each require a 4 |
1103 | * block reservation. Hence by default we cover roughly 2000 concurrent | ||
1104 | * allocation reservations. | ||
1103 | */ | 1105 | */ |
1104 | resblks = mp->m_sb.sb_dblocks; | 1106 | resblks = mp->m_sb.sb_dblocks; |
1105 | do_div(resblks, 20); | 1107 | do_div(resblks, 20); |
1106 | resblks = min_t(__uint64_t, resblks, 1024); | 1108 | resblks = min_t(__uint64_t, resblks, 8192); |
1107 | return resblks; | 1109 | return resblks; |
1108 | } | 1110 | } |
1109 | 1111 | ||
@@ -1417,6 +1419,9 @@ xfs_mountfs( | |||
1417 | * when at ENOSPC. This is needed for operations like create with | 1419 | * when at ENOSPC. This is needed for operations like create with |
1418 | * attr, unwritten extent conversion at ENOSPC, etc. Data allocations | 1420 | * attr, unwritten extent conversion at ENOSPC, etc. Data allocations |
1419 | * are not allowed to use this reserved space. | 1421 | * are not allowed to use this reserved space. |
1422 | * | ||
1423 | * This may drive us straight to ENOSPC on mount, but that implies | ||
1424 | * we were already there on the last unmount. Warn if this occurs. | ||
1420 | */ | 1425 | */ |
1421 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { | 1426 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { |
1422 | resblks = xfs_default_resblks(mp); | 1427 | resblks = xfs_default_resblks(mp); |
@@ -1725,26 +1730,30 @@ xfs_mod_incore_sb_unlocked( | |||
1725 | lcounter += rem; | 1730 | lcounter += rem; |
1726 | } | 1731 | } |
1727 | } else { /* Taking blocks away */ | 1732 | } else { /* Taking blocks away */ |
1728 | |||
1729 | lcounter += delta; | 1733 | lcounter += delta; |
1734 | if (lcounter >= 0) { | ||
1735 | mp->m_sb.sb_fdblocks = lcounter + | ||
1736 | XFS_ALLOC_SET_ASIDE(mp); | ||
1737 | return 0; | ||
1738 | } | ||
1730 | 1739 | ||
1731 | /* | 1740 | /* |
1732 | * If were out of blocks, use any available reserved blocks if | 1741 | * We are out of blocks, use any available reserved |
1733 | * were allowed to. | 1742 | * blocks if were allowed to. |
1734 | */ | 1743 | */ |
1744 | if (!rsvd) | ||
1745 | return XFS_ERROR(ENOSPC); | ||
1735 | 1746 | ||
1736 | if (lcounter < 0) { | 1747 | lcounter = (long long)mp->m_resblks_avail + delta; |
1737 | if (rsvd) { | 1748 | if (lcounter >= 0) { |
1738 | lcounter = (long long)mp->m_resblks_avail + delta; | 1749 | mp->m_resblks_avail = lcounter; |
1739 | if (lcounter < 0) { | 1750 | return 0; |
1740 | return XFS_ERROR(ENOSPC); | ||
1741 | } | ||
1742 | mp->m_resblks_avail = lcounter; | ||
1743 | return 0; | ||
1744 | } else { /* not reserved */ | ||
1745 | return XFS_ERROR(ENOSPC); | ||
1746 | } | ||
1747 | } | 1751 | } |
1752 | printk_once(KERN_WARNING | ||
1753 | "Filesystem \"%s\": reserve blocks depleted! " | ||
1754 | "Consider increasing reserve pool size.", | ||
1755 | mp->m_fsname); | ||
1756 | return XFS_ERROR(ENOSPC); | ||
1748 | } | 1757 | } |
1749 | 1758 | ||
1750 | mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); | 1759 | mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); |