aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c73
1 files changed, 54 insertions, 19 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index b48abc300c36..6de613b558a9 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -4721,6 +4721,47 @@ error0:
4721} 4721}
4722 4722
4723/* 4723/*
4724 * When a delalloc extent is split (e.g., due to a hole punch), the original
4725 * indlen reservation must be shared across the two new extents that are left
4726 * behind.
4727 *
4728 * Given the original reservation and the worst case indlen for the two new
4729 * extents (as calculated by xfs_bmap_worst_indlen()), split the original
4730 * reservation fairly across the two new extents.
4731 */
4732static void
4733xfs_bmap_split_indlen(
4734 xfs_filblks_t ores, /* original res. */
4735 xfs_filblks_t *indlen1, /* ext1 worst indlen */
4736 xfs_filblks_t *indlen2) /* ext2 worst indlen */
4737{
4738 xfs_filblks_t len1 = *indlen1;
4739 xfs_filblks_t len2 = *indlen2;
4740 xfs_filblks_t nres = len1 + len2; /* new total res. */
4741
4742 /*
4743 * The only blocks available are those reserved for the original extent.
4744 * Therefore, we have to skim blocks off each of the new reservations so
4745 * long as the new total reservation is greater than the original.
4746 */
4747 while (nres > ores) {
4748 if (len1) {
4749 len1--;
4750 nres--;
4751 }
4752 if (nres == ores)
4753 break;
4754 if (len2) {
4755 len2--;
4756 nres--;
4757 }
4758 }
4759
4760 *indlen1 = len1;
4761 *indlen2 = len2;
4762}
4763
4764/*
4724 * Called by xfs_bmapi to update file extent records and the btree 4765 * Called by xfs_bmapi to update file extent records and the btree
4725 * after removing space (or undoing a delayed allocation). 4766 * after removing space (or undoing a delayed allocation).
4726 */ 4767 */
@@ -4985,27 +5026,21 @@ xfs_bmap_del_extent(
4985 XFS_IFORK_NEXTENTS(ip, whichfork) + 1); 5026 XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
4986 } else { 5027 } else {
4987 ASSERT(whichfork == XFS_DATA_FORK); 5028 ASSERT(whichfork == XFS_DATA_FORK);
4988 temp = xfs_bmap_worst_indlen(ip, temp); 5029
5030 /*
5031 * Distribute the original indlen reservation across the
5032 * two new extents.
5033 */
5034 temp = xfs_bmap_worst_indlen(ip, got.br_blockcount);
5035 temp2 = xfs_bmap_worst_indlen(ip, new.br_blockcount);
5036 xfs_bmap_split_indlen(da_old, &temp, &temp2);
5037 da_new = temp + temp2;
5038
5039 /*
5040 * Set the reservation for each extent.
5041 */
4989 xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); 5042 xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
4990 temp2 = xfs_bmap_worst_indlen(ip, temp2);
4991 new.br_startblock = nullstartblock((int)temp2); 5043 new.br_startblock = nullstartblock((int)temp2);
4992 da_new = temp + temp2;
4993 while (da_new > da_old) {
4994 if (temp) {
4995 temp--;
4996 da_new--;
4997 xfs_bmbt_set_startblock(ep,
4998 nullstartblock((int)temp));
4999 }
5000 if (da_new == da_old)
5001 break;
5002 if (temp2) {
5003 temp2--;
5004 da_new--;
5005 new.br_startblock =
5006 nullstartblock((int)temp2);
5007 }
5008 }
5009 } 5044 }
5010 trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); 5045 trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
5011 xfs_iext_insert(ip, *idx + 1, 1, &new, state); 5046 xfs_iext_insert(ip, *idx + 1, 1, &new, state);