aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_fsops.c
diff options
context:
space:
mode:
authorDavid Chinner <dgc@sgi.com>2007-06-18 02:50:27 -0400
committerTim Shimmin <tes@chook.melbourne.sgi.com>2007-07-14 01:35:19 -0400
commit84e1e99f112dead8f9ba036c02d24a9f5ce7f544 (patch)
treee903589be98c05b45586908171d795a1a466357d /fs/xfs/xfs_fsops.c
parent641c56fbfeae85d5ec87fee90a752f7b7224f236 (diff)
[XFS] Prevent ENOSPC from aborting transactions that need to succeed
During delayed allocation extent conversion or unwritten extent conversion, we need to reserve some blocks for transactions reservations. We need to reserve these blocks in case a btree split occurs and we need to allocate some blocks. Unfortunately, we've only ever reserved the number of data blocks we are allocating, so in both the unwritten and delalloc case we can get ENOSPC to the transaction reservation. This is bad because in both cases we cannot report the failure to the writing application. The fix is two-fold: 1 - leverage the reserved block infrastructure XFS already has to reserve a small pool of blocks by default to allow specially marked transactions to dip into when we are at ENOSPC. Default setting is min(5%, 1024 blocks). 2 - convert critical transaction reservations to be allowed to dip into this pool. Spots changed are delalloc conversion, unwritten extent conversion and growing a filesystem at ENOSPC. This also allows growing the filesytsem to succeed at ENOSPC. SGI-PV: 964468 SGI-Modid: xfs-linux-melb:xfs-kern:28865a Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_fsops.c')
-rw-r--r--fs/xfs/xfs_fsops.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index ddd45e5b9383..2251a49f3e17 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -177,6 +177,7 @@ xfs_growfs_data_private(
177 up_write(&mp->m_peraglock); 177 up_write(&mp->m_peraglock);
178 } 178 }
179 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); 179 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
180 tp->t_flags |= XFS_TRANS_RESERVE;
180 if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp), 181 if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp),
181 XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) { 182 XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) {
182 xfs_trans_cancel(tp, 0); 183 xfs_trans_cancel(tp, 0);
@@ -499,8 +500,9 @@ xfs_reserve_blocks(
499 unsigned long s; 500 unsigned long s;
500 501
501 /* If inval is null, report current values and return */ 502 /* If inval is null, report current values and return */
502
503 if (inval == (__uint64_t *)NULL) { 503 if (inval == (__uint64_t *)NULL) {
504 if (!outval)
505 return EINVAL;
504 outval->resblks = mp->m_resblks; 506 outval->resblks = mp->m_resblks;
505 outval->resblks_avail = mp->m_resblks_avail; 507 outval->resblks_avail = mp->m_resblks_avail;
506 return 0; 508 return 0;
@@ -563,8 +565,10 @@ retry:
563 } 565 }
564 } 566 }
565out: 567out:
566 outval->resblks = mp->m_resblks; 568 if (outval) {
567 outval->resblks_avail = mp->m_resblks_avail; 569 outval->resblks = mp->m_resblks;
570 outval->resblks_avail = mp->m_resblks_avail;
571 }
568 XFS_SB_UNLOCK(mp, s); 572 XFS_SB_UNLOCK(mp, s);
569 573
570 if (fdblks_delta) { 574 if (fdblks_delta) {