Skip to content

Commit

Permalink
xfs: use generic percpu counters for free block counter
Browse files Browse the repository at this point in the history
XFS has hand-rolled per-cpu counters for the superblock since before
there was any generic implementation. The free block counter is
special in that it is used for ENOSPC detection outside transaction
contexts for for delayed allocation. This means that the counter
needs to be accurate at zero. The current per-cpu counter code jumps
through lots of hoops to ensure we never run past zero, but we don't
need to make all those jumps with the generic counter
implementation.

The generic counter implementation allows us to pass a "batch"
threshold at which the addition/subtraction to the counter value
will be folded back into global value under lock. We can use this
feature to reduce the batch size as we approach 0 in a very similar
manner to the existing counters and their rebalance algorithm. If we
use a batch size of 1 as we approach 0, then every addition and
subtraction will be done against the global value and hence allow
accurate detection of zero threshold crossing.

Hence we can replace the handrolled, accurate-at-zero counters with
generic percpu counters.

Note: this removes just enough of the icsb infrastructure to compile
without warnings. The rest will go in subsequent commits.

Signed-off-by: Dave Chinner <[email protected]>
Reviewed-by: Brian Foster <[email protected]>
Signed-off-by: Dave Chinner <[email protected]>
  • Loading branch information
dchinner committed Feb 23, 2015
1 parent e88b64e commit 0d485ad
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 131 deletions.
32 changes: 13 additions & 19 deletions fs/xfs/libxfs/xfs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2212,9 +2212,8 @@ xfs_bmap_add_extent_delay_real(
diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
(bma->cur ? bma->cur->bc_private.b.allocated : 0));
if (diff > 0) {
error = xfs_icsb_modify_counters(bma->ip->i_mount,
XFS_SBS_FDBLOCKS,
-((int64_t)diff), 0);
error = xfs_mod_fdblocks(bma->ip->i_mount,
-((int64_t)diff), false);
ASSERT(!error);
if (error)
goto done;
Expand Down Expand Up @@ -2265,9 +2264,8 @@ xfs_bmap_add_extent_delay_real(
temp += bma->cur->bc_private.b.allocated;
ASSERT(temp <= da_old);
if (temp < da_old)
xfs_icsb_modify_counters(bma->ip->i_mount,
XFS_SBS_FDBLOCKS,
(int64_t)(da_old - temp), 0);
xfs_mod_fdblocks(bma->ip->i_mount,
(int64_t)(da_old - temp), false);
}

/* clear out the allocated field, done with it now in any case. */
Expand Down Expand Up @@ -2944,8 +2942,8 @@ xfs_bmap_add_extent_hole_delay(
}
if (oldlen != newlen) {
ASSERT(oldlen > newlen);
xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
(int64_t)(oldlen - newlen), 0);
xfs_mod_fdblocks(ip->i_mount, (int64_t)(oldlen - newlen),
false);
/*
* Nothing to do for disk quota accounting here.
*/
Expand Down Expand Up @@ -4163,15 +4161,13 @@ xfs_bmapi_reserve_delalloc(
error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
-((int64_t)extsz), 0);
} else {
error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-((int64_t)alen), 0);
error = xfs_mod_fdblocks(mp, -((int64_t)alen), false);
}

if (error)
goto out_unreserve_quota;

error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-((int64_t)indlen), 0);
error = xfs_mod_fdblocks(mp, -((int64_t)indlen), false);
if (error)
goto out_unreserve_blocks;

Expand Down Expand Up @@ -4200,7 +4196,7 @@ xfs_bmapi_reserve_delalloc(
if (rt)
xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0);
else
xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0);
xfs_mod_fdblocks(mp, alen, false);
out_unreserve_quota:
if (XFS_IS_QUOTA_ON(mp))
xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ?
Expand Down Expand Up @@ -5012,10 +5008,8 @@ xfs_bmap_del_extent(
* Nothing to do for disk quota accounting here.
*/
ASSERT(da_old >= da_new);
if (da_old > da_new) {
xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
(int64_t)(da_old - da_new), 0);
}
if (da_old > da_new)
xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false);
done:
*logflagsp = flags;
return error;
Expand Down Expand Up @@ -5290,8 +5284,8 @@ xfs_bunmapi(
ip, -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_RTBLKS);
} else {
xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
(int64_t)del.br_blockcount, 0);
xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount,
false);
(void)xfs_trans_reserve_quota_nblks(NULL,
ip, -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_REGBLKS);
Expand Down
1 change: 1 addition & 0 deletions fs/xfs/libxfs/xfs_sb.c
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@ xfs_log_sb(

mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks);

xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
Expand Down
9 changes: 5 additions & 4 deletions fs/xfs/xfs_fsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -640,9 +640,10 @@ xfs_fs_counts(
xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
cnt->allocino = percpu_counter_read_positive(&mp->m_icount);
cnt->freeino = percpu_counter_read_positive(&mp->m_ifree);
cnt->freedata = percpu_counter_read_positive(&mp->m_fdblocks) -
XFS_ALLOC_SET_ASIDE(mp);

spin_lock(&mp->m_sb_lock);
cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
cnt->freertx = mp->m_sb.sb_frextents;
spin_unlock(&mp->m_sb_lock);
return 0;
Expand Down Expand Up @@ -717,7 +718,8 @@ xfs_reserve_blocks(
} else {
__int64_t free;

free = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
free = percpu_counter_sum(&mp->m_fdblocks) -
XFS_ALLOC_SET_ASIDE(mp);
if (!free)
goto out; /* ENOSPC and fdblks_delta = 0 */

Expand Down Expand Up @@ -756,8 +758,7 @@ xfs_reserve_blocks(
* the extra reserve blocks from the reserve.....
*/
int error;
error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
fdblks_delta, 0);
error = xfs_mod_fdblocks(mp, fdblks_delta, 0);
if (error == -ENOSPC)
goto retry;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_iomap.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ xfs_iomap_prealloc_size(
alloc_blocks);

xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
freesp = mp->m_sb.sb_fdblocks;
freesp = percpu_counter_read_positive(&mp->m_fdblocks);
if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
shift = 2;
if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT])
Expand Down
Loading

0 comments on commit 0d485ad

Please sign in to comment.