All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7 V2] xfs: use generic percpu counters for icsb
@ 2015-02-04 20:54 Dave Chinner
  2015-02-04 20:54 ` [PATCH 1/7] xfs: use generic percpu counters for inode counter Dave Chinner
                   ` (7 more replies)
  0 siblings, 8 replies; 25+ messages in thread
From: Dave Chinner @ 2015-02-04 20:54 UTC (permalink / raw)
  To: xfs

Hi folks,

This is the second version of the generic per-cpu counter rework
patch series. The first version can be found here:

http://oss.sgi.com/archives/xfs/2015-02/msg00000.html

New in V2:

- drop the moving of the struct xfs_sb to xfs_super.h
- fixed all the little things that Christoph and Brian noted.
- keep the per-cpu counters in the struct xfs_mount and keep the
  functions to sync them with the struct xfs_sb values when read
  from disk or written to disk.
- integrated Christoph Hellwig's additional cleanup patch. This was
  done by:
	- intergating xfs_mod_XXX factoring into the relevant percpu
	  counter conversion patch
	- separating out xfs_mod_frextents into it's won patch
	- separating out the replacement of
	  xfs_mod_incore_sb_batched
	- doing all the now unused API removal in a separate patch

The series passes xfstests without regressions, and no scalability
issues have been seen in my performance tests on a 16p VM. SGI - you
still need to test this, though. :)

Thoughts, comments?

-Dave.

PS: diffstat of the series is now:

 fs/xfs/libxfs/xfs_bmap.c   |  40 +--
 fs/xfs/libxfs/xfs_format.h |  62 ----
 fs/xfs/libxfs/xfs_ialloc.c |   6 +-
 fs/xfs/libxfs/xfs_sb.c     |  12 +-
 fs/xfs/xfs_fsops.c         |  20 +-
 fs/xfs/xfs_iomap.c         |   3 +-
 fs/xfs/xfs_linux.h         |   9 -
 fs/xfs/xfs_log_recover.c   |   4 +-
 fs/xfs/xfs_mount.c         | 919 ++++++-----------------------------------------
 fs/xfs/xfs_mount.h         |  95 +----
 fs/xfs/xfs_super.c         | 103 ++++--
 fs/xfs/xfs_super.h         |   2 +
 fs/xfs/xfs_trans.c         | 234 +++++++-----
 13 files changed, 381 insertions(+), 1128 deletions(-)

So we have a net reduction of roughly 750 lines of code.  When
combined with the changes to the superblock logging that has already
been committed, we have reduced the superblock modification code by
close to 1000 lines compared to 3.19...

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/7] xfs: use generic percpu counters for inode counter
  2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
@ 2015-02-04 20:54 ` Dave Chinner
  2015-02-05 14:09   ` Brian Foster
  2015-02-23 20:55   ` Christoph Hellwig
  2015-02-04 20:54 ` [PATCH 2/7] xfs: use generic percpu counters for free " Dave Chinner
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Dave Chinner @ 2015-02-04 20:54 UTC (permalink / raw)
  To: xfs

XFS has hand-rolled per-cpu counters for the superblock since before
there was any generic implementation. There are some warts around
the  use of them for the inode counter as the hand rolled counter is
designed to be accurate at zero, but has no specific accurracy at
any other value. This design causes problems for the maximum inode
count threshold enforcement, as there is no trigger that balances
the counters as they get close tothe maximum threshold.

Instead of designing new triggers for balancing, just replace the
handrolled per-cpu counter with a generic counter.  This enables us
to update the counter through the normal superblock modification
funtions, but rather than do that we add a xfs_mod_icount() helper
function (from Christoph Hellwig) and keep the percpu counter
outside the superblock in the struct xfs_mount.

This means we still need to initialise the per-cpu counter
specifically when we read the superblock, and vice versa when we
log/write it, but it does mean that we don't need to change any
other code.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 fs/xfs/libxfs/xfs_ialloc.c |  6 ++--
 fs/xfs/libxfs/xfs_sb.c     |  2 ++
 fs/xfs/xfs_fsops.c         |  3 +-
 fs/xfs/xfs_mount.c         | 76 +++++++++++++++++++++-------------------------
 fs/xfs/xfs_mount.h         |  7 +++--
 fs/xfs/xfs_super.c         |  7 +++--
 fs/xfs/xfs_trans.c         |  5 ++-
 7 files changed, 54 insertions(+), 52 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 116ef1d..5b4ba9f 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -376,7 +376,8 @@ xfs_ialloc_ag_alloc(
 	 */
 	newlen = args.mp->m_ialloc_inos;
 	if (args.mp->m_maxicount &&
-	    args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount)
+	    percpu_counter_read(&args.mp->m_icount) + newlen >
+							args.mp->m_maxicount)
 		return -ENOSPC;
 	args.minlen = args.maxlen = args.mp->m_ialloc_blks;
 	/*
@@ -1340,7 +1341,8 @@ xfs_dialloc(
 	 * inode.
 	 */
 	if (mp->m_maxicount &&
-	    mp->m_sb.sb_icount + mp->m_ialloc_inos > mp->m_maxicount) {
+	    percpu_counter_read(&mp->m_icount) + mp->m_ialloc_inos >
+							mp->m_maxicount) {
 		noroom = 1;
 		okalloc = 0;
 	}
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index b0a5fe9..017cb2f 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -771,6 +771,8 @@ xfs_log_sb(
 	struct xfs_mount	*mp = tp->t_mountp;
 	struct xfs_buf		*bp = xfs_trans_getsb(tp, mp, 0);
 
+	mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
+
 	xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);
 	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
 	xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb));
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index f711452..e1470f2 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -631,11 +631,12 @@ xfs_fs_counts(
 	xfs_fsop_counts_t	*cnt)
 {
 	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
+	cnt->allocino = percpu_counter_read_positive(&mp->m_icount);
+
 	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;
 	cnt->freeino = mp->m_sb.sb_ifree;
-	cnt->allocino = mp->m_sb.sb_icount;
 	spin_unlock(&mp->m_sb_lock);
 	return 0;
 }
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 4fa80e6..702ea6a 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1099,6 +1099,21 @@ xfs_log_sbcount(xfs_mount_t *mp)
 	return xfs_sync_sb(mp, true);
 }
 
+int
+xfs_mod_icount(
+	struct xfs_mount	*mp,
+	int64_t			delta)
+{
+	/* deltas are +/-64, hence the large batch size of 128. */
+	__percpu_counter_add(&mp->m_icount, delta, 128);
+	if (percpu_counter_compare(&mp->m_icount, 0) < 0) {
+		ASSERT(0);
+		percpu_counter_add(&mp->m_icount, -delta);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 /*
  * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
  * a delta to a specified field in the in-core superblock.  Simply
@@ -1127,14 +1142,8 @@ xfs_mod_incore_sb_unlocked(
 	 */
 	switch (field) {
 	case XFS_SBS_ICOUNT:
-		lcounter = (long long)mp->m_sb.sb_icount;
-		lcounter += delta;
-		if (lcounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_icount = lcounter;
-		return 0;
+		ASSERT(0);
+		return -ENOSPC;
 	case XFS_SBS_IFREE:
 		lcounter = (long long)mp->m_sb.sb_ifree;
 		lcounter += delta;
@@ -1288,8 +1297,9 @@ xfs_mod_incore_sb(
 	int			status;
 
 #ifdef HAVE_PERCPU_SB
-	ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS);
+	ASSERT(field < XFS_SBS_IFREE || field > XFS_SBS_FDBLOCKS);
 #endif
+
 	spin_lock(&mp->m_sb_lock);
 	status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
 	spin_unlock(&mp->m_sb_lock);
@@ -1492,7 +1502,6 @@ xfs_icsb_cpu_notify(
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
 		xfs_icsb_lock(mp);
-		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
 		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
 		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
 		xfs_icsb_unlock(mp);
@@ -1504,17 +1513,14 @@ xfs_icsb_cpu_notify(
 		 * re-enable the counters. */
 		xfs_icsb_lock(mp);
 		spin_lock(&mp->m_sb_lock);
-		xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
 		xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
 		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
 
-		mp->m_sb.sb_icount += cntp->icsb_icount;
 		mp->m_sb.sb_ifree += cntp->icsb_ifree;
 		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
 
 		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
 
-		xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
 		xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
 		xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
 		spin_unlock(&mp->m_sb_lock);
@@ -1531,11 +1537,18 @@ xfs_icsb_init_counters(
 	xfs_mount_t	*mp)
 {
 	xfs_icsb_cnts_t *cntp;
+	int		error;
 	int		i;
 
+	error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
+	if (error)
+		return error;
+
 	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
-	if (mp->m_sb_cnts == NULL)
+	if (!mp->m_sb_cnts) {
+		percpu_counter_destroy(&mp->m_icount);
 		return -ENOMEM;
+	}
 
 	for_each_online_cpu(i) {
 		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
@@ -1563,13 +1576,14 @@ void
 xfs_icsb_reinit_counters(
 	xfs_mount_t	*mp)
 {
+	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
+
 	xfs_icsb_lock(mp);
 	/*
 	 * start with all counters disabled so that the
 	 * initial balance kicks us off correctly
 	 */
 	mp->m_icsb_counters = -1;
-	xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
 	xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
 	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
 	xfs_icsb_unlock(mp);
@@ -1583,6 +1597,9 @@ xfs_icsb_destroy_counters(
 		unregister_hotcpu_notifier(&mp->m_icsb_notifier);
 		free_percpu(mp->m_sb_cnts);
 	}
+
+	percpu_counter_destroy(&mp->m_icount);
+
 	mutex_destroy(&mp->m_icsb_mutex);
 }
 
@@ -1645,7 +1662,6 @@ xfs_icsb_count(
 
 	for_each_online_cpu(i) {
 		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-		cnt->icsb_icount += cntp->icsb_icount;
 		cnt->icsb_ifree += cntp->icsb_ifree;
 		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
 	}
@@ -1659,7 +1675,7 @@ xfs_icsb_counter_disabled(
 	xfs_mount_t	*mp,
 	xfs_sb_field_t	field)
 {
-	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
+	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
 	return test_bit(field, &mp->m_icsb_counters);
 }
 
@@ -1670,7 +1686,7 @@ xfs_icsb_disable_counter(
 {
 	xfs_icsb_cnts_t	cnt;
 
-	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
+	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
 
 	/*
 	 * If we are already disabled, then there is nothing to do
@@ -1689,9 +1705,6 @@ xfs_icsb_disable_counter(
 
 		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
 		switch(field) {
-		case XFS_SBS_ICOUNT:
-			mp->m_sb.sb_icount = cnt.icsb_icount;
-			break;
 		case XFS_SBS_IFREE:
 			mp->m_sb.sb_ifree = cnt.icsb_ifree;
 			break;
@@ -1716,15 +1729,12 @@ xfs_icsb_enable_counter(
 	xfs_icsb_cnts_t	*cntp;
 	int		i;
 
-	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
+	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
 
 	xfs_icsb_lock_all_counters(mp);
 	for_each_online_cpu(i) {
 		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
 		switch (field) {
-		case XFS_SBS_ICOUNT:
-			cntp->icsb_icount = count + resid;
-			break;
 		case XFS_SBS_IFREE:
 			cntp->icsb_ifree = count + resid;
 			break;
@@ -1750,8 +1760,6 @@ xfs_icsb_sync_counters_locked(
 
 	xfs_icsb_count(mp, &cnt, flags);
 
-	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
-		mp->m_sb.sb_icount = cnt.icsb_icount;
 	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
 		mp->m_sb.sb_ifree = cnt.icsb_ifree;
 	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
@@ -1805,12 +1813,6 @@ xfs_icsb_balance_counter_locked(
 
 	/* update counters  - first CPU gets residual*/
 	switch (field) {
-	case XFS_SBS_ICOUNT:
-		count = mp->m_sb.sb_icount;
-		resid = do_div(count, weight);
-		if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
-			return;
-		break;
 	case XFS_SBS_IFREE:
 		count = mp->m_sb.sb_ifree;
 		resid = do_div(count, weight);
@@ -1871,14 +1873,6 @@ again:
 	}
 
 	switch (field) {
-	case XFS_SBS_ICOUNT:
-		lcounter = icsbp->icsb_icount;
-		lcounter += delta;
-		if (unlikely(lcounter < 0))
-			goto balance_counter;
-		icsbp->icsb_icount = lcounter;
-		break;
-
 	case XFS_SBS_IFREE:
 		lcounter = icsbp->icsb_ifree;
 		lcounter += delta;
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index a5b2ff8..457c6e3 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -41,7 +41,6 @@ struct xfs_da_geometry;
 typedef struct xfs_icsb_cnts {
 	uint64_t	icsb_fdblocks;
 	uint64_t	icsb_ifree;
-	uint64_t	icsb_icount;
 	unsigned long	icsb_flags;
 } xfs_icsb_cnts_t;
 
@@ -81,8 +80,11 @@ typedef struct xfs_mount {
 	struct super_block	*m_super;
 	xfs_tid_t		m_tid;		/* next unused tid for fs */
 	struct xfs_ail		*m_ail;		/* fs active log item list */
-	xfs_sb_t		m_sb;		/* copy of fs superblock */
+
+	struct xfs_sb		m_sb;		/* copy of fs superblock */
 	spinlock_t		m_sb_lock;	/* sb counter lock */
+	struct percpu_counter	m_icount;	/* allocated inodes counter */
+
 	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
 	char			*m_fsname;	/* filesystem name */
 	int			m_fsname_len;	/* strlen of fs name */
@@ -377,6 +379,7 @@ extern void	xfs_unmountfs(xfs_mount_t *);
 extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
 extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
 			uint, int);
+extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mount_log_sb(xfs_mount_t *);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern int	xfs_readsb(xfs_mount_t *, int);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 40d2ac5..87e169f 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1087,6 +1087,7 @@ xfs_fs_statfs(
 	xfs_sb_t		*sbp = &mp->m_sb;
 	struct xfs_inode	*ip = XFS_I(dentry->d_inode);
 	__uint64_t		fakeinos, id;
+	__uint64_t		icount;
 	xfs_extlen_t		lsize;
 	__int64_t		ffree;
 
@@ -1098,6 +1099,7 @@ xfs_fs_statfs(
 	statp->f_fsid.val[1] = (u32)(id >> 32);
 
 	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
+	icount = percpu_counter_sum(&mp->m_icount);
 
 	spin_lock(&mp->m_sb_lock);
 	statp->f_bsize = sbp->sb_blocksize;
@@ -1106,15 +1108,14 @@ xfs_fs_statfs(
 	statp->f_bfree = statp->f_bavail =
 				sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
 	fakeinos = statp->f_bfree << sbp->sb_inopblog;
-	statp->f_files =
-	    MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
+	statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
 	if (mp->m_maxicount)
 		statp->f_files = min_t(typeof(statp->f_files),
 					statp->f_files,
 					mp->m_maxicount);
 
 	/* make sure statp->f_ffree does not underflow */
-	ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
+	ffree = statp->f_files - (icount - sbp->sb_ifree);
 	statp->f_ffree = max_t(__int64_t, ffree, 0);
 
 	spin_unlock(&mp->m_sb_lock);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index eb90cd5..9bc742b 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -554,8 +554,7 @@ xfs_trans_unreserve_and_mod_sb(
 	}
 
 	if (idelta) {
-		error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT,
-						 idelta, rsvd);
+		error = xfs_mod_icount(mp, idelta);
 		if (error)
 			goto out_undo_fdblocks;
 	}
@@ -634,7 +633,7 @@ out_undo_ifreecount:
 		xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
 out_undo_icount:
 	if (idelta)
-		xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd);
+		xfs_mod_icount(mp, -idelta);
 out_undo_fdblocks:
 	if (blkdelta)
 		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
-- 
2.0.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 2/7] xfs: use generic percpu counters for free inode counter
  2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
  2015-02-04 20:54 ` [PATCH 1/7] xfs: use generic percpu counters for inode counter Dave Chinner
@ 2015-02-04 20:54 ` Dave Chinner
  2015-02-05 14:10   ` Brian Foster
  2015-02-23 20:56   ` Christoph Hellwig
  2015-02-04 20:54 ` [PATCH 3/7] xfs: use generic percpu counters for free block counter Dave Chinner
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Dave Chinner @ 2015-02-04 20:54 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

XFS has hand-rolled per-cpu counters for the superblock since before
there was any generic implementation. The free inode counter is not
used for any limit enforcement - the per-AG free inode counters are
used during allocation to determine if there are inode available for
allocation.

Hence we don't need any of the complexity of the hand-rolled
counters and we can simply replace them with generic per-cpu
counters similar to the inode counter.

This version introduces a xfs_mod_ifree() helper function from
Christoph Hellwig.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 fs/xfs/libxfs/xfs_sb.c |  1 +
 fs/xfs/xfs_fsops.c     |  2 +-
 fs/xfs/xfs_mount.c     | 76 ++++++++++++++++++++++----------------------------
 fs/xfs/xfs_mount.h     |  2 ++
 fs/xfs/xfs_super.c     |  4 ++-
 fs/xfs/xfs_trans.c     |  5 ++--
 6 files changed, 42 insertions(+), 48 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 017cb2f..b66aeab 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -772,6 +772,7 @@ xfs_log_sb(
 	struct xfs_buf		*bp = xfs_trans_getsb(tp, mp, 0);
 
 	mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
+	mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
 
 	xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);
 	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index e1470f2..fa74d03 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -632,11 +632,11 @@ 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);
 
 	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;
-	cnt->freeino = mp->m_sb.sb_ifree;
 	spin_unlock(&mp->m_sb_lock);
 	return 0;
 }
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 702ea6a..650e8f1 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1114,6 +1114,20 @@ xfs_mod_icount(
 	return 0;
 }
 
+
+int
+xfs_mod_ifree(
+	struct xfs_mount	*mp,
+	int64_t			delta)
+{
+	percpu_counter_add(&mp->m_ifree, delta);
+	if (percpu_counter_compare(&mp->m_ifree, 0) < 0) {
+		ASSERT(0);
+		percpu_counter_add(&mp->m_ifree, -delta);
+		return -EINVAL;
+	}
+	return 0;
+}
 /*
  * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
  * a delta to a specified field in the in-core superblock.  Simply
@@ -1142,17 +1156,9 @@ xfs_mod_incore_sb_unlocked(
 	 */
 	switch (field) {
 	case XFS_SBS_ICOUNT:
-		ASSERT(0);
-		return -ENOSPC;
 	case XFS_SBS_IFREE:
-		lcounter = (long long)mp->m_sb.sb_ifree;
-		lcounter += delta;
-		if (lcounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_ifree = lcounter;
-		return 0;
+		ASSERT(0);
+		return -EINVAL;
 	case XFS_SBS_FDBLOCKS:
 		lcounter = (long long)
 			mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
@@ -1502,7 +1508,6 @@ xfs_icsb_cpu_notify(
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
 		xfs_icsb_lock(mp);
-		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
 		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
 		xfs_icsb_unlock(mp);
 		break;
@@ -1513,15 +1518,12 @@ xfs_icsb_cpu_notify(
 		 * re-enable the counters. */
 		xfs_icsb_lock(mp);
 		spin_lock(&mp->m_sb_lock);
-		xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
 		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
 
-		mp->m_sb.sb_ifree += cntp->icsb_ifree;
 		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
 
 		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
 
-		xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
 		xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
 		spin_unlock(&mp->m_sb_lock);
 		xfs_icsb_unlock(mp);
@@ -1544,10 +1546,14 @@ xfs_icsb_init_counters(
 	if (error)
 		return error;
 
+	error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
+	if (error)
+		goto free_icount;
+
 	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
 	if (!mp->m_sb_cnts) {
-		percpu_counter_destroy(&mp->m_icount);
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto free_ifree;
 	}
 
 	for_each_online_cpu(i) {
@@ -1570,6 +1576,12 @@ xfs_icsb_init_counters(
 #endif /* CONFIG_HOTPLUG_CPU */
 
 	return 0;
+
+free_ifree:
+	percpu_counter_destroy(&mp->m_ifree);
+free_icount:
+	percpu_counter_destroy(&mp->m_icount);
+	return error;
 }
 
 void
@@ -1577,6 +1589,7 @@ xfs_icsb_reinit_counters(
 	xfs_mount_t	*mp)
 {
 	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
+	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
 
 	xfs_icsb_lock(mp);
 	/*
@@ -1584,7 +1597,6 @@ xfs_icsb_reinit_counters(
 	 * initial balance kicks us off correctly
 	 */
 	mp->m_icsb_counters = -1;
-	xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
 	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
 	xfs_icsb_unlock(mp);
 }
@@ -1599,6 +1611,7 @@ xfs_icsb_destroy_counters(
 	}
 
 	percpu_counter_destroy(&mp->m_icount);
+	percpu_counter_destroy(&mp->m_ifree);
 
 	mutex_destroy(&mp->m_icsb_mutex);
 }
@@ -1662,7 +1675,6 @@ xfs_icsb_count(
 
 	for_each_online_cpu(i) {
 		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-		cnt->icsb_ifree += cntp->icsb_ifree;
 		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
 	}
 
@@ -1675,7 +1687,7 @@ xfs_icsb_counter_disabled(
 	xfs_mount_t	*mp,
 	xfs_sb_field_t	field)
 {
-	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
+	ASSERT(field == XFS_SBS_FDBLOCKS);
 	return test_bit(field, &mp->m_icsb_counters);
 }
 
@@ -1686,7 +1698,7 @@ xfs_icsb_disable_counter(
 {
 	xfs_icsb_cnts_t	cnt;
 
-	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
+	ASSERT(field == XFS_SBS_FDBLOCKS);
 
 	/*
 	 * If we are already disabled, then there is nothing to do
@@ -1705,9 +1717,6 @@ xfs_icsb_disable_counter(
 
 		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
 		switch(field) {
-		case XFS_SBS_IFREE:
-			mp->m_sb.sb_ifree = cnt.icsb_ifree;
-			break;
 		case XFS_SBS_FDBLOCKS:
 			mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
 			break;
@@ -1729,15 +1738,12 @@ xfs_icsb_enable_counter(
 	xfs_icsb_cnts_t	*cntp;
 	int		i;
 
-	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
+	ASSERT(field == XFS_SBS_FDBLOCKS);
 
 	xfs_icsb_lock_all_counters(mp);
 	for_each_online_cpu(i) {
 		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
 		switch (field) {
-		case XFS_SBS_IFREE:
-			cntp->icsb_ifree = count + resid;
-			break;
 		case XFS_SBS_FDBLOCKS:
 			cntp->icsb_fdblocks = count + resid;
 			break;
@@ -1760,8 +1766,6 @@ xfs_icsb_sync_counters_locked(
 
 	xfs_icsb_count(mp, &cnt, flags);
 
-	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
-		mp->m_sb.sb_ifree = cnt.icsb_ifree;
 	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
 		mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
 }
@@ -1813,12 +1817,6 @@ xfs_icsb_balance_counter_locked(
 
 	/* update counters  - first CPU gets residual*/
 	switch (field) {
-	case XFS_SBS_IFREE:
-		count = mp->m_sb.sb_ifree;
-		resid = do_div(count, weight);
-		if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
-			return;
-		break;
 	case XFS_SBS_FDBLOCKS:
 		count = mp->m_sb.sb_fdblocks;
 		resid = do_div(count, weight);
@@ -1873,14 +1871,6 @@ again:
 	}
 
 	switch (field) {
-	case XFS_SBS_IFREE:
-		lcounter = icsbp->icsb_ifree;
-		lcounter += delta;
-		if (unlikely(lcounter < 0))
-			goto balance_counter;
-		icsbp->icsb_ifree = lcounter;
-		break;
-
 	case XFS_SBS_FDBLOCKS:
 		BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
 
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 457c6e3..0cb32ce 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -84,6 +84,7 @@ typedef struct xfs_mount {
 	struct xfs_sb		m_sb;		/* copy of fs superblock */
 	spinlock_t		m_sb_lock;	/* sb counter lock */
 	struct percpu_counter	m_icount;	/* allocated inodes counter */
+	struct percpu_counter	m_ifree;	/* free inodes counter */
 
 	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
 	char			*m_fsname;	/* filesystem name */
@@ -380,6 +381,7 @@ extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
 extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
 			uint, int);
 extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
+extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mount_log_sb(xfs_mount_t *);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern int	xfs_readsb(xfs_mount_t *, int);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 87e169f..e06aa6b 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1088,6 +1088,7 @@ xfs_fs_statfs(
 	struct xfs_inode	*ip = XFS_I(dentry->d_inode);
 	__uint64_t		fakeinos, id;
 	__uint64_t		icount;
+	__uint64_t		ifree;
 	xfs_extlen_t		lsize;
 	__int64_t		ffree;
 
@@ -1100,6 +1101,7 @@ xfs_fs_statfs(
 
 	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
 	icount = percpu_counter_sum(&mp->m_icount);
+	ifree = percpu_counter_sum(&mp->m_ifree);
 
 	spin_lock(&mp->m_sb_lock);
 	statp->f_bsize = sbp->sb_blocksize;
@@ -1115,7 +1117,7 @@ xfs_fs_statfs(
 					mp->m_maxicount);
 
 	/* make sure statp->f_ffree does not underflow */
-	ffree = statp->f_files - (icount - sbp->sb_ifree);
+	ffree = statp->f_files - (icount - ifree);
 	statp->f_ffree = max_t(__int64_t, ffree, 0);
 
 	spin_unlock(&mp->m_sb_lock);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 9bc742b..68680ce 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -560,8 +560,7 @@ xfs_trans_unreserve_and_mod_sb(
 	}
 
 	if (ifreedelta) {
-		error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE,
-						 ifreedelta, rsvd);
+		error = xfs_mod_ifree(mp, ifreedelta);
 		if (error)
 			goto out_undo_icount;
 	}
@@ -630,7 +629,7 @@ xfs_trans_unreserve_and_mod_sb(
 
 out_undo_ifreecount:
 	if (ifreedelta)
-		xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
+		xfs_mod_ifree(mp, -ifreedelta);
 out_undo_icount:
 	if (idelta)
 		xfs_mod_icount(mp, -idelta);
-- 
2.0.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 3/7] xfs: use generic percpu counters for free block counter
  2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
  2015-02-04 20:54 ` [PATCH 1/7] xfs: use generic percpu counters for inode counter Dave Chinner
  2015-02-04 20:54 ` [PATCH 2/7] xfs: use generic percpu counters for free " Dave Chinner
@ 2015-02-04 20:54 ` Dave Chinner
  2015-02-05 14:10   ` Brian Foster
  2015-02-23 20:57   ` Christoph Hellwig
  2015-02-04 20:54 ` [PATCH 4/7] xfs: Remove icsb infrastructure Dave Chinner
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Dave Chinner @ 2015-02-04 20:54 UTC (permalink / raw)
  To: xfs

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 <dchinner@redhat.com>
---
 fs/xfs/libxfs/xfs_bmap.c |  32 ++++----
 fs/xfs/libxfs/xfs_sb.c   |   1 +
 fs/xfs/xfs_fsops.c       |   9 ++-
 fs/xfs/xfs_iomap.c       |   2 +-
 fs/xfs/xfs_mount.c       | 193 ++++++++++++++++++++++++-----------------------
 fs/xfs/xfs_mount.h       |   3 +
 fs/xfs/xfs_super.c       |  10 ++-
 fs/xfs/xfs_trans.c       |  16 ++--
 8 files changed, 135 insertions(+), 131 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 61ec015..e39c9e8 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -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;
@@ -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. */
@@ -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.
 		 */
@@ -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;
 
@@ -4200,7 +4196,7 @@ out_unreserve_blocks:
 	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 ?
@@ -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;
@@ -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);
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index b66aeab..31a3e97 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -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);
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index fa74d03..fed97a9 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -633,9 +633,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;
@@ -710,7 +711,8 @@ retry:
 	} 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 */
 
@@ -749,8 +751,7 @@ out:
 		 * 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;
 	}
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index ccb1dd0..205b948 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -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])
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 650e8f1..9e433b2 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1114,7 +1114,6 @@ xfs_mod_icount(
 	return 0;
 }
 
-
 int
 xfs_mod_ifree(
 	struct xfs_mount	*mp,
@@ -1128,6 +1127,93 @@ xfs_mod_ifree(
 	}
 	return 0;
 }
+
+int
+xfs_mod_fdblocks(
+	struct xfs_mount	*mp,
+	int64_t			delta,
+	bool			rsvd)
+{
+	int64_t			lcounter;
+	long long		res_used;
+	s32			batch;
+
+	if (delta > 0) {
+		/*
+		 * If the reserve pool is depleted, put blocks back into it
+		 * first. Most of the time the pool is full.
+		 */
+		if (likely(mp->m_resblks == mp->m_resblks_avail)) {
+			percpu_counter_add(&mp->m_fdblocks, delta);
+			return 0;
+		}
+
+		spin_lock(&mp->m_sb_lock);
+		res_used = (long long)
+				(mp->m_resblks - mp->m_resblks_avail);
+
+		if (res_used > delta) {
+			mp->m_resblks_avail += delta;
+		} else {
+			delta -= res_used;
+				mp->m_resblks_avail = mp->m_resblks;
+			percpu_counter_add(&mp->m_fdblocks, delta);
+		}
+		spin_unlock(&mp->m_sb_lock);
+		return 0;
+	}
+
+	/*
+	 * Taking blocks away, need to be more accurate the closer we
+	 * are to zero.
+	 *
+	 * batch size is set to a maximum of 1024 blocks - if we are
+	 * allocating of freeing extents larger than this then we aren't
+	 * going to be hammering the counter lock so a lock per update
+	 * is not a problem.
+	 *
+	 * If the counter has a value of less than 2 * max batch size,
+	 * then make everything serialise as we are real close to
+	 * ENOSPC.
+	 */
+#define __BATCH	1024
+	if (percpu_counter_compare(&mp->m_fdblocks, 2 * __BATCH) < 0)
+		batch = 1;
+	else
+		batch = __BATCH;
+#undef __BATCH
+
+	__percpu_counter_add(&mp->m_fdblocks, delta, batch);
+	if (percpu_counter_compare(&mp->m_fdblocks,
+				   XFS_ALLOC_SET_ASIDE(mp)) >= 0) {
+		/* we had space! */
+		return 0;
+	}
+
+	/*
+	 * lock up the sb for dipping into reserves before releasing the space
+	 * that took us to ENOSPC.
+	 */
+	spin_lock(&mp->m_sb_lock);
+	percpu_counter_add(&mp->m_fdblocks, -delta);
+	if (!rsvd)
+		goto fdblocks_enospc;
+
+	lcounter = (long long)mp->m_resblks_avail + delta;
+	if (lcounter >= 0) {
+		mp->m_resblks_avail = lcounter;
+		spin_unlock(&mp->m_sb_lock);
+		return 0;
+	}
+	printk_once(KERN_WARNING
+		"Filesystem \"%s\": reserve blocks depleted! "
+		"Consider increasing reserve pool size.",
+		mp->m_fsname);
+fdblocks_enospc:
+	spin_unlock(&mp->m_sb_lock);
+	return -ENOSPC;
+}
+
 /*
  * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
  * a delta to a specified field in the in-core superblock.  Simply
@@ -1146,7 +1232,6 @@ xfs_mod_incore_sb_unlocked(
 {
 	int		scounter;	/* short counter for 32 bit fields */
 	long long	lcounter;	/* long counter for 64 bit fields */
-	long long	res_used, rem;
 
 	/*
 	 * With the in-core superblock spin lock held, switch
@@ -1157,50 +1242,9 @@ xfs_mod_incore_sb_unlocked(
 	switch (field) {
 	case XFS_SBS_ICOUNT:
 	case XFS_SBS_IFREE:
+	case XFS_SBS_FDBLOCKS:
 		ASSERT(0);
 		return -EINVAL;
-	case XFS_SBS_FDBLOCKS:
-		lcounter = (long long)
-			mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
-		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
-
-		if (delta > 0) {		/* Putting blocks back */
-			if (res_used > delta) {
-				mp->m_resblks_avail += delta;
-			} else {
-				rem = delta - res_used;
-				mp->m_resblks_avail = mp->m_resblks;
-				lcounter += rem;
-			}
-		} else {				/* Taking blocks away */
-			lcounter += delta;
-			if (lcounter >= 0) {
-				mp->m_sb.sb_fdblocks = lcounter +
-							XFS_ALLOC_SET_ASIDE(mp);
-				return 0;
-			}
-
-			/*
-			 * We are out of blocks, use any available reserved
-			 * blocks if were allowed to.
-			 */
-			if (!rsvd)
-				return -ENOSPC;
-
-			lcounter = (long long)mp->m_resblks_avail + delta;
-			if (lcounter >= 0) {
-				mp->m_resblks_avail = lcounter;
-				return 0;
-			}
-			printk_once(KERN_WARNING
-				"Filesystem \"%s\": reserve blocks depleted! "
-				"Consider increasing reserve pool size.",
-				mp->m_fsname);
-			return -ENOSPC;
-		}
-
-		mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
-		return 0;
 	case XFS_SBS_FREXTENTS:
 		lcounter = (long long)mp->m_sb.sb_frextents;
 		lcounter += delta;
@@ -1323,7 +1367,7 @@ xfs_mod_incore_sb(
  *
  * Note that this function may not be used for the superblock values that
  * are tracked with the in-memory per-cpu counters - a direct call to
- * xfs_icsb_modify_counters is required for these.
+ * xfs_mod_incore_sb is required for these.
  */
 int
 xfs_mod_incore_sb_batch(
@@ -1508,7 +1552,6 @@ xfs_icsb_cpu_notify(
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
 		xfs_icsb_lock(mp);
-		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
 		xfs_icsb_unlock(mp);
 		break;
 	case CPU_DEAD:
@@ -1518,13 +1561,9 @@ xfs_icsb_cpu_notify(
 		 * re-enable the counters. */
 		xfs_icsb_lock(mp);
 		spin_lock(&mp->m_sb_lock);
-		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
-
-		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
 
 		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
 
-		xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
 		spin_unlock(&mp->m_sb_lock);
 		xfs_icsb_unlock(mp);
 		break;
@@ -1550,10 +1589,14 @@ xfs_icsb_init_counters(
 	if (error)
 		goto free_icount;
 
+	error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
+	if (error)
+		goto free_ifree;
+
 	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
 	if (!mp->m_sb_cnts) {
 		error = -ENOMEM;
-		goto free_ifree;
+		goto free_fdblocks;
 	}
 
 	for_each_online_cpu(i) {
@@ -1577,6 +1620,8 @@ xfs_icsb_init_counters(
 
 	return 0;
 
+free_fdblocks:
+	percpu_counter_destroy(&mp->m_fdblocks);
 free_ifree:
 	percpu_counter_destroy(&mp->m_ifree);
 free_icount:
@@ -1590,6 +1635,7 @@ xfs_icsb_reinit_counters(
 {
 	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
 	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
+	percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
 
 	xfs_icsb_lock(mp);
 	/*
@@ -1597,7 +1643,6 @@ xfs_icsb_reinit_counters(
 	 * initial balance kicks us off correctly
 	 */
 	mp->m_icsb_counters = -1;
-	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
 	xfs_icsb_unlock(mp);
 }
 
@@ -1612,6 +1657,7 @@ xfs_icsb_destroy_counters(
 
 	percpu_counter_destroy(&mp->m_icount);
 	percpu_counter_destroy(&mp->m_ifree);
+	percpu_counter_destroy(&mp->m_fdblocks);
 
 	mutex_destroy(&mp->m_icsb_mutex);
 }
@@ -1665,18 +1711,11 @@ xfs_icsb_count(
 	xfs_icsb_cnts_t	*cnt,
 	int		flags)
 {
-	xfs_icsb_cnts_t *cntp;
-	int		i;
-
 	memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
 
 	if (!(flags & XFS_ICSB_LAZY_COUNT))
 		xfs_icsb_lock_all_counters(mp);
 
-	for_each_online_cpu(i) {
-		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
-	}
 
 	if (!(flags & XFS_ICSB_LAZY_COUNT))
 		xfs_icsb_unlock_all_counters(mp);
@@ -1687,7 +1726,6 @@ xfs_icsb_counter_disabled(
 	xfs_mount_t	*mp,
 	xfs_sb_field_t	field)
 {
-	ASSERT(field == XFS_SBS_FDBLOCKS);
 	return test_bit(field, &mp->m_icsb_counters);
 }
 
@@ -1698,8 +1736,6 @@ xfs_icsb_disable_counter(
 {
 	xfs_icsb_cnts_t	cnt;
 
-	ASSERT(field == XFS_SBS_FDBLOCKS);
-
 	/*
 	 * If we are already disabled, then there is nothing to do
 	 * here. We check before locking all the counters to avoid
@@ -1717,9 +1753,6 @@ xfs_icsb_disable_counter(
 
 		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
 		switch(field) {
-		case XFS_SBS_FDBLOCKS:
-			mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
-			break;
 		default:
 			BUG();
 		}
@@ -1735,18 +1768,11 @@ xfs_icsb_enable_counter(
 	uint64_t	count,
 	uint64_t	resid)
 {
-	xfs_icsb_cnts_t	*cntp;
 	int		i;
 
-	ASSERT(field == XFS_SBS_FDBLOCKS);
-
 	xfs_icsb_lock_all_counters(mp);
 	for_each_online_cpu(i) {
-		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
 		switch (field) {
-		case XFS_SBS_FDBLOCKS:
-			cntp->icsb_fdblocks = count + resid;
-			break;
 		default:
 			BUG();
 			break;
@@ -1765,9 +1791,6 @@ xfs_icsb_sync_counters_locked(
 	xfs_icsb_cnts_t	cnt;
 
 	xfs_icsb_count(mp, &cnt, flags);
-
-	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
-		mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
 }
 
 /*
@@ -1809,20 +1832,12 @@ xfs_icsb_balance_counter_locked(
 	int		min_per_cpu)
 {
 	uint64_t	count, resid;
-	int		weight = num_online_cpus();
-	uint64_t	min = (uint64_t)min_per_cpu;
 
 	/* disable counter and sync counter */
 	xfs_icsb_disable_counter(mp, field);
 
 	/* update counters  - first CPU gets residual*/
 	switch (field) {
-	case XFS_SBS_FDBLOCKS:
-		count = mp->m_sb.sb_fdblocks;
-		resid = do_div(count, weight);
-		if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
-			return;
-		break;
 	default:
 		BUG();
 		count = resid = 0;	/* quiet, gcc */
@@ -1851,7 +1866,6 @@ xfs_icsb_modify_counters(
 	int		rsvd)
 {
 	xfs_icsb_cnts_t	*icsbp;
-	long long	lcounter;	/* long counter for 64 bit fields */
 	int		ret = 0;
 
 	might_sleep();
@@ -1871,18 +1885,9 @@ again:
 	}
 
 	switch (field) {
-	case XFS_SBS_FDBLOCKS:
-		BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
-
-		lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
-		lcounter += delta;
-		if (unlikely(lcounter < 0))
-			goto balance_counter;
-		icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
-		break;
 	default:
 		BUG();
-		break;
+		goto balance_counter; /* be still, gcc */
 	}
 	xfs_icsb_unlock_cntr(icsbp);
 	preempt_enable();
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 0cb32ce..76f5d25 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -85,6 +85,7 @@ typedef struct xfs_mount {
 	spinlock_t		m_sb_lock;	/* sb counter lock */
 	struct percpu_counter	m_icount;	/* allocated inodes counter */
 	struct percpu_counter	m_ifree;	/* free inodes counter */
+	struct percpu_counter	m_fdblocks;	/* free block counter */
 
 	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
 	char			*m_fsname;	/* filesystem name */
@@ -382,6 +383,8 @@ extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
 			uint, int);
 extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
+extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
+				 bool reserved);
 extern int	xfs_mount_log_sb(xfs_mount_t *);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern int	xfs_readsb(xfs_mount_t *, int);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index e06aa6b..4c6af31 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1089,6 +1089,7 @@ xfs_fs_statfs(
 	__uint64_t		fakeinos, id;
 	__uint64_t		icount;
 	__uint64_t		ifree;
+	__uint64_t		fdblocks;
 	xfs_extlen_t		lsize;
 	__int64_t		ffree;
 
@@ -1102,13 +1103,17 @@ xfs_fs_statfs(
 	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
 	icount = percpu_counter_sum(&mp->m_icount);
 	ifree = percpu_counter_sum(&mp->m_ifree);
+	fdblocks = percpu_counter_sum(&mp->m_fdblocks);
 
 	spin_lock(&mp->m_sb_lock);
 	statp->f_bsize = sbp->sb_blocksize;
 	lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
 	statp->f_blocks = sbp->sb_dblocks - lsize;
-	statp->f_bfree = statp->f_bavail =
-				sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+	spin_unlock(&mp->m_sb_lock);
+
+	statp->f_bfree = fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+	statp->f_bavail = statp->f_bfree;
+
 	fakeinos = statp->f_bfree << sbp->sb_inopblog;
 	statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
 	if (mp->m_maxicount)
@@ -1120,7 +1125,6 @@ xfs_fs_statfs(
 	ffree = statp->f_files - (icount - ifree);
 	statp->f_ffree = max_t(__int64_t, ffree, 0);
 
-	spin_unlock(&mp->m_sb_lock);
 
 	if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
 	    ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) ==
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 68680ce..e99f5e5 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -173,7 +173,7 @@ xfs_trans_reserve(
 	uint			rtextents)
 {
 	int		error = 0;
-	int		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
+	bool		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
 
 	/* Mark this thread as being in a transaction */
 	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
@@ -184,8 +184,7 @@ xfs_trans_reserve(
 	 * fail if the count would go below zero.
 	 */
 	if (blocks > 0) {
-		error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
-					  -((int64_t)blocks), rsvd);
+		error = xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
 		if (error != 0) {
 			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 			return -ENOSPC;
@@ -268,8 +267,7 @@ undo_log:
 
 undo_blocks:
 	if (blocks > 0) {
-		xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
-					 (int64_t)blocks, rsvd);
+		xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
 		tp->t_blk_res = 0;
 	}
 
@@ -516,14 +514,13 @@ xfs_trans_unreserve_and_mod_sb(
 	xfs_mount_t	*mp = tp->t_mountp;
 	/* REFERENCED */
 	int		error;
-	int		rsvd;
+	bool		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
 	int64_t		blkdelta = 0;
 	int64_t		rtxdelta = 0;
 	int64_t		idelta = 0;
 	int64_t		ifreedelta = 0;
 
 	msbp = msb;
-	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
 
 	/* calculate deltas */
 	if (tp->t_blk_res > 0)
@@ -547,8 +544,7 @@ xfs_trans_unreserve_and_mod_sb(
 
 	/* apply the per-cpu counters */
 	if (blkdelta) {
-		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-						 blkdelta, rsvd);
+		error = xfs_mod_fdblocks(mp, blkdelta, rsvd);
 		if (error)
 			goto out;
 	}
@@ -635,7 +631,7 @@ out_undo_icount:
 		xfs_mod_icount(mp, -idelta);
 out_undo_fdblocks:
 	if (blkdelta)
-		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
+		xfs_mod_fdblocks(mp, -blkdelta, rsvd);
 out:
 	ASSERT(error == 0);
 	return;
-- 
2.0.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 4/7] xfs: Remove icsb infrastructure
  2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
                   ` (2 preceding siblings ...)
  2015-02-04 20:54 ` [PATCH 3/7] xfs: use generic percpu counters for free block counter Dave Chinner
@ 2015-02-04 20:54 ` Dave Chinner
  2015-02-05 14:10   ` Brian Foster
  2015-02-23 20:59   ` Christoph Hellwig
  2015-02-04 20:54 ` [PATCH 5/7] xfs: introduce xfs_mod_frextents Dave Chinner
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Dave Chinner @ 2015-02-04 20:54 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Now that the in-core superblock infrastructure has been replaced with
generic per-cpu counters, we don't need it anymore. Nuke it from
orbit so we are sure that it won't haunt us again...

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 fs/xfs/libxfs/xfs_sb.c   |   8 +-
 fs/xfs/xfs_fsops.c       |   2 -
 fs/xfs/xfs_iomap.c       |   1 -
 fs/xfs/xfs_linux.h       |   9 -
 fs/xfs/xfs_log_recover.c |   4 +-
 fs/xfs/xfs_mount.c       | 516 +----------------------------------------------
 fs/xfs/xfs_mount.h       |  67 ------
 fs/xfs/xfs_super.c       |  84 ++++++--
 fs/xfs/xfs_super.h       |   2 +
 9 files changed, 72 insertions(+), 621 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 31a3e97..a270095 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -743,17 +743,15 @@ xfs_initialize_perag_data(
 		btree += pag->pagf_btreeblks;
 		xfs_perag_put(pag);
 	}
-	/*
-	 * Overwrite incore superblock counters with just-read data
-	 */
+
+	/* Overwrite incore superblock counters with just-read data */
 	spin_lock(&mp->m_sb_lock);
 	sbp->sb_ifree = ifree;
 	sbp->sb_icount = ialloc;
 	sbp->sb_fdblocks = bfree + bfreelst + btree;
 	spin_unlock(&mp->m_sb_lock);
 
-	/* Fixup the per-cpu counters as well. */
-	xfs_icsb_reinit_counters(mp);
+	xfs_reinit_percpu_counters(mp);
 
 	return 0;
 }
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index fed97a9..a45c82b4 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -630,7 +630,6 @@ xfs_fs_counts(
 	xfs_mount_t		*mp,
 	xfs_fsop_counts_t	*cnt)
 {
-	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) -
@@ -694,7 +693,6 @@ xfs_reserve_blocks(
 	 */
 retry:
 	spin_lock(&mp->m_sb_lock);
-	xfs_icsb_sync_counters_locked(mp, 0);
 
 	/*
 	 * If our previous reservation was larger than the current value,
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 205b948..38e633b 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -460,7 +460,6 @@ xfs_iomap_prealloc_size(
 	alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN),
 				       alloc_blocks);
 
-	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
 	freesp = percpu_counter_read_positive(&mp->m_fdblocks);
 	if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
 		shift = 2;
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index c31d2c2..7c7842c 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -116,15 +116,6 @@ typedef __uint64_t __psunsigned_t;
 #undef XFS_NATIVE_HOST
 #endif
 
-/*
- * Feature macros (disable/enable)
- */
-#ifdef CONFIG_SMP
-#define HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
-#else
-#undef  HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
-#endif
-
 #define irix_sgid_inherit	xfs_params.sgid_inherit.val
 #define irix_symlink_mode	xfs_params.symlink_mode.val
 #define xfs_panic_mask		xfs_params.panic_mask.val
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index a5a945f..4f5784f 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -4463,10 +4463,10 @@ xlog_do_recover(
 	xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
 	ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
 	ASSERT(xfs_sb_good_version(sbp));
+	xfs_reinit_percpu_counters(log->l_mp);
+
 	xfs_buf_relse(bp);
 
-	/* We've re-read the superblock so re-initialize per-cpu counters */
-	xfs_icsb_reinit_counters(log->l_mp);
 
 	xlog_recover_check_summary(log);
 
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 9e433b2..1d26200 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -43,18 +43,6 @@
 #include "xfs_sysfs.h"
 
 
-#ifdef HAVE_PERCPU_SB
-STATIC void	xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
-						int);
-STATIC void	xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
-						int);
-STATIC void	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
-#else
-
-#define xfs_icsb_balance_counter(mp, a, b)		do { } while (0)
-#define xfs_icsb_balance_counter_locked(mp, a, b)	do { } while (0)
-#endif
-
 static DEFINE_MUTEX(xfs_uuid_table_mutex);
 static int xfs_uuid_table_size;
 static uuid_t *xfs_uuid_table;
@@ -347,8 +335,7 @@ reread:
 		goto reread;
 	}
 
-	/* Initialize per-cpu counters */
-	xfs_icsb_reinit_counters(mp);
+	xfs_reinit_percpu_counters(mp);
 
 	/* no need to be quiet anymore, so reset the buf ops */
 	bp->b_ops = &xfs_sb_buf_ops;
@@ -1087,8 +1074,6 @@ xfs_log_sbcount(xfs_mount_t *mp)
 	if (!xfs_fs_writable(mp, SB_FREEZE_COMPLETE))
 		return 0;
 
-	xfs_icsb_sync_counters(mp, 0);
-
 	/*
 	 * we don't need to do this if we are updating the superblock
 	 * counters on every modification.
@@ -1467,502 +1452,3 @@ xfs_dev_is_read_only(
 	}
 	return 0;
 }
-
-#ifdef HAVE_PERCPU_SB
-/*
- * Per-cpu incore superblock counters
- *
- * Simple concept, difficult implementation
- *
- * Basically, replace the incore superblock counters with a distributed per cpu
- * counter for contended fields (e.g.  free block count).
- *
- * Difficulties arise in that the incore sb is used for ENOSPC checking, and
- * hence needs to be accurately read when we are running low on space. Hence
- * there is a method to enable and disable the per-cpu counters based on how
- * much "stuff" is available in them.
- *
- * Basically, a counter is enabled if there is enough free resource to justify
- * running a per-cpu fast-path. If the per-cpu counter runs out (i.e. a local
- * ENOSPC), then we disable the counters to synchronise all callers and
- * re-distribute the available resources.
- *
- * If, once we redistributed the available resources, we still get a failure,
- * we disable the per-cpu counter and go through the slow path.
- *
- * The slow path is the current xfs_mod_incore_sb() function.  This means that
- * when we disable a per-cpu counter, we need to drain its resources back to
- * the global superblock. We do this after disabling the counter to prevent
- * more threads from queueing up on the counter.
- *
- * Essentially, this means that we still need a lock in the fast path to enable
- * synchronisation between the global counters and the per-cpu counters. This
- * is not a problem because the lock will be local to a CPU almost all the time
- * and have little contention except when we get to ENOSPC conditions.
- *
- * Basically, this lock becomes a barrier that enables us to lock out the fast
- * path while we do things like enabling and disabling counters and
- * synchronising the counters.
- *
- * Locking rules:
- *
- * 	1. m_sb_lock before picking up per-cpu locks
- * 	2. per-cpu locks always picked up via for_each_online_cpu() order
- * 	3. accurate counter sync requires m_sb_lock + per cpu locks
- * 	4. modifying per-cpu counters requires holding per-cpu lock
- * 	5. modifying global counters requires holding m_sb_lock
- *	6. enabling or disabling a counter requires holding the m_sb_lock 
- *	   and _none_ of the per-cpu locks.
- *
- * Disabled counters are only ever re-enabled by a balance operation
- * that results in more free resources per CPU than a given threshold.
- * To ensure counters don't remain disabled, they are rebalanced when
- * the global resource goes above a higher threshold (i.e. some hysteresis
- * is present to prevent thrashing).
- */
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * hot-plug CPU notifier support.
- *
- * We need a notifier per filesystem as we need to be able to identify
- * the filesystem to balance the counters out. This is achieved by
- * having a notifier block embedded in the xfs_mount_t and doing pointer
- * magic to get the mount pointer from the notifier block address.
- */
-STATIC int
-xfs_icsb_cpu_notify(
-	struct notifier_block *nfb,
-	unsigned long action,
-	void *hcpu)
-{
-	xfs_icsb_cnts_t *cntp;
-	xfs_mount_t	*mp;
-
-	mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
-	cntp = (xfs_icsb_cnts_t *)
-			per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
-	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		/* Easy Case - initialize the area and locks, and
-		 * then rebalance when online does everything else for us. */
-		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
-		break;
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		xfs_icsb_lock(mp);
-		xfs_icsb_unlock(mp);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		/* Disable all the counters, then fold the dead cpu's
-		 * count into the total on the global superblock and
-		 * re-enable the counters. */
-		xfs_icsb_lock(mp);
-		spin_lock(&mp->m_sb_lock);
-
-		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
-
-		spin_unlock(&mp->m_sb_lock);
-		xfs_icsb_unlock(mp);
-		break;
-	}
-
-	return NOTIFY_OK;
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
-int
-xfs_icsb_init_counters(
-	xfs_mount_t	*mp)
-{
-	xfs_icsb_cnts_t *cntp;
-	int		error;
-	int		i;
-
-	error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
-	if (error)
-		return error;
-
-	error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
-	if (error)
-		goto free_icount;
-
-	error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
-	if (error)
-		goto free_ifree;
-
-	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
-	if (!mp->m_sb_cnts) {
-		error = -ENOMEM;
-		goto free_fdblocks;
-	}
-
-	for_each_online_cpu(i) {
-		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
-	}
-
-	mutex_init(&mp->m_icsb_mutex);
-
-	/*
-	 * start with all counters disabled so that the
-	 * initial balance kicks us off correctly
-	 */
-	mp->m_icsb_counters = -1;
-
-#ifdef CONFIG_HOTPLUG_CPU
-	mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
-	mp->m_icsb_notifier.priority = 0;
-	register_hotcpu_notifier(&mp->m_icsb_notifier);
-#endif /* CONFIG_HOTPLUG_CPU */
-
-	return 0;
-
-free_fdblocks:
-	percpu_counter_destroy(&mp->m_fdblocks);
-free_ifree:
-	percpu_counter_destroy(&mp->m_ifree);
-free_icount:
-	percpu_counter_destroy(&mp->m_icount);
-	return error;
-}
-
-void
-xfs_icsb_reinit_counters(
-	xfs_mount_t	*mp)
-{
-	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
-	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
-	percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
-
-	xfs_icsb_lock(mp);
-	/*
-	 * start with all counters disabled so that the
-	 * initial balance kicks us off correctly
-	 */
-	mp->m_icsb_counters = -1;
-	xfs_icsb_unlock(mp);
-}
-
-void
-xfs_icsb_destroy_counters(
-	xfs_mount_t	*mp)
-{
-	if (mp->m_sb_cnts) {
-		unregister_hotcpu_notifier(&mp->m_icsb_notifier);
-		free_percpu(mp->m_sb_cnts);
-	}
-
-	percpu_counter_destroy(&mp->m_icount);
-	percpu_counter_destroy(&mp->m_ifree);
-	percpu_counter_destroy(&mp->m_fdblocks);
-
-	mutex_destroy(&mp->m_icsb_mutex);
-}
-
-STATIC void
-xfs_icsb_lock_cntr(
-	xfs_icsb_cnts_t	*icsbp)
-{
-	while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
-		ndelay(1000);
-	}
-}
-
-STATIC void
-xfs_icsb_unlock_cntr(
-	xfs_icsb_cnts_t	*icsbp)
-{
-	clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
-}
-
-
-STATIC void
-xfs_icsb_lock_all_counters(
-	xfs_mount_t	*mp)
-{
-	xfs_icsb_cnts_t *cntp;
-	int		i;
-
-	for_each_online_cpu(i) {
-		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-		xfs_icsb_lock_cntr(cntp);
-	}
-}
-
-STATIC void
-xfs_icsb_unlock_all_counters(
-	xfs_mount_t	*mp)
-{
-	xfs_icsb_cnts_t *cntp;
-	int		i;
-
-	for_each_online_cpu(i) {
-		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-		xfs_icsb_unlock_cntr(cntp);
-	}
-}
-
-STATIC void
-xfs_icsb_count(
-	xfs_mount_t	*mp,
-	xfs_icsb_cnts_t	*cnt,
-	int		flags)
-{
-	memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
-
-	if (!(flags & XFS_ICSB_LAZY_COUNT))
-		xfs_icsb_lock_all_counters(mp);
-
-
-	if (!(flags & XFS_ICSB_LAZY_COUNT))
-		xfs_icsb_unlock_all_counters(mp);
-}
-
-STATIC int
-xfs_icsb_counter_disabled(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field)
-{
-	return test_bit(field, &mp->m_icsb_counters);
-}
-
-STATIC void
-xfs_icsb_disable_counter(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field)
-{
-	xfs_icsb_cnts_t	cnt;
-
-	/*
-	 * If we are already disabled, then there is nothing to do
-	 * here. We check before locking all the counters to avoid
-	 * the expensive lock operation when being called in the
-	 * slow path and the counter is already disabled. This is
-	 * safe because the only time we set or clear this state is under
-	 * the m_icsb_mutex.
-	 */
-	if (xfs_icsb_counter_disabled(mp, field))
-		return;
-
-	xfs_icsb_lock_all_counters(mp);
-	if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
-		/* drain back to superblock */
-
-		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
-		switch(field) {
-		default:
-			BUG();
-		}
-	}
-
-	xfs_icsb_unlock_all_counters(mp);
-}
-
-STATIC void
-xfs_icsb_enable_counter(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field,
-	uint64_t	count,
-	uint64_t	resid)
-{
-	int		i;
-
-	xfs_icsb_lock_all_counters(mp);
-	for_each_online_cpu(i) {
-		switch (field) {
-		default:
-			BUG();
-			break;
-		}
-		resid = 0;
-	}
-	clear_bit(field, &mp->m_icsb_counters);
-	xfs_icsb_unlock_all_counters(mp);
-}
-
-void
-xfs_icsb_sync_counters_locked(
-	xfs_mount_t	*mp,
-	int		flags)
-{
-	xfs_icsb_cnts_t	cnt;
-
-	xfs_icsb_count(mp, &cnt, flags);
-}
-
-/*
- * Accurate update of per-cpu counters to incore superblock
- */
-void
-xfs_icsb_sync_counters(
-	xfs_mount_t	*mp,
-	int		flags)
-{
-	spin_lock(&mp->m_sb_lock);
-	xfs_icsb_sync_counters_locked(mp, flags);
-	spin_unlock(&mp->m_sb_lock);
-}
-
-/*
- * Balance and enable/disable counters as necessary.
- *
- * Thresholds for re-enabling counters are somewhat magic.  inode counts are
- * chosen to be the same number as single on disk allocation chunk per CPU, and
- * free blocks is something far enough zero that we aren't going thrash when we
- * get near ENOSPC. We also need to supply a minimum we require per cpu to
- * prevent looping endlessly when xfs_alloc_space asks for more than will
- * be distributed to a single CPU but each CPU has enough blocks to be
- * reenabled.
- *
- * Note that we can be called when counters are already disabled.
- * xfs_icsb_disable_counter() optimises the counter locking in this case to
- * prevent locking every per-cpu counter needlessly.
- */
-
-#define XFS_ICSB_INO_CNTR_REENABLE	(uint64_t)64
-#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
-		(uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
-STATIC void
-xfs_icsb_balance_counter_locked(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t  field,
-	int		min_per_cpu)
-{
-	uint64_t	count, resid;
-
-	/* disable counter and sync counter */
-	xfs_icsb_disable_counter(mp, field);
-
-	/* update counters  - first CPU gets residual*/
-	switch (field) {
-	default:
-		BUG();
-		count = resid = 0;	/* quiet, gcc */
-		break;
-	}
-
-	xfs_icsb_enable_counter(mp, field, count, resid);
-}
-
-STATIC void
-xfs_icsb_balance_counter(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t  fields,
-	int		min_per_cpu)
-{
-	spin_lock(&mp->m_sb_lock);
-	xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
-	spin_unlock(&mp->m_sb_lock);
-}
-
-int
-xfs_icsb_modify_counters(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field,
-	int64_t		delta,
-	int		rsvd)
-{
-	xfs_icsb_cnts_t	*icsbp;
-	int		ret = 0;
-
-	might_sleep();
-again:
-	preempt_disable();
-	icsbp = this_cpu_ptr(mp->m_sb_cnts);
-
-	/*
-	 * if the counter is disabled, go to slow path
-	 */
-	if (unlikely(xfs_icsb_counter_disabled(mp, field)))
-		goto slow_path;
-	xfs_icsb_lock_cntr(icsbp);
-	if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
-		xfs_icsb_unlock_cntr(icsbp);
-		goto slow_path;
-	}
-
-	switch (field) {
-	default:
-		BUG();
-		goto balance_counter; /* be still, gcc */
-	}
-	xfs_icsb_unlock_cntr(icsbp);
-	preempt_enable();
-	return 0;
-
-slow_path:
-	preempt_enable();
-
-	/*
-	 * serialise with a mutex so we don't burn lots of cpu on
-	 * the superblock lock. We still need to hold the superblock
-	 * lock, however, when we modify the global structures.
-	 */
-	xfs_icsb_lock(mp);
-
-	/*
-	 * Now running atomically.
-	 *
-	 * If the counter is enabled, someone has beaten us to rebalancing.
-	 * Drop the lock and try again in the fast path....
-	 */
-	if (!(xfs_icsb_counter_disabled(mp, field))) {
-		xfs_icsb_unlock(mp);
-		goto again;
-	}
-
-	/*
-	 * The counter is currently disabled. Because we are
-	 * running atomically here, we know a rebalance cannot
-	 * be in progress. Hence we can go straight to operating
-	 * on the global superblock. We do not call xfs_mod_incore_sb()
-	 * here even though we need to get the m_sb_lock. Doing so
-	 * will cause us to re-enter this function and deadlock.
-	 * Hence we get the m_sb_lock ourselves and then call
-	 * xfs_mod_incore_sb_unlocked() as the unlocked path operates
-	 * directly on the global counters.
-	 */
-	spin_lock(&mp->m_sb_lock);
-	ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-	spin_unlock(&mp->m_sb_lock);
-
-	/*
-	 * Now that we've modified the global superblock, we
-	 * may be able to re-enable the distributed counters
-	 * (e.g. lots of space just got freed). After that
-	 * we are done.
-	 */
-	if (ret != -ENOSPC)
-		xfs_icsb_balance_counter(mp, field, 0);
-	xfs_icsb_unlock(mp);
-	return ret;
-
-balance_counter:
-	xfs_icsb_unlock_cntr(icsbp);
-	preempt_enable();
-
-	/*
-	 * We may have multiple threads here if multiple per-cpu
-	 * counters run dry at the same time. This will mean we can
-	 * do more balances than strictly necessary but it is not
-	 * the common slowpath case.
-	 */
-	xfs_icsb_lock(mp);
-
-	/*
-	 * running atomically.
-	 *
-	 * This will leave the counter in the correct state for future
-	 * accesses. After the rebalance, we simply try again and our retry
-	 * will either succeed through the fast path or slow path without
-	 * another balance operation being required.
-	 */
-	xfs_icsb_balance_counter(mp, field, delta);
-	xfs_icsb_unlock(mp);
-	goto again;
-}
-
-#endif
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 76f5d25..ff1d1d5 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -18,8 +18,6 @@
 #ifndef __XFS_MOUNT_H__
 #define	__XFS_MOUNT_H__
 
-#ifdef __KERNEL__
-
 struct xlog;
 struct xfs_inode;
 struct xfs_mru_cache;
@@ -29,43 +27,6 @@ struct xfs_quotainfo;
 struct xfs_dir_ops;
 struct xfs_da_geometry;
 
-#ifdef HAVE_PERCPU_SB
-
-/*
- * Valid per-cpu incore superblock counters. Note that if you add new counters,
- * you may need to define new counter disabled bit field descriptors as there
- * are more possible fields in the superblock that can fit in a bitfield on a
- * 32 bit platform. The XFS_SBS_* values for the current current counters just
- * fit.
- */
-typedef struct xfs_icsb_cnts {
-	uint64_t	icsb_fdblocks;
-	uint64_t	icsb_ifree;
-	unsigned long	icsb_flags;
-} xfs_icsb_cnts_t;
-
-#define XFS_ICSB_FLAG_LOCK	(1 << 0)	/* counter lock bit */
-
-#define XFS_ICSB_LAZY_COUNT	(1 << 1)	/* accuracy not needed */
-
-extern int	xfs_icsb_init_counters(struct xfs_mount *);
-extern void	xfs_icsb_reinit_counters(struct xfs_mount *);
-extern void	xfs_icsb_destroy_counters(struct xfs_mount *);
-extern void	xfs_icsb_sync_counters(struct xfs_mount *, int);
-extern void	xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
-extern int	xfs_icsb_modify_counters(struct xfs_mount *, xfs_sb_field_t,
-						int64_t, int);
-
-#else
-#define xfs_icsb_init_counters(mp)		(0)
-#define xfs_icsb_destroy_counters(mp)		do { } while (0)
-#define xfs_icsb_reinit_counters(mp)		do { } while (0)
-#define xfs_icsb_sync_counters(mp, flags)	do { } while (0)
-#define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
-#define xfs_icsb_modify_counters(mp, field, delta, rsvd) \
-	xfs_mod_incore_sb(mp, field, delta, rsvd)
-#endif
-
 /* dynamic preallocation free space thresholds, 5% down to 1% */
 enum {
 	XFS_LOWSP_1_PCNT = 0,
@@ -156,12 +117,6 @@ typedef struct xfs_mount {
 	const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */
 	uint			m_chsize;	/* size of next field */
 	atomic_t		m_active_trans;	/* number trans frozen */
-#ifdef HAVE_PERCPU_SB
-	xfs_icsb_cnts_t __percpu *m_sb_cnts;	/* per-cpu superblock counters */
-	unsigned long		m_icsb_counters; /* disabled per-cpu counters */
-	struct notifier_block	m_icsb_notifier; /* hotplug cpu notifier */
-	struct mutex		m_icsb_mutex;	/* balancer sync lock */
-#endif
 	struct xfs_mru_cache	*m_filestream;  /* per-mount filestream data */
 	struct delayed_work	m_reclaim_work;	/* background inode reclaim */
 	struct delayed_work	m_eofblocks_work; /* background eof blocks
@@ -294,26 +249,6 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
 }
 
 /*
- * Per-cpu superblock locking functions
- */
-#ifdef HAVE_PERCPU_SB
-static inline void
-xfs_icsb_lock(xfs_mount_t *mp)
-{
-	mutex_lock(&mp->m_icsb_mutex);
-}
-
-static inline void
-xfs_icsb_unlock(xfs_mount_t *mp)
-{
-	mutex_unlock(&mp->m_icsb_mutex);
-}
-#else
-#define xfs_icsb_lock(mp)
-#define xfs_icsb_unlock(mp)
-#endif
-
-/*
  * This structure is for use by the xfs_mod_incore_sb_batch() routine.
  * xfs_growfs can specify a few fields which are more than int limit
  */
@@ -396,6 +331,4 @@ extern int	xfs_dev_is_read_only(struct xfs_mount *, char *);
 
 extern void	xfs_set_low_space_thresholds(struct xfs_mount *);
 
-#endif	/* __KERNEL__ */
-
 #endif	/* __XFS_MOUNT_H__ */
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 4c6af31..af6d268 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1035,23 +1035,6 @@ xfs_free_fsname(
 	kfree(mp->m_logname);
 }
 
-STATIC void
-xfs_fs_put_super(
-	struct super_block	*sb)
-{
-	struct xfs_mount	*mp = XFS_M(sb);
-
-	xfs_filestream_unmount(mp);
-	xfs_unmountfs(mp);
-
-	xfs_freesb(mp);
-	xfs_icsb_destroy_counters(mp);
-	xfs_destroy_mount_workqueues(mp);
-	xfs_close_devices(mp);
-	xfs_free_fsname(mp);
-	kfree(mp);
-}
-
 STATIC int
 xfs_fs_sync_fs(
 	struct super_block	*sb,
@@ -1100,7 +1083,6 @@ xfs_fs_statfs(
 	statp->f_fsid.val[0] = (u32)id;
 	statp->f_fsid.val[1] = (u32)(id >> 32);
 
-	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
 	icount = percpu_counter_sum(&mp->m_icount);
 	ifree = percpu_counter_sum(&mp->m_ifree);
 	fdblocks = percpu_counter_sum(&mp->m_fdblocks);
@@ -1405,6 +1387,51 @@ xfs_finish_flags(
 	return 0;
 }
 
+static int
+xfs_init_percpu_counters(
+	struct xfs_mount	*mp)
+{
+	int		error;
+
+	error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
+	if (error)
+		return ENOMEM;
+
+	error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
+	if (error)
+		goto free_icount;
+
+	error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
+	if (error)
+		goto free_ifree;
+
+	return 0;
+
+free_ifree:
+	percpu_counter_destroy(&mp->m_ifree);
+free_icount:
+	percpu_counter_destroy(&mp->m_icount);
+	return -ENOMEM;
+}
+
+void
+xfs_reinit_percpu_counters(
+	struct xfs_mount	*mp)
+{
+	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
+	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
+	percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
+}
+
+static void
+xfs_destroy_percpu_counters(
+	struct xfs_mount	*mp)
+{
+	percpu_counter_destroy(&mp->m_icount);
+	percpu_counter_destroy(&mp->m_ifree);
+	percpu_counter_destroy(&mp->m_fdblocks);
+}
+
 STATIC int
 xfs_fs_fill_super(
 	struct super_block	*sb,
@@ -1453,7 +1480,7 @@ xfs_fs_fill_super(
 	if (error)
 		goto out_close_devices;
 
-	error = xfs_icsb_init_counters(mp);
+	error = xfs_init_percpu_counters(mp);
 	if (error)
 		goto out_destroy_workqueues;
 
@@ -1511,7 +1538,7 @@ xfs_fs_fill_super(
  out_free_sb:
 	xfs_freesb(mp);
  out_destroy_counters:
-	xfs_icsb_destroy_counters(mp);
+	xfs_destroy_percpu_counters(mp);
 out_destroy_workqueues:
 	xfs_destroy_mount_workqueues(mp);
  out_close_devices:
@@ -1528,6 +1555,23 @@ out_destroy_workqueues:
 	goto out_free_sb;
 }
 
+STATIC void
+xfs_fs_put_super(
+	struct super_block	*sb)
+{
+	struct xfs_mount	*mp = XFS_M(sb);
+
+	xfs_filestream_unmount(mp);
+	xfs_unmountfs(mp);
+
+	xfs_freesb(mp);
+	xfs_destroy_percpu_counters(mp);
+	xfs_destroy_mount_workqueues(mp);
+	xfs_close_devices(mp);
+	xfs_free_fsname(mp);
+	kfree(mp);
+}
+
 STATIC struct dentry *
 xfs_fs_mount(
 	struct file_system_type	*fs_type,
diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
index 2b830c2..499058f 100644
--- a/fs/xfs/xfs_super.h
+++ b/fs/xfs/xfs_super.h
@@ -72,6 +72,8 @@ extern const struct export_operations xfs_export_operations;
 extern const struct xattr_handler *xfs_xattr_handlers[];
 extern const struct quotactl_ops xfs_quotactl_operations;
 
+extern void xfs_reinit_percpu_counters(struct xfs_mount *mp);
+
 #define XFS_M(sb)		((struct xfs_mount *)((sb)->s_fs_info))
 
 #endif	/* __XFS_SUPER_H__ */
-- 
2.0.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 5/7] xfs: introduce xfs_mod_frextents
  2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
                   ` (3 preceding siblings ...)
  2015-02-04 20:54 ` [PATCH 4/7] xfs: Remove icsb infrastructure Dave Chinner
@ 2015-02-04 20:54 ` Dave Chinner
  2015-02-05 14:10   ` Brian Foster
  2015-02-23 21:02   ` Christoph Hellwig
  2015-02-04 20:54 ` [PATCH 6/7] xfs: replace xfs_mod_incore_sb_batched Dave Chinner
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Dave Chinner @ 2015-02-04 20:54 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Add a new helper to modify the incore counter of free realtime
extents. This matches the helpers used for inode and data block
counters, and removes a significant users of the xfs_mod_incore_sb()
interface.

Based on a patch originally from Christoph Hellwig.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 fs/xfs/libxfs/xfs_bmap.c |  8 +++-----
 fs/xfs/xfs_mount.c       | 27 +++++++++++++++++++--------
 fs/xfs/xfs_mount.h       |  2 ++
 fs/xfs/xfs_trans.c       | 18 ++++++++++--------
 4 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index e39c9e8..b8e97fd0 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -4158,8 +4158,7 @@ xfs_bmapi_reserve_delalloc(
 	ASSERT(indlen > 0);
 
 	if (rt) {
-		error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
-					  -((int64_t)extsz), 0);
+		error = xfs_mod_frextents(mp, -((int64_t)extsz));
 	} else {
 		error = xfs_mod_fdblocks(mp, -((int64_t)alen), false);
 	}
@@ -4194,7 +4193,7 @@ xfs_bmapi_reserve_delalloc(
 
 out_unreserve_blocks:
 	if (rt)
-		xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0);
+		xfs_mod_frextents(mp, extsz);
 	else
 		xfs_mod_fdblocks(mp, alen, false);
 out_unreserve_quota:
@@ -5278,8 +5277,7 @@ xfs_bunmapi(
 
 				rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
 				do_div(rtexts, mp->m_sb.sb_rextsize);
-				xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
-						(int64_t)rtexts, 0);
+				xfs_mod_frextents(mp, (int64_t)rtexts);
 				(void)xfs_trans_reserve_quota_nblks(NULL,
 					ip, -((long)del.br_blockcount), 0,
 					XFS_QMOPT_RES_RTBLKS);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 1d26200..284f528 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1199,6 +1199,24 @@ fdblocks_enospc:
 	return -ENOSPC;
 }
 
+int
+xfs_mod_frextents(
+	struct xfs_mount	*mp,
+	int64_t			delta)
+{
+	int64_t			lcounter;
+	int			ret = 0;
+
+	spin_lock(&mp->m_sb_lock);
+	lcounter = mp->m_sb.sb_frextents + delta;
+	if (lcounter < 0)
+		ret = -ENOSPC;
+	else
+		mp->m_sb.sb_frextents = lcounter;
+	spin_unlock(&mp->m_sb_lock);
+	return ret;
+}
+
 /*
  * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
  * a delta to a specified field in the in-core superblock.  Simply
@@ -1228,16 +1246,9 @@ xfs_mod_incore_sb_unlocked(
 	case XFS_SBS_ICOUNT:
 	case XFS_SBS_IFREE:
 	case XFS_SBS_FDBLOCKS:
+	case XFS_SBS_FREXTENTS:
 		ASSERT(0);
 		return -EINVAL;
-	case XFS_SBS_FREXTENTS:
-		lcounter = (long long)mp->m_sb.sb_frextents;
-		lcounter += delta;
-		if (lcounter < 0) {
-			return -ENOSPC;
-		}
-		mp->m_sb.sb_frextents = lcounter;
-		return 0;
 	case XFS_SBS_DBLOCKS:
 		lcounter = (long long)mp->m_sb.sb_dblocks;
 		lcounter += delta;
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index ff1d1d5..8970489 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -320,6 +320,8 @@ extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
 				 bool reserved);
+extern int	xfs_mod_frextents(struct xfs_mount *mp, int64_t delta);
+
 extern int	xfs_mount_log_sb(xfs_mount_t *);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern int	xfs_readsb(xfs_mount_t *, int);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index e99f5e5..4e4bc5a 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -235,8 +235,7 @@ xfs_trans_reserve(
 	 * fail if the count would go below zero.
 	 */
 	if (rtextents > 0) {
-		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
-					  -((int64_t)rtextents), rsvd);
+		error = xfs_mod_frextents(tp->t_mountp, -((int64_t)rtextents));
 		if (error) {
 			error = -ENOSPC;
 			goto undo_log;
@@ -562,10 +561,10 @@ xfs_trans_unreserve_and_mod_sb(
 	}
 
 	/* apply remaining deltas */
-	if (rtxdelta != 0) {
-		msbp->msb_field = XFS_SBS_FREXTENTS;
-		msbp->msb_delta = rtxdelta;
-		msbp++;
+	if (rtxdelta) {
+		error = xfs_mod_frextents(mp, rtxdelta);
+		if (error)
+			goto out_undo_ifree;
 	}
 
 	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
@@ -618,12 +617,15 @@ xfs_trans_unreserve_and_mod_sb(
 		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
 			(uint)(msbp - msb), rsvd);
 		if (error)
-			goto out_undo_ifreecount;
+			goto out_undo_frextents;
 	}
 
 	return;
 
-out_undo_ifreecount:
+out_undo_frextents:
+	if (rtxdelta)
+		xfs_mod_frextents(mp, -rtxdelta);
+out_undo_ifree:
 	if (ifreedelta)
 		xfs_mod_ifree(mp, -ifreedelta);
 out_undo_icount:
-- 
2.0.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 6/7] xfs: replace xfs_mod_incore_sb_batched
  2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
                   ` (4 preceding siblings ...)
  2015-02-04 20:54 ` [PATCH 5/7] xfs: introduce xfs_mod_frextents Dave Chinner
@ 2015-02-04 20:54 ` Dave Chinner
  2015-02-05 14:10   ` Brian Foster
  2015-02-04 20:54 ` [PATCH 7/7] xfs: remove xfs_mod_incore_sb API Dave Chinner
  2015-02-05 14:08 ` [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Brian Foster
  7 siblings, 1 reply; 25+ messages in thread
From: Dave Chinner @ 2015-02-04 20:54 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Introduce helper functions for modifying fields in the superblock
into xfs_trans.c, the only caller of xfs_mod_incore_sb_batch().  We
can then use these directly in xfs_trans_unreserve_and_mod_sb() and
so remove another user of the xfs_mode_incore_sb() API without
losing any functionality or scalability of the transaction commit
code..

Based on a patch from Christoph Hellwig.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 fs/xfs/xfs_mount.c |  51 --------------
 fs/xfs/xfs_mount.h |  11 ---
 fs/xfs/xfs_trans.c | 198 ++++++++++++++++++++++++++++++++++-------------------
 3 files changed, 126 insertions(+), 134 deletions(-)

diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 284f528..9499e88 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1354,57 +1354,6 @@ xfs_mod_incore_sb(
 }
 
 /*
- * Change more than one field in the in-core superblock structure at a time.
- *
- * The fields and changes to those fields are specified in the array of
- * xfs_mod_sb structures passed in.  Either all of the specified deltas
- * will be applied or none of them will.  If any modified field dips below 0,
- * then all modifications will be backed out and EINVAL will be returned.
- *
- * Note that this function may not be used for the superblock values that
- * are tracked with the in-memory per-cpu counters - a direct call to
- * xfs_mod_incore_sb is required for these.
- */
-int
-xfs_mod_incore_sb_batch(
-	struct xfs_mount	*mp,
-	xfs_mod_sb_t		*msb,
-	uint			nmsb,
-	int			rsvd)
-{
-	xfs_mod_sb_t		*msbp;
-	int			error = 0;
-
-	/*
-	 * Loop through the array of mod structures and apply each individually.
-	 * If any fail, then back out all those which have already been applied.
-	 * Do all of this within the scope of the m_sb_lock so that all of the
-	 * changes will be atomic.
-	 */
-	spin_lock(&mp->m_sb_lock);
-	for (msbp = msb; msbp < (msb + nmsb); msbp++) {
-		ASSERT(msbp->msb_field < XFS_SBS_ICOUNT ||
-		       msbp->msb_field > XFS_SBS_FDBLOCKS);
-
-		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
-						   msbp->msb_delta, rsvd);
-		if (error)
-			goto unwind;
-	}
-	spin_unlock(&mp->m_sb_lock);
-	return 0;
-
-unwind:
-	while (--msbp >= msb) {
-		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
-						   -msbp->msb_delta, rsvd);
-		ASSERT(error == 0);
-	}
-	spin_unlock(&mp->m_sb_lock);
-	return error;
-}
-
-/*
  * xfs_getsb() is called to obtain the buffer for the superblock.
  * The buffer is returned locked and read in from disk.
  * The buffer should be released with a call to xfs_brelse().
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 8970489..66f28c1 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -249,15 +249,6 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
 }
 
 /*
- * This structure is for use by the xfs_mod_incore_sb_batch() routine.
- * xfs_growfs can specify a few fields which are more than int limit
- */
-typedef struct xfs_mod_sb {
-	xfs_sb_field_t	msb_field;	/* Field to modify, see below */
-	int64_t		msb_delta;	/* Change to make to specified field */
-} xfs_mod_sb_t;
-
-/*
  * Per-ag incore structure, copies of information in agf and agi, to improve the
  * performance of allocation group selection.
  */
@@ -314,8 +305,6 @@ extern int	xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount,
 
 extern void	xfs_unmountfs(xfs_mount_t *);
 extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
-extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
-			uint, int);
 extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 4e4bc5a..220ef2c 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -485,6 +485,54 @@ xfs_trans_apply_sb_deltas(
 				  sizeof(sbp->sb_frextents) - 1);
 }
 
+STATIC int
+xfs_sb_mod8(
+	uint8_t			*field,
+	int8_t			delta)
+{
+	int8_t			counter = *field;
+
+	counter += delta;
+	if (counter < 0) {
+		ASSERT(0);
+		return -EINVAL;
+	}
+	*field = counter;
+	return 0;
+}
+
+STATIC int
+xfs_sb_mod32(
+	uint32_t		*field,
+	int32_t			delta)
+{
+	int32_t			counter = *field;
+
+	counter += delta;
+	if (counter < 0) {
+		ASSERT(0);
+		return -EINVAL;
+	}
+	*field = counter;
+	return 0;
+}
+
+STATIC int
+xfs_sb_mod64(
+	uint64_t		*field,
+	int64_t			delta)
+{
+	int64_t			counter = *field;
+
+	counter += delta;
+	if (counter < 0) {
+		ASSERT(0);
+		return -EINVAL;
+	}
+	*field = counter;
+	return 0;
+}
+
 /*
  * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
  * and apply superblock counter changes to the in-core superblock.  The
@@ -492,13 +540,6 @@ xfs_trans_apply_sb_deltas(
  * applied to the in-core superblock.  The idea is that that has already been
  * done.
  *
- * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
- * However, we have to ensure that we only modify each superblock field only
- * once because the application of the delta values may not be atomic. That can
- * lead to ENOSPC races occurring if we have two separate modifcations of the
- * free space counter to put back the entire reservation and then take away
- * what we used.
- *
  * If we are not logging superblock counters, then the inode allocated/free and
  * used block counts are not updated in the on disk superblock. In this case,
  * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
@@ -506,20 +547,15 @@ xfs_trans_apply_sb_deltas(
  */
 void
 xfs_trans_unreserve_and_mod_sb(
-	xfs_trans_t	*tp)
+	struct xfs_trans	*tp)
 {
-	xfs_mod_sb_t	msb[9];	/* If you add cases, add entries */
-	xfs_mod_sb_t	*msbp;
-	xfs_mount_t	*mp = tp->t_mountp;
-	/* REFERENCED */
-	int		error;
-	bool		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
-	int64_t		blkdelta = 0;
-	int64_t		rtxdelta = 0;
-	int64_t		idelta = 0;
-	int64_t		ifreedelta = 0;
-
-	msbp = msb;
+	struct xfs_mount	*mp = tp->t_mountp;
+	bool			rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
+	int64_t			blkdelta = 0;
+	int64_t			rtxdelta = 0;
+	int64_t			idelta = 0;
+	int64_t			ifreedelta = 0;
+	int			error;
 
 	/* calculate deltas */
 	if (tp->t_blk_res > 0)
@@ -560,72 +596,90 @@ xfs_trans_unreserve_and_mod_sb(
 			goto out_undo_icount;
 	}
 
+	if (rtxdelta == 0 && !(tp->t_flags & XFS_TRANS_SB_DIRTY))
+		return;
+
 	/* apply remaining deltas */
+	spin_lock(&mp->m_sb_lock);
 	if (rtxdelta) {
-		error = xfs_mod_frextents(mp, rtxdelta);
+		error = xfs_sb_mod64(&mp->m_sb.sb_frextents, rtxdelta);
 		if (error)
 			goto out_undo_ifree;
 	}
 
-	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
-		if (tp->t_dblocks_delta != 0) {
-			msbp->msb_field = XFS_SBS_DBLOCKS;
-			msbp->msb_delta = tp->t_dblocks_delta;
-			msbp++;
-		}
-		if (tp->t_agcount_delta != 0) {
-			msbp->msb_field = XFS_SBS_AGCOUNT;
-			msbp->msb_delta = tp->t_agcount_delta;
-			msbp++;
-		}
-		if (tp->t_imaxpct_delta != 0) {
-			msbp->msb_field = XFS_SBS_IMAX_PCT;
-			msbp->msb_delta = tp->t_imaxpct_delta;
-			msbp++;
-		}
-		if (tp->t_rextsize_delta != 0) {
-			msbp->msb_field = XFS_SBS_REXTSIZE;
-			msbp->msb_delta = tp->t_rextsize_delta;
-			msbp++;
-		}
-		if (tp->t_rbmblocks_delta != 0) {
-			msbp->msb_field = XFS_SBS_RBMBLOCKS;
-			msbp->msb_delta = tp->t_rbmblocks_delta;
-			msbp++;
-		}
-		if (tp->t_rblocks_delta != 0) {
-			msbp->msb_field = XFS_SBS_RBLOCKS;
-			msbp->msb_delta = tp->t_rblocks_delta;
-			msbp++;
-		}
-		if (tp->t_rextents_delta != 0) {
-			msbp->msb_field = XFS_SBS_REXTENTS;
-			msbp->msb_delta = tp->t_rextents_delta;
-			msbp++;
-		}
-		if (tp->t_rextslog_delta != 0) {
-			msbp->msb_field = XFS_SBS_REXTSLOG;
-			msbp->msb_delta = tp->t_rextslog_delta;
-			msbp++;
-		}
-	}
-
-	/*
-	 * If we need to change anything, do it.
-	 */
-	if (msbp > msb) {
-		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
-			(uint)(msbp - msb), rsvd);
+	if (tp->t_dblocks_delta != 0) {
+		error = xfs_sb_mod64(&mp->m_sb.sb_dblocks, tp->t_dblocks_delta);
 		if (error)
 			goto out_undo_frextents;
 	}
-
+	if (tp->t_agcount_delta != 0) {
+		error = xfs_sb_mod32(&mp->m_sb.sb_agcount, tp->t_agcount_delta);
+		if (error)
+			goto out_undo_dblocks;
+	}
+	if (tp->t_imaxpct_delta != 0) {
+		error = xfs_sb_mod8(&mp->m_sb.sb_imax_pct, tp->t_imaxpct_delta);
+		if (error)
+			goto out_undo_agcount;
+	}
+	if (tp->t_rextsize_delta != 0) {
+		error = xfs_sb_mod32(&mp->m_sb.sb_rextsize,
+				     tp->t_rextsize_delta);
+		if (error)
+			goto out_undo_imaxpct;
+	}
+	if (tp->t_rbmblocks_delta != 0) {
+		error = xfs_sb_mod32(&mp->m_sb.sb_rbmblocks,
+				     tp->t_rbmblocks_delta);
+		if (error)
+			goto out_undo_rextsize;
+	}
+	if (tp->t_rblocks_delta != 0) {
+		error = xfs_sb_mod64(&mp->m_sb.sb_rblocks, tp->t_rblocks_delta);
+		if (error)
+			goto out_undo_rbmblocks;
+	}
+	if (tp->t_rextents_delta != 0) {
+		error = xfs_sb_mod64(&mp->m_sb.sb_rextents,
+				     tp->t_rextents_delta);
+		if (error)
+			goto out_undo_rblocks;
+	}
+	if (tp->t_rextslog_delta != 0) {
+		error = xfs_sb_mod8(&mp->m_sb.sb_rextslog,
+				     tp->t_rextslog_delta);
+		if (error)
+			goto out_undo_rextents;
+	}
+	spin_unlock(&mp->m_sb_lock);
 	return;
 
+out_undo_rextents:
+	if (tp->t_rextents_delta)
+		xfs_sb_mod64(&mp->m_sb.sb_rextents, -tp->t_rextents_delta);
+out_undo_rblocks:
+	if (tp->t_rblocks_delta)
+		xfs_sb_mod64(&mp->m_sb.sb_rblocks, -tp->t_rblocks_delta);
+out_undo_rbmblocks:
+	if (tp->t_rbmblocks_delta)
+		xfs_sb_mod32(&mp->m_sb.sb_rbmblocks, -tp->t_rbmblocks_delta);
+out_undo_rextsize:
+	if (tp->t_rextsize_delta)
+		xfs_sb_mod32(&mp->m_sb.sb_rextsize, -tp->t_rextsize_delta);
+out_undo_imaxpct:
+	if (tp->t_rextsize_delta)
+		xfs_sb_mod8(&mp->m_sb.sb_imax_pct, -tp->t_imaxpct_delta);
+out_undo_agcount:
+	if (tp->t_agcount_delta)
+		xfs_sb_mod32(&mp->m_sb.sb_agcount, -tp->t_agcount_delta);
+out_undo_dblocks:
+	if (tp->t_dblocks_delta)
+		xfs_sb_mod64(&mp->m_sb.sb_dblocks, -tp->t_dblocks_delta);
 out_undo_frextents:
 	if (rtxdelta)
-		xfs_mod_frextents(mp, -rtxdelta);
+		xfs_sb_mod64(&mp->m_sb.sb_frextents, -rtxdelta);
 out_undo_ifree:
+	spin_unlock(&mp->m_sb_lock);
 	if (ifreedelta)
 		xfs_mod_ifree(mp, -ifreedelta);
 out_undo_icount:
-- 
2.0.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 7/7] xfs: remove xfs_mod_incore_sb API
  2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
                   ` (5 preceding siblings ...)
  2015-02-04 20:54 ` [PATCH 6/7] xfs: replace xfs_mod_incore_sb_batched Dave Chinner
@ 2015-02-04 20:54 ` Dave Chinner
  2015-02-05 14:10   ` Brian Foster
  2015-02-05 14:08 ` [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Brian Foster
  7 siblings, 1 reply; 25+ messages in thread
From: Dave Chinner @ 2015-02-04 20:54 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Now that there are no users of the bitfield based incore superblock
modification API, just remove the whole damn lot of it, including
all the bitfield definitions. This finally removes a lot of cruft
that has been around for a long time.

Credit goes to Christoph Hellwig for providing a great patch
connecting all the dots to enale us to do this. This patch is
derived from that work.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 fs/xfs/libxfs/xfs_format.h |  62 ---------------------
 fs/xfs/xfs_fsops.c         |   4 --
 fs/xfs/xfs_mount.c         | 136 ---------------------------------------------
 fs/xfs/xfs_mount.h         |   3 +-
 4 files changed, 1 insertion(+), 204 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 8eb7189..4daaa66 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -264,68 +264,6 @@ typedef struct xfs_dsb {
 	/* must be padded to 64 bit alignment */
 } xfs_dsb_t;
 
-/*
- * Sequence number values for the fields.
- */
-typedef enum {
-	XFS_SBS_MAGICNUM, XFS_SBS_BLOCKSIZE, XFS_SBS_DBLOCKS, XFS_SBS_RBLOCKS,
-	XFS_SBS_REXTENTS, XFS_SBS_UUID, XFS_SBS_LOGSTART, XFS_SBS_ROOTINO,
-	XFS_SBS_RBMINO, XFS_SBS_RSUMINO, XFS_SBS_REXTSIZE, XFS_SBS_AGBLOCKS,
-	XFS_SBS_AGCOUNT, XFS_SBS_RBMBLOCKS, XFS_SBS_LOGBLOCKS,
-	XFS_SBS_VERSIONNUM, XFS_SBS_SECTSIZE, XFS_SBS_INODESIZE,
-	XFS_SBS_INOPBLOCK, XFS_SBS_FNAME, XFS_SBS_BLOCKLOG,
-	XFS_SBS_SECTLOG, XFS_SBS_INODELOG, XFS_SBS_INOPBLOG, XFS_SBS_AGBLKLOG,
-	XFS_SBS_REXTSLOG, XFS_SBS_INPROGRESS, XFS_SBS_IMAX_PCT, XFS_SBS_ICOUNT,
-	XFS_SBS_IFREE, XFS_SBS_FDBLOCKS, XFS_SBS_FREXTENTS, XFS_SBS_UQUOTINO,
-	XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
-	XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
-	XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
-	XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_FEATURES_COMPAT,
-	XFS_SBS_FEATURES_RO_COMPAT, XFS_SBS_FEATURES_INCOMPAT,
-	XFS_SBS_FEATURES_LOG_INCOMPAT, XFS_SBS_CRC, XFS_SBS_PAD,
-	XFS_SBS_PQUOTINO, XFS_SBS_LSN,
-	XFS_SBS_FIELDCOUNT
-} xfs_sb_field_t;
-
-/*
- * Mask values, defined based on the xfs_sb_field_t values.
- * Only define the ones we're using.
- */
-#define	XFS_SB_MVAL(x)		(1LL << XFS_SBS_ ## x)
-#define	XFS_SB_UUID		XFS_SB_MVAL(UUID)
-#define	XFS_SB_FNAME		XFS_SB_MVAL(FNAME)
-#define	XFS_SB_ROOTINO		XFS_SB_MVAL(ROOTINO)
-#define	XFS_SB_RBMINO		XFS_SB_MVAL(RBMINO)
-#define	XFS_SB_RSUMINO		XFS_SB_MVAL(RSUMINO)
-#define	XFS_SB_VERSIONNUM	XFS_SB_MVAL(VERSIONNUM)
-#define XFS_SB_UQUOTINO		XFS_SB_MVAL(UQUOTINO)
-#define XFS_SB_GQUOTINO		XFS_SB_MVAL(GQUOTINO)
-#define XFS_SB_QFLAGS		XFS_SB_MVAL(QFLAGS)
-#define XFS_SB_SHARED_VN	XFS_SB_MVAL(SHARED_VN)
-#define XFS_SB_UNIT		XFS_SB_MVAL(UNIT)
-#define XFS_SB_WIDTH		XFS_SB_MVAL(WIDTH)
-#define XFS_SB_ICOUNT		XFS_SB_MVAL(ICOUNT)
-#define XFS_SB_IFREE		XFS_SB_MVAL(IFREE)
-#define XFS_SB_FDBLOCKS		XFS_SB_MVAL(FDBLOCKS)
-#define XFS_SB_FEATURES2	(XFS_SB_MVAL(FEATURES2) | \
-				 XFS_SB_MVAL(BAD_FEATURES2))
-#define XFS_SB_FEATURES_COMPAT	XFS_SB_MVAL(FEATURES_COMPAT)
-#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT)
-#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT)
-#define XFS_SB_FEATURES_LOG_INCOMPAT XFS_SB_MVAL(FEATURES_LOG_INCOMPAT)
-#define XFS_SB_CRC		XFS_SB_MVAL(CRC)
-#define XFS_SB_PQUOTINO		XFS_SB_MVAL(PQUOTINO)
-#define	XFS_SB_NUM_BITS		((int)XFS_SBS_FIELDCOUNT)
-#define	XFS_SB_ALL_BITS		((1LL << XFS_SB_NUM_BITS) - 1)
-#define	XFS_SB_MOD_BITS		\
-	(XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
-	 XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
-	 XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
-	 XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \
-	 XFS_SB_FEATURES_COMPAT | XFS_SB_FEATURES_RO_COMPAT | \
-	 XFS_SB_FEATURES_INCOMPAT | XFS_SB_FEATURES_LOG_INCOMPAT | \
-	 XFS_SB_PQUOTINO)
-
 
 /*
  * Misc. Flags - warning - these will be cleared by xfs_repair unless
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index a45c82b4..6c248bf 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -686,10 +686,6 @@ xfs_reserve_blocks(
 	 * what to do. This means that the amount of free space can
 	 * change while we do this, so we need to retry if we end up
 	 * trying to reserve more space than is available.
-	 *
-	 * We also use the xfs_mod_incore_sb() interface so that we
-	 * don't have to care about whether per cpu counter are
-	 * enabled, disabled or even compiled in....
 	 */
 retry:
 	spin_lock(&mp->m_sb_lock);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 9499e88..6e6bc40 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1218,142 +1218,6 @@ xfs_mod_frextents(
 }
 
 /*
- * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
- * a delta to a specified field in the in-core superblock.  Simply
- * switch on the field indicated and apply the delta to that field.
- * Fields are not allowed to dip below zero, so if the delta would
- * do this do not apply it and return EINVAL.
- *
- * The m_sb_lock must be held when this routine is called.
- */
-STATIC int
-xfs_mod_incore_sb_unlocked(
-	xfs_mount_t	*mp,
-	xfs_sb_field_t	field,
-	int64_t		delta,
-	int		rsvd)
-{
-	int		scounter;	/* short counter for 32 bit fields */
-	long long	lcounter;	/* long counter for 64 bit fields */
-
-	/*
-	 * With the in-core superblock spin lock held, switch
-	 * on the indicated field.  Apply the delta to the
-	 * proper field.  If the fields value would dip below
-	 * 0, then do not apply the delta and return EINVAL.
-	 */
-	switch (field) {
-	case XFS_SBS_ICOUNT:
-	case XFS_SBS_IFREE:
-	case XFS_SBS_FDBLOCKS:
-	case XFS_SBS_FREXTENTS:
-		ASSERT(0);
-		return -EINVAL;
-	case XFS_SBS_DBLOCKS:
-		lcounter = (long long)mp->m_sb.sb_dblocks;
-		lcounter += delta;
-		if (lcounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_dblocks = lcounter;
-		return 0;
-	case XFS_SBS_AGCOUNT:
-		scounter = mp->m_sb.sb_agcount;
-		scounter += delta;
-		if (scounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_agcount = scounter;
-		return 0;
-	case XFS_SBS_IMAX_PCT:
-		scounter = mp->m_sb.sb_imax_pct;
-		scounter += delta;
-		if (scounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_imax_pct = scounter;
-		return 0;
-	case XFS_SBS_REXTSIZE:
-		scounter = mp->m_sb.sb_rextsize;
-		scounter += delta;
-		if (scounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_rextsize = scounter;
-		return 0;
-	case XFS_SBS_RBMBLOCKS:
-		scounter = mp->m_sb.sb_rbmblocks;
-		scounter += delta;
-		if (scounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_rbmblocks = scounter;
-		return 0;
-	case XFS_SBS_RBLOCKS:
-		lcounter = (long long)mp->m_sb.sb_rblocks;
-		lcounter += delta;
-		if (lcounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_rblocks = lcounter;
-		return 0;
-	case XFS_SBS_REXTENTS:
-		lcounter = (long long)mp->m_sb.sb_rextents;
-		lcounter += delta;
-		if (lcounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_rextents = lcounter;
-		return 0;
-	case XFS_SBS_REXTSLOG:
-		scounter = mp->m_sb.sb_rextslog;
-		scounter += delta;
-		if (scounter < 0) {
-			ASSERT(0);
-			return -EINVAL;
-		}
-		mp->m_sb.sb_rextslog = scounter;
-		return 0;
-	default:
-		ASSERT(0);
-		return -EINVAL;
-	}
-}
-
-/*
- * xfs_mod_incore_sb() is used to change a field in the in-core
- * superblock structure by the specified delta.  This modification
- * is protected by the m_sb_lock.  Just use the xfs_mod_incore_sb_unlocked()
- * routine to do the work.
- */
-int
-xfs_mod_incore_sb(
-	struct xfs_mount	*mp,
-	xfs_sb_field_t		field,
-	int64_t			delta,
-	int			rsvd)
-{
-	int			status;
-
-#ifdef HAVE_PERCPU_SB
-	ASSERT(field < XFS_SBS_IFREE || field > XFS_SBS_FDBLOCKS);
-#endif
-
-	spin_lock(&mp->m_sb_lock);
-	status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-	spin_unlock(&mp->m_sb_lock);
-
-	return status;
-}
-
-/*
  * xfs_getsb() is called to obtain the buffer for the superblock.
  * The buffer is returned locked and read in from disk.
  * The buffer should be released with a call to xfs_brelse().
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 66f28c1..616e1ba 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -302,9 +302,8 @@ extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
 extern int	xfs_mountfs(xfs_mount_t *mp);
 extern int	xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount,
 				     xfs_agnumber_t *maxagi);
-
 extern void	xfs_unmountfs(xfs_mount_t *);
-extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
+
 extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
 extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
-- 
2.0.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/7 V2] xfs: use generic percpu counters for icsb
  2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
                   ` (6 preceding siblings ...)
  2015-02-04 20:54 ` [PATCH 7/7] xfs: remove xfs_mod_incore_sb API Dave Chinner
@ 2015-02-05 14:08 ` Brian Foster
  2015-02-05 22:18   ` Dave Chinner
  7 siblings, 1 reply; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:08 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 07:54:02AM +1100, Dave Chinner wrote:
> Hi folks,
> 
> This is the second version of the generic per-cpu counter rework
> patch series. The first version can be found here:
> 
> http://oss.sgi.com/archives/xfs/2015-02/msg00000.html
> 
> New in V2:
> 
> - drop the moving of the struct xfs_sb to xfs_super.h
> - fixed all the little things that Christoph and Brian noted.
> - keep the per-cpu counters in the struct xfs_mount and keep the
>   functions to sync them with the struct xfs_sb values when read
>   from disk or written to disk.
> - integrated Christoph Hellwig's additional cleanup patch. This was
>   done by:
> 	- intergating xfs_mod_XXX factoring into the relevant percpu
> 	  counter conversion patch
> 	- separating out xfs_mod_frextents into it's won patch
> 	- separating out the replacement of
> 	  xfs_mod_incore_sb_batched
> 	- doing all the now unused API removal in a separate patch
> 
> The series passes xfstests without regressions, and no scalability
> issues have been seen in my performance tests on a 16p VM. SGI - you
> still need to test this, though. :)
> 
> Thoughts, comments?
> 

All in all this looks pretty good to me save a couple notes pointed out
in the patches. In a quick test, this handles the imaxct overshoot
problem Eric noted much better than the current implementation. That
said, it's still not precise.

My understanding is that's fine, but I wonder if we want to tack on a
variant of Eric's original patch as well so when we still do overshoot
imaxpct (albeit by much less than before: I reproduce an overshoot of
<100 inodes vs several thousand) we at least report an accurate inode
count. Thoughts?

Brian

> -Dave.
> 
> PS: diffstat of the series is now:
> 
>  fs/xfs/libxfs/xfs_bmap.c   |  40 +--
>  fs/xfs/libxfs/xfs_format.h |  62 ----
>  fs/xfs/libxfs/xfs_ialloc.c |   6 +-
>  fs/xfs/libxfs/xfs_sb.c     |  12 +-
>  fs/xfs/xfs_fsops.c         |  20 +-
>  fs/xfs/xfs_iomap.c         |   3 +-
>  fs/xfs/xfs_linux.h         |   9 -
>  fs/xfs/xfs_log_recover.c   |   4 +-
>  fs/xfs/xfs_mount.c         | 919 ++++++-----------------------------------------
>  fs/xfs/xfs_mount.h         |  95 +----
>  fs/xfs/xfs_super.c         | 103 ++++--
>  fs/xfs/xfs_super.h         |   2 +
>  fs/xfs/xfs_trans.c         | 234 +++++++-----
>  13 files changed, 381 insertions(+), 1128 deletions(-)
> 
> So we have a net reduction of roughly 750 lines of code.  When
> combined with the changes to the superblock logging that has already
> been committed, we have reduced the superblock modification code by
> close to 1000 lines compared to 3.19...
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/7] xfs: use generic percpu counters for inode counter
  2015-02-04 20:54 ` [PATCH 1/7] xfs: use generic percpu counters for inode counter Dave Chinner
@ 2015-02-05 14:09   ` Brian Foster
  2015-02-23 20:55   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:09 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 07:54:03AM +1100, Dave Chinner wrote:
> XFS has hand-rolled per-cpu counters for the superblock since before
> there was any generic implementation. There are some warts around
> the  use of them for the inode counter as the hand rolled counter is
> designed to be accurate at zero, but has no specific accurracy at
> any other value. This design causes problems for the maximum inode
> count threshold enforcement, as there is no trigger that balances
> the counters as they get close tothe maximum threshold.
> 
> Instead of designing new triggers for balancing, just replace the
> handrolled per-cpu counter with a generic counter.  This enables us
> to update the counter through the normal superblock modification
> funtions, but rather than do that we add a xfs_mod_icount() helper
> function (from Christoph Hellwig) and keep the percpu counter
> outside the superblock in the struct xfs_mount.
> 
> This means we still need to initialise the per-cpu counter
> specifically when we read the superblock, and vice versa when we
> log/write it, but it does mean that we don't need to change any
> other code.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
>  fs/xfs/libxfs/xfs_ialloc.c |  6 ++--
>  fs/xfs/libxfs/xfs_sb.c     |  2 ++
>  fs/xfs/xfs_fsops.c         |  3 +-
>  fs/xfs/xfs_mount.c         | 76 +++++++++++++++++++++-------------------------
>  fs/xfs/xfs_mount.h         |  7 +++--
>  fs/xfs/xfs_super.c         |  7 +++--
>  fs/xfs/xfs_trans.c         |  5 ++-
>  7 files changed, 54 insertions(+), 52 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
> index 116ef1d..5b4ba9f 100644
> --- a/fs/xfs/libxfs/xfs_ialloc.c
> +++ b/fs/xfs/libxfs/xfs_ialloc.c
> @@ -376,7 +376,8 @@ xfs_ialloc_ag_alloc(
>  	 */
>  	newlen = args.mp->m_ialloc_inos;
>  	if (args.mp->m_maxicount &&
> -	    args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount)
> +	    percpu_counter_read(&args.mp->m_icount) + newlen >
> +							args.mp->m_maxicount)
>  		return -ENOSPC;
>  	args.minlen = args.maxlen = args.mp->m_ialloc_blks;
>  	/*
> @@ -1340,7 +1341,8 @@ xfs_dialloc(
>  	 * inode.
>  	 */
>  	if (mp->m_maxicount &&
> -	    mp->m_sb.sb_icount + mp->m_ialloc_inos > mp->m_maxicount) {
> +	    percpu_counter_read(&mp->m_icount) + mp->m_ialloc_inos >
> +							mp->m_maxicount) {
>  		noroom = 1;
>  		okalloc = 0;
>  	}
> diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
> index b0a5fe9..017cb2f 100644
> --- a/fs/xfs/libxfs/xfs_sb.c
> +++ b/fs/xfs/libxfs/xfs_sb.c
> @@ -771,6 +771,8 @@ xfs_log_sb(
>  	struct xfs_mount	*mp = tp->t_mountp;
>  	struct xfs_buf		*bp = xfs_trans_getsb(tp, mp, 0);
>  
> +	mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
> +
>  	xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);
>  	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
>  	xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb));
> diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> index f711452..e1470f2 100644
> --- a/fs/xfs/xfs_fsops.c
> +++ b/fs/xfs/xfs_fsops.c
> @@ -631,11 +631,12 @@ xfs_fs_counts(
>  	xfs_fsop_counts_t	*cnt)
>  {
>  	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
> +	cnt->allocino = percpu_counter_read_positive(&mp->m_icount);
> +
>  	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;
>  	cnt->freeino = mp->m_sb.sb_ifree;
> -	cnt->allocino = mp->m_sb.sb_icount;
>  	spin_unlock(&mp->m_sb_lock);
>  	return 0;
>  }
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 4fa80e6..702ea6a 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -1099,6 +1099,21 @@ xfs_log_sbcount(xfs_mount_t *mp)
>  	return xfs_sync_sb(mp, true);
>  }
>  
> +int
> +xfs_mod_icount(
> +	struct xfs_mount	*mp,
> +	int64_t			delta)
> +{
> +	/* deltas are +/-64, hence the large batch size of 128. */
> +	__percpu_counter_add(&mp->m_icount, delta, 128);
> +	if (percpu_counter_compare(&mp->m_icount, 0) < 0) {
> +		ASSERT(0);
> +		percpu_counter_add(&mp->m_icount, -delta);
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +
>  /*
>   * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
>   * a delta to a specified field in the in-core superblock.  Simply
> @@ -1127,14 +1142,8 @@ xfs_mod_incore_sb_unlocked(
>  	 */
>  	switch (field) {
>  	case XFS_SBS_ICOUNT:
> -		lcounter = (long long)mp->m_sb.sb_icount;
> -		lcounter += delta;
> -		if (lcounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_icount = lcounter;
> -		return 0;
> +		ASSERT(0);
> +		return -ENOSPC;
>  	case XFS_SBS_IFREE:
>  		lcounter = (long long)mp->m_sb.sb_ifree;
>  		lcounter += delta;
> @@ -1288,8 +1297,9 @@ xfs_mod_incore_sb(
>  	int			status;
>  
>  #ifdef HAVE_PERCPU_SB
> -	ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS);
> +	ASSERT(field < XFS_SBS_IFREE || field > XFS_SBS_FDBLOCKS);
>  #endif

Not really sure why the above changes, since XFS_SBS_IFREE >
XFS_SBS_ICOUNT. This goes away, so it doesn't matter. :)

Reviewed-by: Brian Foster <bfoster@redhat.com>

> +
>  	spin_lock(&mp->m_sb_lock);
>  	status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
>  	spin_unlock(&mp->m_sb_lock);
> @@ -1492,7 +1502,6 @@ xfs_icsb_cpu_notify(
>  	case CPU_ONLINE:
>  	case CPU_ONLINE_FROZEN:
>  		xfs_icsb_lock(mp);
> -		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
>  		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
>  		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
>  		xfs_icsb_unlock(mp);
> @@ -1504,17 +1513,14 @@ xfs_icsb_cpu_notify(
>  		 * re-enable the counters. */
>  		xfs_icsb_lock(mp);
>  		spin_lock(&mp->m_sb_lock);
> -		xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
>  		xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
>  		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
>  
> -		mp->m_sb.sb_icount += cntp->icsb_icount;
>  		mp->m_sb.sb_ifree += cntp->icsb_ifree;
>  		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
>  
>  		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
>  
> -		xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
>  		xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
>  		xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
>  		spin_unlock(&mp->m_sb_lock);
> @@ -1531,11 +1537,18 @@ xfs_icsb_init_counters(
>  	xfs_mount_t	*mp)
>  {
>  	xfs_icsb_cnts_t *cntp;
> +	int		error;
>  	int		i;
>  
> +	error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
> +	if (error)
> +		return error;
> +
>  	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
> -	if (mp->m_sb_cnts == NULL)
> +	if (!mp->m_sb_cnts) {
> +		percpu_counter_destroy(&mp->m_icount);
>  		return -ENOMEM;
> +	}
>  
>  	for_each_online_cpu(i) {
>  		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
> @@ -1563,13 +1576,14 @@ void
>  xfs_icsb_reinit_counters(
>  	xfs_mount_t	*mp)
>  {
> +	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
> +
>  	xfs_icsb_lock(mp);
>  	/*
>  	 * start with all counters disabled so that the
>  	 * initial balance kicks us off correctly
>  	 */
>  	mp->m_icsb_counters = -1;
> -	xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
>  	xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
>  	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
>  	xfs_icsb_unlock(mp);
> @@ -1583,6 +1597,9 @@ xfs_icsb_destroy_counters(
>  		unregister_hotcpu_notifier(&mp->m_icsb_notifier);
>  		free_percpu(mp->m_sb_cnts);
>  	}
> +
> +	percpu_counter_destroy(&mp->m_icount);
> +
>  	mutex_destroy(&mp->m_icsb_mutex);
>  }
>  
> @@ -1645,7 +1662,6 @@ xfs_icsb_count(
>  
>  	for_each_online_cpu(i) {
>  		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
> -		cnt->icsb_icount += cntp->icsb_icount;
>  		cnt->icsb_ifree += cntp->icsb_ifree;
>  		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
>  	}
> @@ -1659,7 +1675,7 @@ xfs_icsb_counter_disabled(
>  	xfs_mount_t	*mp,
>  	xfs_sb_field_t	field)
>  {
> -	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
> +	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
>  	return test_bit(field, &mp->m_icsb_counters);
>  }
>  
> @@ -1670,7 +1686,7 @@ xfs_icsb_disable_counter(
>  {
>  	xfs_icsb_cnts_t	cnt;
>  
> -	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
> +	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
>  
>  	/*
>  	 * If we are already disabled, then there is nothing to do
> @@ -1689,9 +1705,6 @@ xfs_icsb_disable_counter(
>  
>  		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
>  		switch(field) {
> -		case XFS_SBS_ICOUNT:
> -			mp->m_sb.sb_icount = cnt.icsb_icount;
> -			break;
>  		case XFS_SBS_IFREE:
>  			mp->m_sb.sb_ifree = cnt.icsb_ifree;
>  			break;
> @@ -1716,15 +1729,12 @@ xfs_icsb_enable_counter(
>  	xfs_icsb_cnts_t	*cntp;
>  	int		i;
>  
> -	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
> +	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
>  
>  	xfs_icsb_lock_all_counters(mp);
>  	for_each_online_cpu(i) {
>  		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
>  		switch (field) {
> -		case XFS_SBS_ICOUNT:
> -			cntp->icsb_icount = count + resid;
> -			break;
>  		case XFS_SBS_IFREE:
>  			cntp->icsb_ifree = count + resid;
>  			break;
> @@ -1750,8 +1760,6 @@ xfs_icsb_sync_counters_locked(
>  
>  	xfs_icsb_count(mp, &cnt, flags);
>  
> -	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
> -		mp->m_sb.sb_icount = cnt.icsb_icount;
>  	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
>  		mp->m_sb.sb_ifree = cnt.icsb_ifree;
>  	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
> @@ -1805,12 +1813,6 @@ xfs_icsb_balance_counter_locked(
>  
>  	/* update counters  - first CPU gets residual*/
>  	switch (field) {
> -	case XFS_SBS_ICOUNT:
> -		count = mp->m_sb.sb_icount;
> -		resid = do_div(count, weight);
> -		if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
> -			return;
> -		break;
>  	case XFS_SBS_IFREE:
>  		count = mp->m_sb.sb_ifree;
>  		resid = do_div(count, weight);
> @@ -1871,14 +1873,6 @@ again:
>  	}
>  
>  	switch (field) {
> -	case XFS_SBS_ICOUNT:
> -		lcounter = icsbp->icsb_icount;
> -		lcounter += delta;
> -		if (unlikely(lcounter < 0))
> -			goto balance_counter;
> -		icsbp->icsb_icount = lcounter;
> -		break;
> -
>  	case XFS_SBS_IFREE:
>  		lcounter = icsbp->icsb_ifree;
>  		lcounter += delta;
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index a5b2ff8..457c6e3 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -41,7 +41,6 @@ struct xfs_da_geometry;
>  typedef struct xfs_icsb_cnts {
>  	uint64_t	icsb_fdblocks;
>  	uint64_t	icsb_ifree;
> -	uint64_t	icsb_icount;
>  	unsigned long	icsb_flags;
>  } xfs_icsb_cnts_t;
>  
> @@ -81,8 +80,11 @@ typedef struct xfs_mount {
>  	struct super_block	*m_super;
>  	xfs_tid_t		m_tid;		/* next unused tid for fs */
>  	struct xfs_ail		*m_ail;		/* fs active log item list */
> -	xfs_sb_t		m_sb;		/* copy of fs superblock */
> +
> +	struct xfs_sb		m_sb;		/* copy of fs superblock */
>  	spinlock_t		m_sb_lock;	/* sb counter lock */
> +	struct percpu_counter	m_icount;	/* allocated inodes counter */
> +
>  	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
>  	char			*m_fsname;	/* filesystem name */
>  	int			m_fsname_len;	/* strlen of fs name */
> @@ -377,6 +379,7 @@ extern void	xfs_unmountfs(xfs_mount_t *);
>  extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
>  extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
>  			uint, int);
> +extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mount_log_sb(xfs_mount_t *);
>  extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
>  extern int	xfs_readsb(xfs_mount_t *, int);
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index 40d2ac5..87e169f 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -1087,6 +1087,7 @@ xfs_fs_statfs(
>  	xfs_sb_t		*sbp = &mp->m_sb;
>  	struct xfs_inode	*ip = XFS_I(dentry->d_inode);
>  	__uint64_t		fakeinos, id;
> +	__uint64_t		icount;
>  	xfs_extlen_t		lsize;
>  	__int64_t		ffree;
>  
> @@ -1098,6 +1099,7 @@ xfs_fs_statfs(
>  	statp->f_fsid.val[1] = (u32)(id >> 32);
>  
>  	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
> +	icount = percpu_counter_sum(&mp->m_icount);
>  
>  	spin_lock(&mp->m_sb_lock);
>  	statp->f_bsize = sbp->sb_blocksize;
> @@ -1106,15 +1108,14 @@ xfs_fs_statfs(
>  	statp->f_bfree = statp->f_bavail =
>  				sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
>  	fakeinos = statp->f_bfree << sbp->sb_inopblog;
> -	statp->f_files =
> -	    MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
> +	statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
>  	if (mp->m_maxicount)
>  		statp->f_files = min_t(typeof(statp->f_files),
>  					statp->f_files,
>  					mp->m_maxicount);
>  
>  	/* make sure statp->f_ffree does not underflow */
> -	ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
> +	ffree = statp->f_files - (icount - sbp->sb_ifree);
>  	statp->f_ffree = max_t(__int64_t, ffree, 0);
>  
>  	spin_unlock(&mp->m_sb_lock);
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index eb90cd5..9bc742b 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -554,8 +554,7 @@ xfs_trans_unreserve_and_mod_sb(
>  	}
>  
>  	if (idelta) {
> -		error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT,
> -						 idelta, rsvd);
> +		error = xfs_mod_icount(mp, idelta);
>  		if (error)
>  			goto out_undo_fdblocks;
>  	}
> @@ -634,7 +633,7 @@ out_undo_ifreecount:
>  		xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
>  out_undo_icount:
>  	if (idelta)
> -		xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd);
> +		xfs_mod_icount(mp, -idelta);
>  out_undo_fdblocks:
>  	if (blkdelta)
>  		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
> -- 
> 2.0.0
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/7] xfs: use generic percpu counters for free inode counter
  2015-02-04 20:54 ` [PATCH 2/7] xfs: use generic percpu counters for free " Dave Chinner
@ 2015-02-05 14:10   ` Brian Foster
  2015-02-23 20:56   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:10 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 07:54:04AM +1100, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> XFS has hand-rolled per-cpu counters for the superblock since before
> there was any generic implementation. The free inode counter is not
> used for any limit enforcement - the per-AG free inode counters are
> used during allocation to determine if there are inode available for
> allocation.
> 
> Hence we don't need any of the complexity of the hand-rolled
> counters and we can simply replace them with generic per-cpu
> counters similar to the inode counter.
> 
> This version introduces a xfs_mod_ifree() helper function from
> Christoph Hellwig.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_sb.c |  1 +
>  fs/xfs/xfs_fsops.c     |  2 +-
>  fs/xfs/xfs_mount.c     | 76 ++++++++++++++++++++++----------------------------
>  fs/xfs/xfs_mount.h     |  2 ++
>  fs/xfs/xfs_super.c     |  4 ++-
>  fs/xfs/xfs_trans.c     |  5 ++--
>  6 files changed, 42 insertions(+), 48 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
> index 017cb2f..b66aeab 100644
> --- a/fs/xfs/libxfs/xfs_sb.c
> +++ b/fs/xfs/libxfs/xfs_sb.c
> @@ -772,6 +772,7 @@ xfs_log_sb(
>  	struct xfs_buf		*bp = xfs_trans_getsb(tp, mp, 0);
>  
>  	mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
> +	mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
>  
>  	xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);
>  	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
> diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> index e1470f2..fa74d03 100644
> --- a/fs/xfs/xfs_fsops.c
> +++ b/fs/xfs/xfs_fsops.c
> @@ -632,11 +632,11 @@ 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);
>  
>  	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;
> -	cnt->freeino = mp->m_sb.sb_ifree;
>  	spin_unlock(&mp->m_sb_lock);
>  	return 0;
>  }
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 702ea6a..650e8f1 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -1114,6 +1114,20 @@ xfs_mod_icount(
>  	return 0;
>  }
>  
> +
> +int
> +xfs_mod_ifree(
> +	struct xfs_mount	*mp,
> +	int64_t			delta)
> +{
> +	percpu_counter_add(&mp->m_ifree, delta);
> +	if (percpu_counter_compare(&mp->m_ifree, 0) < 0) {
> +		ASSERT(0);
> +		percpu_counter_add(&mp->m_ifree, -delta);
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
>  /*
>   * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
>   * a delta to a specified field in the in-core superblock.  Simply
> @@ -1142,17 +1156,9 @@ xfs_mod_incore_sb_unlocked(
>  	 */
>  	switch (field) {
>  	case XFS_SBS_ICOUNT:
> -		ASSERT(0);
> -		return -ENOSPC;
>  	case XFS_SBS_IFREE:
> -		lcounter = (long long)mp->m_sb.sb_ifree;
> -		lcounter += delta;
> -		if (lcounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_ifree = lcounter;
> -		return 0;
> +		ASSERT(0);
> +		return -EINVAL;
>  	case XFS_SBS_FDBLOCKS:
>  		lcounter = (long long)
>  			mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> @@ -1502,7 +1508,6 @@ xfs_icsb_cpu_notify(
>  	case CPU_ONLINE:
>  	case CPU_ONLINE_FROZEN:
>  		xfs_icsb_lock(mp);
> -		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
>  		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
>  		xfs_icsb_unlock(mp);
>  		break;
> @@ -1513,15 +1518,12 @@ xfs_icsb_cpu_notify(
>  		 * re-enable the counters. */
>  		xfs_icsb_lock(mp);
>  		spin_lock(&mp->m_sb_lock);
> -		xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
>  		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
>  
> -		mp->m_sb.sb_ifree += cntp->icsb_ifree;
>  		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
>  
>  		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
>  
> -		xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
>  		xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
>  		spin_unlock(&mp->m_sb_lock);
>  		xfs_icsb_unlock(mp);
> @@ -1544,10 +1546,14 @@ xfs_icsb_init_counters(
>  	if (error)
>  		return error;
>  
> +	error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
> +	if (error)
> +		goto free_icount;
> +
>  	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
>  	if (!mp->m_sb_cnts) {
> -		percpu_counter_destroy(&mp->m_icount);
> -		return -ENOMEM;
> +		error = -ENOMEM;
> +		goto free_ifree;
>  	}
>  
>  	for_each_online_cpu(i) {
> @@ -1570,6 +1576,12 @@ xfs_icsb_init_counters(
>  #endif /* CONFIG_HOTPLUG_CPU */
>  
>  	return 0;
> +
> +free_ifree:
> +	percpu_counter_destroy(&mp->m_ifree);
> +free_icount:
> +	percpu_counter_destroy(&mp->m_icount);
> +	return error;
>  }
>  
>  void
> @@ -1577,6 +1589,7 @@ xfs_icsb_reinit_counters(
>  	xfs_mount_t	*mp)
>  {
>  	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
> +	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
>  
>  	xfs_icsb_lock(mp);
>  	/*
> @@ -1584,7 +1597,6 @@ xfs_icsb_reinit_counters(
>  	 * initial balance kicks us off correctly
>  	 */
>  	mp->m_icsb_counters = -1;
> -	xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
>  	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
>  	xfs_icsb_unlock(mp);
>  }
> @@ -1599,6 +1611,7 @@ xfs_icsb_destroy_counters(
>  	}
>  
>  	percpu_counter_destroy(&mp->m_icount);
> +	percpu_counter_destroy(&mp->m_ifree);
>  
>  	mutex_destroy(&mp->m_icsb_mutex);
>  }
> @@ -1662,7 +1675,6 @@ xfs_icsb_count(
>  
>  	for_each_online_cpu(i) {
>  		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
> -		cnt->icsb_ifree += cntp->icsb_ifree;
>  		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
>  	}
>  
> @@ -1675,7 +1687,7 @@ xfs_icsb_counter_disabled(
>  	xfs_mount_t	*mp,
>  	xfs_sb_field_t	field)
>  {
> -	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
> +	ASSERT(field == XFS_SBS_FDBLOCKS);
>  	return test_bit(field, &mp->m_icsb_counters);
>  }
>  
> @@ -1686,7 +1698,7 @@ xfs_icsb_disable_counter(
>  {
>  	xfs_icsb_cnts_t	cnt;
>  
> -	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
> +	ASSERT(field == XFS_SBS_FDBLOCKS);
>  
>  	/*
>  	 * If we are already disabled, then there is nothing to do
> @@ -1705,9 +1717,6 @@ xfs_icsb_disable_counter(
>  
>  		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
>  		switch(field) {
> -		case XFS_SBS_IFREE:
> -			mp->m_sb.sb_ifree = cnt.icsb_ifree;
> -			break;
>  		case XFS_SBS_FDBLOCKS:
>  			mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
>  			break;
> @@ -1729,15 +1738,12 @@ xfs_icsb_enable_counter(
>  	xfs_icsb_cnts_t	*cntp;
>  	int		i;
>  
> -	ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
> +	ASSERT(field == XFS_SBS_FDBLOCKS);
>  
>  	xfs_icsb_lock_all_counters(mp);
>  	for_each_online_cpu(i) {
>  		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
>  		switch (field) {
> -		case XFS_SBS_IFREE:
> -			cntp->icsb_ifree = count + resid;
> -			break;
>  		case XFS_SBS_FDBLOCKS:
>  			cntp->icsb_fdblocks = count + resid;
>  			break;
> @@ -1760,8 +1766,6 @@ xfs_icsb_sync_counters_locked(
>  
>  	xfs_icsb_count(mp, &cnt, flags);
>  
> -	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
> -		mp->m_sb.sb_ifree = cnt.icsb_ifree;
>  	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
>  		mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
>  }
> @@ -1813,12 +1817,6 @@ xfs_icsb_balance_counter_locked(
>  
>  	/* update counters  - first CPU gets residual*/
>  	switch (field) {
> -	case XFS_SBS_IFREE:
> -		count = mp->m_sb.sb_ifree;
> -		resid = do_div(count, weight);
> -		if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
> -			return;
> -		break;
>  	case XFS_SBS_FDBLOCKS:
>  		count = mp->m_sb.sb_fdblocks;
>  		resid = do_div(count, weight);
> @@ -1873,14 +1871,6 @@ again:
>  	}
>  
>  	switch (field) {
> -	case XFS_SBS_IFREE:
> -		lcounter = icsbp->icsb_ifree;
> -		lcounter += delta;
> -		if (unlikely(lcounter < 0))
> -			goto balance_counter;
> -		icsbp->icsb_ifree = lcounter;
> -		break;
> -
>  	case XFS_SBS_FDBLOCKS:
>  		BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
>  
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index 457c6e3..0cb32ce 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -84,6 +84,7 @@ typedef struct xfs_mount {
>  	struct xfs_sb		m_sb;		/* copy of fs superblock */
>  	spinlock_t		m_sb_lock;	/* sb counter lock */
>  	struct percpu_counter	m_icount;	/* allocated inodes counter */
> +	struct percpu_counter	m_ifree;	/* free inodes counter */
>  
>  	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
>  	char			*m_fsname;	/* filesystem name */
> @@ -380,6 +381,7 @@ extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
>  extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
>  			uint, int);
>  extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
> +extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mount_log_sb(xfs_mount_t *);
>  extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
>  extern int	xfs_readsb(xfs_mount_t *, int);
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index 87e169f..e06aa6b 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -1088,6 +1088,7 @@ xfs_fs_statfs(
>  	struct xfs_inode	*ip = XFS_I(dentry->d_inode);
>  	__uint64_t		fakeinos, id;
>  	__uint64_t		icount;
> +	__uint64_t		ifree;
>  	xfs_extlen_t		lsize;
>  	__int64_t		ffree;
>  
> @@ -1100,6 +1101,7 @@ xfs_fs_statfs(
>  
>  	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
>  	icount = percpu_counter_sum(&mp->m_icount);
> +	ifree = percpu_counter_sum(&mp->m_ifree);
>  
>  	spin_lock(&mp->m_sb_lock);
>  	statp->f_bsize = sbp->sb_blocksize;
> @@ -1115,7 +1117,7 @@ xfs_fs_statfs(
>  					mp->m_maxicount);
>  
>  	/* make sure statp->f_ffree does not underflow */
> -	ffree = statp->f_files - (icount - sbp->sb_ifree);
> +	ffree = statp->f_files - (icount - ifree);
>  	statp->f_ffree = max_t(__int64_t, ffree, 0);
>  
>  	spin_unlock(&mp->m_sb_lock);
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 9bc742b..68680ce 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -560,8 +560,7 @@ xfs_trans_unreserve_and_mod_sb(
>  	}
>  
>  	if (ifreedelta) {
> -		error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE,
> -						 ifreedelta, rsvd);
> +		error = xfs_mod_ifree(mp, ifreedelta);
>  		if (error)
>  			goto out_undo_icount;
>  	}
> @@ -630,7 +629,7 @@ xfs_trans_unreserve_and_mod_sb(
>  
>  out_undo_ifreecount:
>  	if (ifreedelta)
> -		xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
> +		xfs_mod_ifree(mp, -ifreedelta);
>  out_undo_icount:
>  	if (idelta)
>  		xfs_mod_icount(mp, -idelta);
> -- 
> 2.0.0
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/7] xfs: use generic percpu counters for free block counter
  2015-02-04 20:54 ` [PATCH 3/7] xfs: use generic percpu counters for free block counter Dave Chinner
@ 2015-02-05 14:10   ` Brian Foster
  2015-02-05 14:18     ` Brian Foster
  2015-02-23 20:57   ` Christoph Hellwig
  1 sibling, 1 reply; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:10 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 07:54:05AM +1100, Dave Chinner wrote:
> 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 <dchinner@redhat.com>
> ---
>  fs/xfs/libxfs/xfs_bmap.c |  32 ++++----
>  fs/xfs/libxfs/xfs_sb.c   |   1 +
>  fs/xfs/xfs_fsops.c       |   9 ++-
>  fs/xfs/xfs_iomap.c       |   2 +-
>  fs/xfs/xfs_mount.c       | 193 ++++++++++++++++++++++++-----------------------
>  fs/xfs/xfs_mount.h       |   3 +
>  fs/xfs/xfs_super.c       |  10 ++-
>  fs/xfs/xfs_trans.c       |  16 ++--
>  8 files changed, 135 insertions(+), 131 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index 61ec015..e39c9e8 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -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;
> @@ -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. */
> @@ -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.
>  		 */
> @@ -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;
>  
> @@ -4200,7 +4196,7 @@ out_unreserve_blocks:
>  	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 ?
> @@ -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;
> @@ -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);
> diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
> index b66aeab..31a3e97 100644
> --- a/fs/xfs/libxfs/xfs_sb.c
> +++ b/fs/xfs/libxfs/xfs_sb.c
> @@ -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);
> diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> index fa74d03..fed97a9 100644
> --- a/fs/xfs/xfs_fsops.c
> +++ b/fs/xfs/xfs_fsops.c
> @@ -633,9 +633,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;
> @@ -710,7 +711,8 @@ retry:
>  	} 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 */
>  
> @@ -749,8 +751,7 @@ out:
>  		 * 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;
>  	}
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index ccb1dd0..205b948 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -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])
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 650e8f1..9e433b2 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -1114,7 +1114,6 @@ xfs_mod_icount(
>  	return 0;
>  }
>  
> -
>  int
>  xfs_mod_ifree(
>  	struct xfs_mount	*mp,
> @@ -1128,6 +1127,93 @@ xfs_mod_ifree(
>  	}
>  	return 0;
>  }
> +
> +int
> +xfs_mod_fdblocks(
> +	struct xfs_mount	*mp,
> +	int64_t			delta,
> +	bool			rsvd)
> +{
> +	int64_t			lcounter;
> +	long long		res_used;
> +	s32			batch;
> +
> +	if (delta > 0) {
> +		/*
> +		 * If the reserve pool is depleted, put blocks back into it
> +		 * first. Most of the time the pool is full.
> +		 */
> +		if (likely(mp->m_resblks == mp->m_resblks_avail)) {
> +			percpu_counter_add(&mp->m_fdblocks, delta);
> +			return 0;
> +		}
> +
> +		spin_lock(&mp->m_sb_lock);
> +		res_used = (long long)
> +				(mp->m_resblks - mp->m_resblks_avail);
> +
> +		if (res_used > delta) {
> +			mp->m_resblks_avail += delta;
> +		} else {
> +			delta -= res_used;
> +				mp->m_resblks_avail = mp->m_resblks;

Extra tab on the line above.

Brian

> +			percpu_counter_add(&mp->m_fdblocks, delta);
> +		}
> +		spin_unlock(&mp->m_sb_lock);
> +		return 0;
> +	}
> +
> +	/*
> +	 * Taking blocks away, need to be more accurate the closer we
> +	 * are to zero.
> +	 *
> +	 * batch size is set to a maximum of 1024 blocks - if we are
> +	 * allocating of freeing extents larger than this then we aren't
> +	 * going to be hammering the counter lock so a lock per update
> +	 * is not a problem.
> +	 *
> +	 * If the counter has a value of less than 2 * max batch size,
> +	 * then make everything serialise as we are real close to
> +	 * ENOSPC.
> +	 */
> +#define __BATCH	1024
> +	if (percpu_counter_compare(&mp->m_fdblocks, 2 * __BATCH) < 0)
> +		batch = 1;
> +	else
> +		batch = __BATCH;
> +#undef __BATCH
> +
> +	__percpu_counter_add(&mp->m_fdblocks, delta, batch);
> +	if (percpu_counter_compare(&mp->m_fdblocks,
> +				   XFS_ALLOC_SET_ASIDE(mp)) >= 0) {
> +		/* we had space! */
> +		return 0;
> +	}
> +
> +	/*
> +	 * lock up the sb for dipping into reserves before releasing the space
> +	 * that took us to ENOSPC.
> +	 */
> +	spin_lock(&mp->m_sb_lock);
> +	percpu_counter_add(&mp->m_fdblocks, -delta);
> +	if (!rsvd)
> +		goto fdblocks_enospc;
> +
> +	lcounter = (long long)mp->m_resblks_avail + delta;
> +	if (lcounter >= 0) {
> +		mp->m_resblks_avail = lcounter;
> +		spin_unlock(&mp->m_sb_lock);
> +		return 0;
> +	}
> +	printk_once(KERN_WARNING
> +		"Filesystem \"%s\": reserve blocks depleted! "
> +		"Consider increasing reserve pool size.",
> +		mp->m_fsname);
> +fdblocks_enospc:
> +	spin_unlock(&mp->m_sb_lock);
> +	return -ENOSPC;
> +}
> +
>  /*
>   * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
>   * a delta to a specified field in the in-core superblock.  Simply
> @@ -1146,7 +1232,6 @@ xfs_mod_incore_sb_unlocked(
>  {
>  	int		scounter;	/* short counter for 32 bit fields */
>  	long long	lcounter;	/* long counter for 64 bit fields */
> -	long long	res_used, rem;
>  
>  	/*
>  	 * With the in-core superblock spin lock held, switch
> @@ -1157,50 +1242,9 @@ xfs_mod_incore_sb_unlocked(
>  	switch (field) {
>  	case XFS_SBS_ICOUNT:
>  	case XFS_SBS_IFREE:
> +	case XFS_SBS_FDBLOCKS:
>  		ASSERT(0);
>  		return -EINVAL;
> -	case XFS_SBS_FDBLOCKS:
> -		lcounter = (long long)
> -			mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> -		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
> -
> -		if (delta > 0) {		/* Putting blocks back */
> -			if (res_used > delta) {
> -				mp->m_resblks_avail += delta;
> -			} else {
> -				rem = delta - res_used;
> -				mp->m_resblks_avail = mp->m_resblks;
> -				lcounter += rem;
> -			}
> -		} else {				/* Taking blocks away */
> -			lcounter += delta;
> -			if (lcounter >= 0) {
> -				mp->m_sb.sb_fdblocks = lcounter +
> -							XFS_ALLOC_SET_ASIDE(mp);
> -				return 0;
> -			}
> -
> -			/*
> -			 * We are out of blocks, use any available reserved
> -			 * blocks if were allowed to.
> -			 */
> -			if (!rsvd)
> -				return -ENOSPC;
> -
> -			lcounter = (long long)mp->m_resblks_avail + delta;
> -			if (lcounter >= 0) {
> -				mp->m_resblks_avail = lcounter;
> -				return 0;
> -			}
> -			printk_once(KERN_WARNING
> -				"Filesystem \"%s\": reserve blocks depleted! "
> -				"Consider increasing reserve pool size.",
> -				mp->m_fsname);
> -			return -ENOSPC;
> -		}
> -
> -		mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
> -		return 0;
>  	case XFS_SBS_FREXTENTS:
>  		lcounter = (long long)mp->m_sb.sb_frextents;
>  		lcounter += delta;
> @@ -1323,7 +1367,7 @@ xfs_mod_incore_sb(
>   *
>   * Note that this function may not be used for the superblock values that
>   * are tracked with the in-memory per-cpu counters - a direct call to
> - * xfs_icsb_modify_counters is required for these.
> + * xfs_mod_incore_sb is required for these.
>   */
>  int
>  xfs_mod_incore_sb_batch(
> @@ -1508,7 +1552,6 @@ xfs_icsb_cpu_notify(
>  	case CPU_ONLINE:
>  	case CPU_ONLINE_FROZEN:
>  		xfs_icsb_lock(mp);
> -		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
>  		xfs_icsb_unlock(mp);
>  		break;
>  	case CPU_DEAD:
> @@ -1518,13 +1561,9 @@ xfs_icsb_cpu_notify(
>  		 * re-enable the counters. */
>  		xfs_icsb_lock(mp);
>  		spin_lock(&mp->m_sb_lock);
> -		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
> -
> -		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
>  
>  		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
>  
> -		xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
>  		spin_unlock(&mp->m_sb_lock);
>  		xfs_icsb_unlock(mp);
>  		break;
> @@ -1550,10 +1589,14 @@ xfs_icsb_init_counters(
>  	if (error)
>  		goto free_icount;
>  
> +	error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
> +	if (error)
> +		goto free_ifree;
> +
>  	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
>  	if (!mp->m_sb_cnts) {
>  		error = -ENOMEM;
> -		goto free_ifree;
> +		goto free_fdblocks;
>  	}
>  
>  	for_each_online_cpu(i) {
> @@ -1577,6 +1620,8 @@ xfs_icsb_init_counters(
>  
>  	return 0;
>  
> +free_fdblocks:
> +	percpu_counter_destroy(&mp->m_fdblocks);
>  free_ifree:
>  	percpu_counter_destroy(&mp->m_ifree);
>  free_icount:
> @@ -1590,6 +1635,7 @@ xfs_icsb_reinit_counters(
>  {
>  	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
>  	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
> +	percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
>  
>  	xfs_icsb_lock(mp);
>  	/*
> @@ -1597,7 +1643,6 @@ xfs_icsb_reinit_counters(
>  	 * initial balance kicks us off correctly
>  	 */
>  	mp->m_icsb_counters = -1;
> -	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
>  	xfs_icsb_unlock(mp);
>  }
>  
> @@ -1612,6 +1657,7 @@ xfs_icsb_destroy_counters(
>  
>  	percpu_counter_destroy(&mp->m_icount);
>  	percpu_counter_destroy(&mp->m_ifree);
> +	percpu_counter_destroy(&mp->m_fdblocks);
>  
>  	mutex_destroy(&mp->m_icsb_mutex);
>  }
> @@ -1665,18 +1711,11 @@ xfs_icsb_count(
>  	xfs_icsb_cnts_t	*cnt,
>  	int		flags)
>  {
> -	xfs_icsb_cnts_t *cntp;
> -	int		i;
> -
>  	memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
>  
>  	if (!(flags & XFS_ICSB_LAZY_COUNT))
>  		xfs_icsb_lock_all_counters(mp);
>  
> -	for_each_online_cpu(i) {
> -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
> -		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
> -	}
>  
>  	if (!(flags & XFS_ICSB_LAZY_COUNT))
>  		xfs_icsb_unlock_all_counters(mp);
> @@ -1687,7 +1726,6 @@ xfs_icsb_counter_disabled(
>  	xfs_mount_t	*mp,
>  	xfs_sb_field_t	field)
>  {
> -	ASSERT(field == XFS_SBS_FDBLOCKS);
>  	return test_bit(field, &mp->m_icsb_counters);
>  }
>  
> @@ -1698,8 +1736,6 @@ xfs_icsb_disable_counter(
>  {
>  	xfs_icsb_cnts_t	cnt;
>  
> -	ASSERT(field == XFS_SBS_FDBLOCKS);
> -
>  	/*
>  	 * If we are already disabled, then there is nothing to do
>  	 * here. We check before locking all the counters to avoid
> @@ -1717,9 +1753,6 @@ xfs_icsb_disable_counter(
>  
>  		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
>  		switch(field) {
> -		case XFS_SBS_FDBLOCKS:
> -			mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
> -			break;
>  		default:
>  			BUG();
>  		}
> @@ -1735,18 +1768,11 @@ xfs_icsb_enable_counter(
>  	uint64_t	count,
>  	uint64_t	resid)
>  {
> -	xfs_icsb_cnts_t	*cntp;
>  	int		i;
>  
> -	ASSERT(field == XFS_SBS_FDBLOCKS);
> -
>  	xfs_icsb_lock_all_counters(mp);
>  	for_each_online_cpu(i) {
> -		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
>  		switch (field) {
> -		case XFS_SBS_FDBLOCKS:
> -			cntp->icsb_fdblocks = count + resid;
> -			break;
>  		default:
>  			BUG();
>  			break;
> @@ -1765,9 +1791,6 @@ xfs_icsb_sync_counters_locked(
>  	xfs_icsb_cnts_t	cnt;
>  
>  	xfs_icsb_count(mp, &cnt, flags);
> -
> -	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
> -		mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
>  }
>  
>  /*
> @@ -1809,20 +1832,12 @@ xfs_icsb_balance_counter_locked(
>  	int		min_per_cpu)
>  {
>  	uint64_t	count, resid;
> -	int		weight = num_online_cpus();
> -	uint64_t	min = (uint64_t)min_per_cpu;
>  
>  	/* disable counter and sync counter */
>  	xfs_icsb_disable_counter(mp, field);
>  
>  	/* update counters  - first CPU gets residual*/
>  	switch (field) {
> -	case XFS_SBS_FDBLOCKS:
> -		count = mp->m_sb.sb_fdblocks;
> -		resid = do_div(count, weight);
> -		if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
> -			return;
> -		break;
>  	default:
>  		BUG();
>  		count = resid = 0;	/* quiet, gcc */
> @@ -1851,7 +1866,6 @@ xfs_icsb_modify_counters(
>  	int		rsvd)
>  {
>  	xfs_icsb_cnts_t	*icsbp;
> -	long long	lcounter;	/* long counter for 64 bit fields */
>  	int		ret = 0;
>  
>  	might_sleep();
> @@ -1871,18 +1885,9 @@ again:
>  	}
>  
>  	switch (field) {
> -	case XFS_SBS_FDBLOCKS:
> -		BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
> -
> -		lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> -		lcounter += delta;
> -		if (unlikely(lcounter < 0))
> -			goto balance_counter;
> -		icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
> -		break;
>  	default:
>  		BUG();
> -		break;
> +		goto balance_counter; /* be still, gcc */
>  	}
>  	xfs_icsb_unlock_cntr(icsbp);
>  	preempt_enable();
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index 0cb32ce..76f5d25 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -85,6 +85,7 @@ typedef struct xfs_mount {
>  	spinlock_t		m_sb_lock;	/* sb counter lock */
>  	struct percpu_counter	m_icount;	/* allocated inodes counter */
>  	struct percpu_counter	m_ifree;	/* free inodes counter */
> +	struct percpu_counter	m_fdblocks;	/* free block counter */
>  
>  	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
>  	char			*m_fsname;	/* filesystem name */
> @@ -382,6 +383,8 @@ extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
>  			uint, int);
>  extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
> +extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
> +				 bool reserved);
>  extern int	xfs_mount_log_sb(xfs_mount_t *);
>  extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
>  extern int	xfs_readsb(xfs_mount_t *, int);
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index e06aa6b..4c6af31 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -1089,6 +1089,7 @@ xfs_fs_statfs(
>  	__uint64_t		fakeinos, id;
>  	__uint64_t		icount;
>  	__uint64_t		ifree;
> +	__uint64_t		fdblocks;
>  	xfs_extlen_t		lsize;
>  	__int64_t		ffree;
>  
> @@ -1102,13 +1103,17 @@ xfs_fs_statfs(
>  	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
>  	icount = percpu_counter_sum(&mp->m_icount);
>  	ifree = percpu_counter_sum(&mp->m_ifree);
> +	fdblocks = percpu_counter_sum(&mp->m_fdblocks);
>  
>  	spin_lock(&mp->m_sb_lock);
>  	statp->f_bsize = sbp->sb_blocksize;
>  	lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
>  	statp->f_blocks = sbp->sb_dblocks - lsize;
> -	statp->f_bfree = statp->f_bavail =
> -				sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> +	spin_unlock(&mp->m_sb_lock);
> +
> +	statp->f_bfree = fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> +	statp->f_bavail = statp->f_bfree;
> +
>  	fakeinos = statp->f_bfree << sbp->sb_inopblog;
>  	statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
>  	if (mp->m_maxicount)
> @@ -1120,7 +1125,6 @@ xfs_fs_statfs(
>  	ffree = statp->f_files - (icount - ifree);
>  	statp->f_ffree = max_t(__int64_t, ffree, 0);
>  
> -	spin_unlock(&mp->m_sb_lock);
>  
>  	if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
>  	    ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) ==
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 68680ce..e99f5e5 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -173,7 +173,7 @@ xfs_trans_reserve(
>  	uint			rtextents)
>  {
>  	int		error = 0;
> -	int		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
> +	bool		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
>  
>  	/* Mark this thread as being in a transaction */
>  	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
> @@ -184,8 +184,7 @@ xfs_trans_reserve(
>  	 * fail if the count would go below zero.
>  	 */
>  	if (blocks > 0) {
> -		error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
> -					  -((int64_t)blocks), rsvd);
> +		error = xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
>  		if (error != 0) {
>  			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
>  			return -ENOSPC;
> @@ -268,8 +267,7 @@ undo_log:
>  
>  undo_blocks:
>  	if (blocks > 0) {
> -		xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
> -					 (int64_t)blocks, rsvd);
> +		xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
>  		tp->t_blk_res = 0;
>  	}
>  
> @@ -516,14 +514,13 @@ xfs_trans_unreserve_and_mod_sb(
>  	xfs_mount_t	*mp = tp->t_mountp;
>  	/* REFERENCED */
>  	int		error;
> -	int		rsvd;
> +	bool		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
>  	int64_t		blkdelta = 0;
>  	int64_t		rtxdelta = 0;
>  	int64_t		idelta = 0;
>  	int64_t		ifreedelta = 0;
>  
>  	msbp = msb;
> -	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
>  
>  	/* calculate deltas */
>  	if (tp->t_blk_res > 0)
> @@ -547,8 +544,7 @@ xfs_trans_unreserve_and_mod_sb(
>  
>  	/* apply the per-cpu counters */
>  	if (blkdelta) {
> -		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
> -						 blkdelta, rsvd);
> +		error = xfs_mod_fdblocks(mp, blkdelta, rsvd);
>  		if (error)
>  			goto out;
>  	}
> @@ -635,7 +631,7 @@ out_undo_icount:
>  		xfs_mod_icount(mp, -idelta);
>  out_undo_fdblocks:
>  	if (blkdelta)
> -		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
> +		xfs_mod_fdblocks(mp, -blkdelta, rsvd);
>  out:
>  	ASSERT(error == 0);
>  	return;
> -- 
> 2.0.0
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 4/7] xfs: Remove icsb infrastructure
  2015-02-04 20:54 ` [PATCH 4/7] xfs: Remove icsb infrastructure Dave Chinner
@ 2015-02-05 14:10   ` Brian Foster
  2015-02-23 20:59   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:10 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 07:54:06AM +1100, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Now that the in-core superblock infrastructure has been replaced with
> generic per-cpu counters, we don't need it anymore. Nuke it from
> orbit so we are sure that it won't haunt us again...
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_sb.c   |   8 +-
>  fs/xfs/xfs_fsops.c       |   2 -
>  fs/xfs/xfs_iomap.c       |   1 -
>  fs/xfs/xfs_linux.h       |   9 -
>  fs/xfs/xfs_log_recover.c |   4 +-
>  fs/xfs/xfs_mount.c       | 516 +----------------------------------------------
>  fs/xfs/xfs_mount.h       |  67 ------
>  fs/xfs/xfs_super.c       |  84 ++++++--
>  fs/xfs/xfs_super.h       |   2 +
>  9 files changed, 72 insertions(+), 621 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
> index 31a3e97..a270095 100644
> --- a/fs/xfs/libxfs/xfs_sb.c
> +++ b/fs/xfs/libxfs/xfs_sb.c
> @@ -743,17 +743,15 @@ xfs_initialize_perag_data(
>  		btree += pag->pagf_btreeblks;
>  		xfs_perag_put(pag);
>  	}
> -	/*
> -	 * Overwrite incore superblock counters with just-read data
> -	 */
> +
> +	/* Overwrite incore superblock counters with just-read data */
>  	spin_lock(&mp->m_sb_lock);
>  	sbp->sb_ifree = ifree;
>  	sbp->sb_icount = ialloc;
>  	sbp->sb_fdblocks = bfree + bfreelst + btree;
>  	spin_unlock(&mp->m_sb_lock);
>  
> -	/* Fixup the per-cpu counters as well. */
> -	xfs_icsb_reinit_counters(mp);
> +	xfs_reinit_percpu_counters(mp);
>  
>  	return 0;
>  }
> diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> index fed97a9..a45c82b4 100644
> --- a/fs/xfs/xfs_fsops.c
> +++ b/fs/xfs/xfs_fsops.c
> @@ -630,7 +630,6 @@ xfs_fs_counts(
>  	xfs_mount_t		*mp,
>  	xfs_fsop_counts_t	*cnt)
>  {
> -	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) -
> @@ -694,7 +693,6 @@ xfs_reserve_blocks(
>  	 */
>  retry:
>  	spin_lock(&mp->m_sb_lock);
> -	xfs_icsb_sync_counters_locked(mp, 0);
>  
>  	/*
>  	 * If our previous reservation was larger than the current value,
> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> index 205b948..38e633b 100644
> --- a/fs/xfs/xfs_iomap.c
> +++ b/fs/xfs/xfs_iomap.c
> @@ -460,7 +460,6 @@ xfs_iomap_prealloc_size(
>  	alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN),
>  				       alloc_blocks);
>  
> -	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
>  	freesp = percpu_counter_read_positive(&mp->m_fdblocks);
>  	if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
>  		shift = 2;
> diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
> index c31d2c2..7c7842c 100644
> --- a/fs/xfs/xfs_linux.h
> +++ b/fs/xfs/xfs_linux.h
> @@ -116,15 +116,6 @@ typedef __uint64_t __psunsigned_t;
>  #undef XFS_NATIVE_HOST
>  #endif
>  
> -/*
> - * Feature macros (disable/enable)
> - */
> -#ifdef CONFIG_SMP
> -#define HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
> -#else
> -#undef  HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
> -#endif
> -
>  #define irix_sgid_inherit	xfs_params.sgid_inherit.val
>  #define irix_symlink_mode	xfs_params.symlink_mode.val
>  #define xfs_panic_mask		xfs_params.panic_mask.val
> diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
> index a5a945f..4f5784f 100644
> --- a/fs/xfs/xfs_log_recover.c
> +++ b/fs/xfs/xfs_log_recover.c
> @@ -4463,10 +4463,10 @@ xlog_do_recover(
>  	xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
>  	ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
>  	ASSERT(xfs_sb_good_version(sbp));
> +	xfs_reinit_percpu_counters(log->l_mp);
> +
>  	xfs_buf_relse(bp);
>  
> -	/* We've re-read the superblock so re-initialize per-cpu counters */
> -	xfs_icsb_reinit_counters(log->l_mp);
>  
>  	xlog_recover_check_summary(log);
>  
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 9e433b2..1d26200 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -43,18 +43,6 @@
>  #include "xfs_sysfs.h"
>  
>  
> -#ifdef HAVE_PERCPU_SB
> -STATIC void	xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
> -						int);
> -STATIC void	xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
> -						int);
> -STATIC void	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
> -#else
> -
> -#define xfs_icsb_balance_counter(mp, a, b)		do { } while (0)
> -#define xfs_icsb_balance_counter_locked(mp, a, b)	do { } while (0)
> -#endif
> -
>  static DEFINE_MUTEX(xfs_uuid_table_mutex);
>  static int xfs_uuid_table_size;
>  static uuid_t *xfs_uuid_table;
> @@ -347,8 +335,7 @@ reread:
>  		goto reread;
>  	}
>  
> -	/* Initialize per-cpu counters */
> -	xfs_icsb_reinit_counters(mp);
> +	xfs_reinit_percpu_counters(mp);
>  
>  	/* no need to be quiet anymore, so reset the buf ops */
>  	bp->b_ops = &xfs_sb_buf_ops;
> @@ -1087,8 +1074,6 @@ xfs_log_sbcount(xfs_mount_t *mp)
>  	if (!xfs_fs_writable(mp, SB_FREEZE_COMPLETE))
>  		return 0;
>  
> -	xfs_icsb_sync_counters(mp, 0);
> -
>  	/*
>  	 * we don't need to do this if we are updating the superblock
>  	 * counters on every modification.
> @@ -1467,502 +1452,3 @@ xfs_dev_is_read_only(
>  	}
>  	return 0;
>  }
> -
> -#ifdef HAVE_PERCPU_SB
> -/*
> - * Per-cpu incore superblock counters
> - *
> - * Simple concept, difficult implementation
> - *
> - * Basically, replace the incore superblock counters with a distributed per cpu
> - * counter for contended fields (e.g.  free block count).
> - *
> - * Difficulties arise in that the incore sb is used for ENOSPC checking, and
> - * hence needs to be accurately read when we are running low on space. Hence
> - * there is a method to enable and disable the per-cpu counters based on how
> - * much "stuff" is available in them.
> - *
> - * Basically, a counter is enabled if there is enough free resource to justify
> - * running a per-cpu fast-path. If the per-cpu counter runs out (i.e. a local
> - * ENOSPC), then we disable the counters to synchronise all callers and
> - * re-distribute the available resources.
> - *
> - * If, once we redistributed the available resources, we still get a failure,
> - * we disable the per-cpu counter and go through the slow path.
> - *
> - * The slow path is the current xfs_mod_incore_sb() function.  This means that
> - * when we disable a per-cpu counter, we need to drain its resources back to
> - * the global superblock. We do this after disabling the counter to prevent
> - * more threads from queueing up on the counter.
> - *
> - * Essentially, this means that we still need a lock in the fast path to enable
> - * synchronisation between the global counters and the per-cpu counters. This
> - * is not a problem because the lock will be local to a CPU almost all the time
> - * and have little contention except when we get to ENOSPC conditions.
> - *
> - * Basically, this lock becomes a barrier that enables us to lock out the fast
> - * path while we do things like enabling and disabling counters and
> - * synchronising the counters.
> - *
> - * Locking rules:
> - *
> - * 	1. m_sb_lock before picking up per-cpu locks
> - * 	2. per-cpu locks always picked up via for_each_online_cpu() order
> - * 	3. accurate counter sync requires m_sb_lock + per cpu locks
> - * 	4. modifying per-cpu counters requires holding per-cpu lock
> - * 	5. modifying global counters requires holding m_sb_lock
> - *	6. enabling or disabling a counter requires holding the m_sb_lock 
> - *	   and _none_ of the per-cpu locks.
> - *
> - * Disabled counters are only ever re-enabled by a balance operation
> - * that results in more free resources per CPU than a given threshold.
> - * To ensure counters don't remain disabled, they are rebalanced when
> - * the global resource goes above a higher threshold (i.e. some hysteresis
> - * is present to prevent thrashing).
> - */
> -
> -#ifdef CONFIG_HOTPLUG_CPU
> -/*
> - * hot-plug CPU notifier support.
> - *
> - * We need a notifier per filesystem as we need to be able to identify
> - * the filesystem to balance the counters out. This is achieved by
> - * having a notifier block embedded in the xfs_mount_t and doing pointer
> - * magic to get the mount pointer from the notifier block address.
> - */
> -STATIC int
> -xfs_icsb_cpu_notify(
> -	struct notifier_block *nfb,
> -	unsigned long action,
> -	void *hcpu)
> -{
> -	xfs_icsb_cnts_t *cntp;
> -	xfs_mount_t	*mp;
> -
> -	mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
> -	cntp = (xfs_icsb_cnts_t *)
> -			per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
> -	switch (action) {
> -	case CPU_UP_PREPARE:
> -	case CPU_UP_PREPARE_FROZEN:
> -		/* Easy Case - initialize the area and locks, and
> -		 * then rebalance when online does everything else for us. */
> -		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
> -		break;
> -	case CPU_ONLINE:
> -	case CPU_ONLINE_FROZEN:
> -		xfs_icsb_lock(mp);
> -		xfs_icsb_unlock(mp);
> -		break;
> -	case CPU_DEAD:
> -	case CPU_DEAD_FROZEN:
> -		/* Disable all the counters, then fold the dead cpu's
> -		 * count into the total on the global superblock and
> -		 * re-enable the counters. */
> -		xfs_icsb_lock(mp);
> -		spin_lock(&mp->m_sb_lock);
> -
> -		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
> -
> -		spin_unlock(&mp->m_sb_lock);
> -		xfs_icsb_unlock(mp);
> -		break;
> -	}
> -
> -	return NOTIFY_OK;
> -}
> -#endif /* CONFIG_HOTPLUG_CPU */
> -
> -int
> -xfs_icsb_init_counters(
> -	xfs_mount_t	*mp)
> -{
> -	xfs_icsb_cnts_t *cntp;
> -	int		error;
> -	int		i;
> -
> -	error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
> -	if (error)
> -		return error;
> -
> -	error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
> -	if (error)
> -		goto free_icount;
> -
> -	error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
> -	if (error)
> -		goto free_ifree;
> -
> -	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
> -	if (!mp->m_sb_cnts) {
> -		error = -ENOMEM;
> -		goto free_fdblocks;
> -	}
> -
> -	for_each_online_cpu(i) {
> -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
> -		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
> -	}
> -
> -	mutex_init(&mp->m_icsb_mutex);
> -
> -	/*
> -	 * start with all counters disabled so that the
> -	 * initial balance kicks us off correctly
> -	 */
> -	mp->m_icsb_counters = -1;
> -
> -#ifdef CONFIG_HOTPLUG_CPU
> -	mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
> -	mp->m_icsb_notifier.priority = 0;
> -	register_hotcpu_notifier(&mp->m_icsb_notifier);
> -#endif /* CONFIG_HOTPLUG_CPU */
> -
> -	return 0;
> -
> -free_fdblocks:
> -	percpu_counter_destroy(&mp->m_fdblocks);
> -free_ifree:
> -	percpu_counter_destroy(&mp->m_ifree);
> -free_icount:
> -	percpu_counter_destroy(&mp->m_icount);
> -	return error;
> -}
> -
> -void
> -xfs_icsb_reinit_counters(
> -	xfs_mount_t	*mp)
> -{
> -	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
> -	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
> -	percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
> -
> -	xfs_icsb_lock(mp);
> -	/*
> -	 * start with all counters disabled so that the
> -	 * initial balance kicks us off correctly
> -	 */
> -	mp->m_icsb_counters = -1;
> -	xfs_icsb_unlock(mp);
> -}
> -
> -void
> -xfs_icsb_destroy_counters(
> -	xfs_mount_t	*mp)
> -{
> -	if (mp->m_sb_cnts) {
> -		unregister_hotcpu_notifier(&mp->m_icsb_notifier);
> -		free_percpu(mp->m_sb_cnts);
> -	}
> -
> -	percpu_counter_destroy(&mp->m_icount);
> -	percpu_counter_destroy(&mp->m_ifree);
> -	percpu_counter_destroy(&mp->m_fdblocks);
> -
> -	mutex_destroy(&mp->m_icsb_mutex);
> -}
> -
> -STATIC void
> -xfs_icsb_lock_cntr(
> -	xfs_icsb_cnts_t	*icsbp)
> -{
> -	while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
> -		ndelay(1000);
> -	}
> -}
> -
> -STATIC void
> -xfs_icsb_unlock_cntr(
> -	xfs_icsb_cnts_t	*icsbp)
> -{
> -	clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
> -}
> -
> -
> -STATIC void
> -xfs_icsb_lock_all_counters(
> -	xfs_mount_t	*mp)
> -{
> -	xfs_icsb_cnts_t *cntp;
> -	int		i;
> -
> -	for_each_online_cpu(i) {
> -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
> -		xfs_icsb_lock_cntr(cntp);
> -	}
> -}
> -
> -STATIC void
> -xfs_icsb_unlock_all_counters(
> -	xfs_mount_t	*mp)
> -{
> -	xfs_icsb_cnts_t *cntp;
> -	int		i;
> -
> -	for_each_online_cpu(i) {
> -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
> -		xfs_icsb_unlock_cntr(cntp);
> -	}
> -}
> -
> -STATIC void
> -xfs_icsb_count(
> -	xfs_mount_t	*mp,
> -	xfs_icsb_cnts_t	*cnt,
> -	int		flags)
> -{
> -	memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
> -
> -	if (!(flags & XFS_ICSB_LAZY_COUNT))
> -		xfs_icsb_lock_all_counters(mp);
> -
> -
> -	if (!(flags & XFS_ICSB_LAZY_COUNT))
> -		xfs_icsb_unlock_all_counters(mp);
> -}
> -
> -STATIC int
> -xfs_icsb_counter_disabled(
> -	xfs_mount_t	*mp,
> -	xfs_sb_field_t	field)
> -{
> -	return test_bit(field, &mp->m_icsb_counters);
> -}
> -
> -STATIC void
> -xfs_icsb_disable_counter(
> -	xfs_mount_t	*mp,
> -	xfs_sb_field_t	field)
> -{
> -	xfs_icsb_cnts_t	cnt;
> -
> -	/*
> -	 * If we are already disabled, then there is nothing to do
> -	 * here. We check before locking all the counters to avoid
> -	 * the expensive lock operation when being called in the
> -	 * slow path and the counter is already disabled. This is
> -	 * safe because the only time we set or clear this state is under
> -	 * the m_icsb_mutex.
> -	 */
> -	if (xfs_icsb_counter_disabled(mp, field))
> -		return;
> -
> -	xfs_icsb_lock_all_counters(mp);
> -	if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
> -		/* drain back to superblock */
> -
> -		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
> -		switch(field) {
> -		default:
> -			BUG();
> -		}
> -	}
> -
> -	xfs_icsb_unlock_all_counters(mp);
> -}
> -
> -STATIC void
> -xfs_icsb_enable_counter(
> -	xfs_mount_t	*mp,
> -	xfs_sb_field_t	field,
> -	uint64_t	count,
> -	uint64_t	resid)
> -{
> -	int		i;
> -
> -	xfs_icsb_lock_all_counters(mp);
> -	for_each_online_cpu(i) {
> -		switch (field) {
> -		default:
> -			BUG();
> -			break;
> -		}
> -		resid = 0;
> -	}
> -	clear_bit(field, &mp->m_icsb_counters);
> -	xfs_icsb_unlock_all_counters(mp);
> -}
> -
> -void
> -xfs_icsb_sync_counters_locked(
> -	xfs_mount_t	*mp,
> -	int		flags)
> -{
> -	xfs_icsb_cnts_t	cnt;
> -
> -	xfs_icsb_count(mp, &cnt, flags);
> -}
> -
> -/*
> - * Accurate update of per-cpu counters to incore superblock
> - */
> -void
> -xfs_icsb_sync_counters(
> -	xfs_mount_t	*mp,
> -	int		flags)
> -{
> -	spin_lock(&mp->m_sb_lock);
> -	xfs_icsb_sync_counters_locked(mp, flags);
> -	spin_unlock(&mp->m_sb_lock);
> -}
> -
> -/*
> - * Balance and enable/disable counters as necessary.
> - *
> - * Thresholds for re-enabling counters are somewhat magic.  inode counts are
> - * chosen to be the same number as single on disk allocation chunk per CPU, and
> - * free blocks is something far enough zero that we aren't going thrash when we
> - * get near ENOSPC. We also need to supply a minimum we require per cpu to
> - * prevent looping endlessly when xfs_alloc_space asks for more than will
> - * be distributed to a single CPU but each CPU has enough blocks to be
> - * reenabled.
> - *
> - * Note that we can be called when counters are already disabled.
> - * xfs_icsb_disable_counter() optimises the counter locking in this case to
> - * prevent locking every per-cpu counter needlessly.
> - */
> -
> -#define XFS_ICSB_INO_CNTR_REENABLE	(uint64_t)64
> -#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
> -		(uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
> -STATIC void
> -xfs_icsb_balance_counter_locked(
> -	xfs_mount_t	*mp,
> -	xfs_sb_field_t  field,
> -	int		min_per_cpu)
> -{
> -	uint64_t	count, resid;
> -
> -	/* disable counter and sync counter */
> -	xfs_icsb_disable_counter(mp, field);
> -
> -	/* update counters  - first CPU gets residual*/
> -	switch (field) {
> -	default:
> -		BUG();
> -		count = resid = 0;	/* quiet, gcc */
> -		break;
> -	}
> -
> -	xfs_icsb_enable_counter(mp, field, count, resid);
> -}
> -
> -STATIC void
> -xfs_icsb_balance_counter(
> -	xfs_mount_t	*mp,
> -	xfs_sb_field_t  fields,
> -	int		min_per_cpu)
> -{
> -	spin_lock(&mp->m_sb_lock);
> -	xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
> -	spin_unlock(&mp->m_sb_lock);
> -}
> -
> -int
> -xfs_icsb_modify_counters(
> -	xfs_mount_t	*mp,
> -	xfs_sb_field_t	field,
> -	int64_t		delta,
> -	int		rsvd)
> -{
> -	xfs_icsb_cnts_t	*icsbp;
> -	int		ret = 0;
> -
> -	might_sleep();
> -again:
> -	preempt_disable();
> -	icsbp = this_cpu_ptr(mp->m_sb_cnts);
> -
> -	/*
> -	 * if the counter is disabled, go to slow path
> -	 */
> -	if (unlikely(xfs_icsb_counter_disabled(mp, field)))
> -		goto slow_path;
> -	xfs_icsb_lock_cntr(icsbp);
> -	if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
> -		xfs_icsb_unlock_cntr(icsbp);
> -		goto slow_path;
> -	}
> -
> -	switch (field) {
> -	default:
> -		BUG();
> -		goto balance_counter; /* be still, gcc */
> -	}
> -	xfs_icsb_unlock_cntr(icsbp);
> -	preempt_enable();
> -	return 0;
> -
> -slow_path:
> -	preempt_enable();
> -
> -	/*
> -	 * serialise with a mutex so we don't burn lots of cpu on
> -	 * the superblock lock. We still need to hold the superblock
> -	 * lock, however, when we modify the global structures.
> -	 */
> -	xfs_icsb_lock(mp);
> -
> -	/*
> -	 * Now running atomically.
> -	 *
> -	 * If the counter is enabled, someone has beaten us to rebalancing.
> -	 * Drop the lock and try again in the fast path....
> -	 */
> -	if (!(xfs_icsb_counter_disabled(mp, field))) {
> -		xfs_icsb_unlock(mp);
> -		goto again;
> -	}
> -
> -	/*
> -	 * The counter is currently disabled. Because we are
> -	 * running atomically here, we know a rebalance cannot
> -	 * be in progress. Hence we can go straight to operating
> -	 * on the global superblock. We do not call xfs_mod_incore_sb()
> -	 * here even though we need to get the m_sb_lock. Doing so
> -	 * will cause us to re-enter this function and deadlock.
> -	 * Hence we get the m_sb_lock ourselves and then call
> -	 * xfs_mod_incore_sb_unlocked() as the unlocked path operates
> -	 * directly on the global counters.
> -	 */
> -	spin_lock(&mp->m_sb_lock);
> -	ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
> -	spin_unlock(&mp->m_sb_lock);
> -
> -	/*
> -	 * Now that we've modified the global superblock, we
> -	 * may be able to re-enable the distributed counters
> -	 * (e.g. lots of space just got freed). After that
> -	 * we are done.
> -	 */
> -	if (ret != -ENOSPC)
> -		xfs_icsb_balance_counter(mp, field, 0);
> -	xfs_icsb_unlock(mp);
> -	return ret;
> -
> -balance_counter:
> -	xfs_icsb_unlock_cntr(icsbp);
> -	preempt_enable();
> -
> -	/*
> -	 * We may have multiple threads here if multiple per-cpu
> -	 * counters run dry at the same time. This will mean we can
> -	 * do more balances than strictly necessary but it is not
> -	 * the common slowpath case.
> -	 */
> -	xfs_icsb_lock(mp);
> -
> -	/*
> -	 * running atomically.
> -	 *
> -	 * This will leave the counter in the correct state for future
> -	 * accesses. After the rebalance, we simply try again and our retry
> -	 * will either succeed through the fast path or slow path without
> -	 * another balance operation being required.
> -	 */
> -	xfs_icsb_balance_counter(mp, field, delta);
> -	xfs_icsb_unlock(mp);
> -	goto again;
> -}
> -
> -#endif
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index 76f5d25..ff1d1d5 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -18,8 +18,6 @@
>  #ifndef __XFS_MOUNT_H__
>  #define	__XFS_MOUNT_H__
>  
> -#ifdef __KERNEL__
> -
>  struct xlog;
>  struct xfs_inode;
>  struct xfs_mru_cache;
> @@ -29,43 +27,6 @@ struct xfs_quotainfo;
>  struct xfs_dir_ops;
>  struct xfs_da_geometry;
>  
> -#ifdef HAVE_PERCPU_SB
> -
> -/*
> - * Valid per-cpu incore superblock counters. Note that if you add new counters,
> - * you may need to define new counter disabled bit field descriptors as there
> - * are more possible fields in the superblock that can fit in a bitfield on a
> - * 32 bit platform. The XFS_SBS_* values for the current current counters just
> - * fit.
> - */
> -typedef struct xfs_icsb_cnts {
> -	uint64_t	icsb_fdblocks;
> -	uint64_t	icsb_ifree;
> -	unsigned long	icsb_flags;
> -} xfs_icsb_cnts_t;
> -
> -#define XFS_ICSB_FLAG_LOCK	(1 << 0)	/* counter lock bit */
> -
> -#define XFS_ICSB_LAZY_COUNT	(1 << 1)	/* accuracy not needed */
> -
> -extern int	xfs_icsb_init_counters(struct xfs_mount *);
> -extern void	xfs_icsb_reinit_counters(struct xfs_mount *);
> -extern void	xfs_icsb_destroy_counters(struct xfs_mount *);
> -extern void	xfs_icsb_sync_counters(struct xfs_mount *, int);
> -extern void	xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
> -extern int	xfs_icsb_modify_counters(struct xfs_mount *, xfs_sb_field_t,
> -						int64_t, int);
> -
> -#else
> -#define xfs_icsb_init_counters(mp)		(0)
> -#define xfs_icsb_destroy_counters(mp)		do { } while (0)
> -#define xfs_icsb_reinit_counters(mp)		do { } while (0)
> -#define xfs_icsb_sync_counters(mp, flags)	do { } while (0)
> -#define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
> -#define xfs_icsb_modify_counters(mp, field, delta, rsvd) \
> -	xfs_mod_incore_sb(mp, field, delta, rsvd)
> -#endif
> -
>  /* dynamic preallocation free space thresholds, 5% down to 1% */
>  enum {
>  	XFS_LOWSP_1_PCNT = 0,
> @@ -156,12 +117,6 @@ typedef struct xfs_mount {
>  	const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */
>  	uint			m_chsize;	/* size of next field */
>  	atomic_t		m_active_trans;	/* number trans frozen */
> -#ifdef HAVE_PERCPU_SB
> -	xfs_icsb_cnts_t __percpu *m_sb_cnts;	/* per-cpu superblock counters */
> -	unsigned long		m_icsb_counters; /* disabled per-cpu counters */
> -	struct notifier_block	m_icsb_notifier; /* hotplug cpu notifier */
> -	struct mutex		m_icsb_mutex;	/* balancer sync lock */
> -#endif
>  	struct xfs_mru_cache	*m_filestream;  /* per-mount filestream data */
>  	struct delayed_work	m_reclaim_work;	/* background inode reclaim */
>  	struct delayed_work	m_eofblocks_work; /* background eof blocks
> @@ -294,26 +249,6 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
>  }
>  
>  /*
> - * Per-cpu superblock locking functions
> - */
> -#ifdef HAVE_PERCPU_SB
> -static inline void
> -xfs_icsb_lock(xfs_mount_t *mp)
> -{
> -	mutex_lock(&mp->m_icsb_mutex);
> -}
> -
> -static inline void
> -xfs_icsb_unlock(xfs_mount_t *mp)
> -{
> -	mutex_unlock(&mp->m_icsb_mutex);
> -}
> -#else
> -#define xfs_icsb_lock(mp)
> -#define xfs_icsb_unlock(mp)
> -#endif
> -
> -/*
>   * This structure is for use by the xfs_mod_incore_sb_batch() routine.
>   * xfs_growfs can specify a few fields which are more than int limit
>   */
> @@ -396,6 +331,4 @@ extern int	xfs_dev_is_read_only(struct xfs_mount *, char *);
>  
>  extern void	xfs_set_low_space_thresholds(struct xfs_mount *);
>  
> -#endif	/* __KERNEL__ */
> -
>  #endif	/* __XFS_MOUNT_H__ */
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index 4c6af31..af6d268 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -1035,23 +1035,6 @@ xfs_free_fsname(
>  	kfree(mp->m_logname);
>  }
>  
> -STATIC void
> -xfs_fs_put_super(
> -	struct super_block	*sb)
> -{
> -	struct xfs_mount	*mp = XFS_M(sb);
> -
> -	xfs_filestream_unmount(mp);
> -	xfs_unmountfs(mp);
> -
> -	xfs_freesb(mp);
> -	xfs_icsb_destroy_counters(mp);
> -	xfs_destroy_mount_workqueues(mp);
> -	xfs_close_devices(mp);
> -	xfs_free_fsname(mp);
> -	kfree(mp);
> -}
> -
>  STATIC int
>  xfs_fs_sync_fs(
>  	struct super_block	*sb,
> @@ -1100,7 +1083,6 @@ xfs_fs_statfs(
>  	statp->f_fsid.val[0] = (u32)id;
>  	statp->f_fsid.val[1] = (u32)(id >> 32);
>  
> -	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
>  	icount = percpu_counter_sum(&mp->m_icount);
>  	ifree = percpu_counter_sum(&mp->m_ifree);
>  	fdblocks = percpu_counter_sum(&mp->m_fdblocks);
> @@ -1405,6 +1387,51 @@ xfs_finish_flags(
>  	return 0;
>  }
>  
> +static int
> +xfs_init_percpu_counters(
> +	struct xfs_mount	*mp)
> +{
> +	int		error;
> +
> +	error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
> +	if (error)
> +		return ENOMEM;
> +
> +	error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
> +	if (error)
> +		goto free_icount;
> +
> +	error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
> +	if (error)
> +		goto free_ifree;
> +
> +	return 0;
> +
> +free_ifree:
> +	percpu_counter_destroy(&mp->m_ifree);
> +free_icount:
> +	percpu_counter_destroy(&mp->m_icount);
> +	return -ENOMEM;
> +}
> +
> +void
> +xfs_reinit_percpu_counters(
> +	struct xfs_mount	*mp)
> +{
> +	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
> +	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
> +	percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
> +}
> +
> +static void
> +xfs_destroy_percpu_counters(
> +	struct xfs_mount	*mp)
> +{
> +	percpu_counter_destroy(&mp->m_icount);
> +	percpu_counter_destroy(&mp->m_ifree);
> +	percpu_counter_destroy(&mp->m_fdblocks);
> +}
> +
>  STATIC int
>  xfs_fs_fill_super(
>  	struct super_block	*sb,
> @@ -1453,7 +1480,7 @@ xfs_fs_fill_super(
>  	if (error)
>  		goto out_close_devices;
>  
> -	error = xfs_icsb_init_counters(mp);
> +	error = xfs_init_percpu_counters(mp);
>  	if (error)
>  		goto out_destroy_workqueues;
>  
> @@ -1511,7 +1538,7 @@ xfs_fs_fill_super(
>   out_free_sb:
>  	xfs_freesb(mp);
>   out_destroy_counters:
> -	xfs_icsb_destroy_counters(mp);
> +	xfs_destroy_percpu_counters(mp);
>  out_destroy_workqueues:
>  	xfs_destroy_mount_workqueues(mp);
>   out_close_devices:
> @@ -1528,6 +1555,23 @@ out_destroy_workqueues:
>  	goto out_free_sb;
>  }
>  
> +STATIC void
> +xfs_fs_put_super(
> +	struct super_block	*sb)
> +{
> +	struct xfs_mount	*mp = XFS_M(sb);
> +
> +	xfs_filestream_unmount(mp);
> +	xfs_unmountfs(mp);
> +
> +	xfs_freesb(mp);
> +	xfs_destroy_percpu_counters(mp);
> +	xfs_destroy_mount_workqueues(mp);
> +	xfs_close_devices(mp);
> +	xfs_free_fsname(mp);
> +	kfree(mp);
> +}
> +
>  STATIC struct dentry *
>  xfs_fs_mount(
>  	struct file_system_type	*fs_type,
> diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
> index 2b830c2..499058f 100644
> --- a/fs/xfs/xfs_super.h
> +++ b/fs/xfs/xfs_super.h
> @@ -72,6 +72,8 @@ extern const struct export_operations xfs_export_operations;
>  extern const struct xattr_handler *xfs_xattr_handlers[];
>  extern const struct quotactl_ops xfs_quotactl_operations;
>  
> +extern void xfs_reinit_percpu_counters(struct xfs_mount *mp);
> +
>  #define XFS_M(sb)		((struct xfs_mount *)((sb)->s_fs_info))
>  
>  #endif	/* __XFS_SUPER_H__ */
> -- 
> 2.0.0
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 5/7] xfs: introduce xfs_mod_frextents
  2015-02-04 20:54 ` [PATCH 5/7] xfs: introduce xfs_mod_frextents Dave Chinner
@ 2015-02-05 14:10   ` Brian Foster
  2015-02-23 21:02   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:10 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 07:54:07AM +1100, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Add a new helper to modify the incore counter of free realtime
> extents. This matches the helpers used for inode and data block
> counters, and removes a significant users of the xfs_mod_incore_sb()
> interface.
> 
> Based on a patch originally from Christoph Hellwig.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_bmap.c |  8 +++-----
>  fs/xfs/xfs_mount.c       | 27 +++++++++++++++++++--------
>  fs/xfs/xfs_mount.h       |  2 ++
>  fs/xfs/xfs_trans.c       | 18 ++++++++++--------
>  4 files changed, 34 insertions(+), 21 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index e39c9e8..b8e97fd0 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -4158,8 +4158,7 @@ xfs_bmapi_reserve_delalloc(
>  	ASSERT(indlen > 0);
>  
>  	if (rt) {
> -		error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
> -					  -((int64_t)extsz), 0);
> +		error = xfs_mod_frextents(mp, -((int64_t)extsz));
>  	} else {
>  		error = xfs_mod_fdblocks(mp, -((int64_t)alen), false);
>  	}
> @@ -4194,7 +4193,7 @@ xfs_bmapi_reserve_delalloc(
>  
>  out_unreserve_blocks:
>  	if (rt)
> -		xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0);
> +		xfs_mod_frextents(mp, extsz);
>  	else
>  		xfs_mod_fdblocks(mp, alen, false);
>  out_unreserve_quota:
> @@ -5278,8 +5277,7 @@ xfs_bunmapi(
>  
>  				rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
>  				do_div(rtexts, mp->m_sb.sb_rextsize);
> -				xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
> -						(int64_t)rtexts, 0);
> +				xfs_mod_frextents(mp, (int64_t)rtexts);
>  				(void)xfs_trans_reserve_quota_nblks(NULL,
>  					ip, -((long)del.br_blockcount), 0,
>  					XFS_QMOPT_RES_RTBLKS);
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 1d26200..284f528 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -1199,6 +1199,24 @@ fdblocks_enospc:
>  	return -ENOSPC;
>  }
>  
> +int
> +xfs_mod_frextents(
> +	struct xfs_mount	*mp,
> +	int64_t			delta)
> +{
> +	int64_t			lcounter;
> +	int			ret = 0;
> +
> +	spin_lock(&mp->m_sb_lock);
> +	lcounter = mp->m_sb.sb_frextents + delta;
> +	if (lcounter < 0)
> +		ret = -ENOSPC;
> +	else
> +		mp->m_sb.sb_frextents = lcounter;
> +	spin_unlock(&mp->m_sb_lock);
> +	return ret;
> +}
> +
>  /*
>   * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
>   * a delta to a specified field in the in-core superblock.  Simply
> @@ -1228,16 +1246,9 @@ xfs_mod_incore_sb_unlocked(
>  	case XFS_SBS_ICOUNT:
>  	case XFS_SBS_IFREE:
>  	case XFS_SBS_FDBLOCKS:
> +	case XFS_SBS_FREXTENTS:
>  		ASSERT(0);
>  		return -EINVAL;
> -	case XFS_SBS_FREXTENTS:
> -		lcounter = (long long)mp->m_sb.sb_frextents;
> -		lcounter += delta;
> -		if (lcounter < 0) {
> -			return -ENOSPC;
> -		}
> -		mp->m_sb.sb_frextents = lcounter;
> -		return 0;
>  	case XFS_SBS_DBLOCKS:
>  		lcounter = (long long)mp->m_sb.sb_dblocks;
>  		lcounter += delta;
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index ff1d1d5..8970489 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -320,6 +320,8 @@ extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
>  				 bool reserved);
> +extern int	xfs_mod_frextents(struct xfs_mount *mp, int64_t delta);
> +
>  extern int	xfs_mount_log_sb(xfs_mount_t *);
>  extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
>  extern int	xfs_readsb(xfs_mount_t *, int);
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index e99f5e5..4e4bc5a 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -235,8 +235,7 @@ xfs_trans_reserve(
>  	 * fail if the count would go below zero.
>  	 */
>  	if (rtextents > 0) {
> -		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
> -					  -((int64_t)rtextents), rsvd);
> +		error = xfs_mod_frextents(tp->t_mountp, -((int64_t)rtextents));
>  		if (error) {
>  			error = -ENOSPC;
>  			goto undo_log;
> @@ -562,10 +561,10 @@ xfs_trans_unreserve_and_mod_sb(
>  	}
>  
>  	/* apply remaining deltas */
> -	if (rtxdelta != 0) {
> -		msbp->msb_field = XFS_SBS_FREXTENTS;
> -		msbp->msb_delta = rtxdelta;
> -		msbp++;
> +	if (rtxdelta) {
> +		error = xfs_mod_frextents(mp, rtxdelta);
> +		if (error)
> +			goto out_undo_ifree;
>  	}
>  
>  	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
> @@ -618,12 +617,15 @@ xfs_trans_unreserve_and_mod_sb(
>  		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
>  			(uint)(msbp - msb), rsvd);
>  		if (error)
> -			goto out_undo_ifreecount;
> +			goto out_undo_frextents;
>  	}
>  
>  	return;
>  
> -out_undo_ifreecount:
> +out_undo_frextents:
> +	if (rtxdelta)
> +		xfs_mod_frextents(mp, -rtxdelta);
> +out_undo_ifree:
>  	if (ifreedelta)
>  		xfs_mod_ifree(mp, -ifreedelta);
>  out_undo_icount:
> -- 
> 2.0.0
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 6/7] xfs: replace xfs_mod_incore_sb_batched
  2015-02-04 20:54 ` [PATCH 6/7] xfs: replace xfs_mod_incore_sb_batched Dave Chinner
@ 2015-02-05 14:10   ` Brian Foster
  2015-02-05 14:19     ` Christoph Hellwig
  0 siblings, 1 reply; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:10 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 07:54:08AM +1100, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Introduce helper functions for modifying fields in the superblock
> into xfs_trans.c, the only caller of xfs_mod_incore_sb_batch().  We
> can then use these directly in xfs_trans_unreserve_and_mod_sb() and
> so remove another user of the xfs_mode_incore_sb() API without
> losing any functionality or scalability of the transaction commit
> code..
> 
> Based on a patch from Christoph Hellwig.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
>  fs/xfs/xfs_mount.c |  51 --------------
>  fs/xfs/xfs_mount.h |  11 ---
>  fs/xfs/xfs_trans.c | 198 ++++++++++++++++++++++++++++++++++-------------------
>  3 files changed, 126 insertions(+), 134 deletions(-)
> 
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 284f528..9499e88 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -1354,57 +1354,6 @@ xfs_mod_incore_sb(
>  }
>  
>  /*
> - * Change more than one field in the in-core superblock structure at a time.
> - *
> - * The fields and changes to those fields are specified in the array of
> - * xfs_mod_sb structures passed in.  Either all of the specified deltas
> - * will be applied or none of them will.  If any modified field dips below 0,
> - * then all modifications will be backed out and EINVAL will be returned.
> - *
> - * Note that this function may not be used for the superblock values that
> - * are tracked with the in-memory per-cpu counters - a direct call to
> - * xfs_mod_incore_sb is required for these.
> - */
> -int
> -xfs_mod_incore_sb_batch(
> -	struct xfs_mount	*mp,
> -	xfs_mod_sb_t		*msb,
> -	uint			nmsb,
> -	int			rsvd)
> -{
> -	xfs_mod_sb_t		*msbp;
> -	int			error = 0;
> -
> -	/*
> -	 * Loop through the array of mod structures and apply each individually.
> -	 * If any fail, then back out all those which have already been applied.
> -	 * Do all of this within the scope of the m_sb_lock so that all of the
> -	 * changes will be atomic.
> -	 */
> -	spin_lock(&mp->m_sb_lock);
> -	for (msbp = msb; msbp < (msb + nmsb); msbp++) {
> -		ASSERT(msbp->msb_field < XFS_SBS_ICOUNT ||
> -		       msbp->msb_field > XFS_SBS_FDBLOCKS);
> -
> -		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
> -						   msbp->msb_delta, rsvd);
> -		if (error)
> -			goto unwind;
> -	}
> -	spin_unlock(&mp->m_sb_lock);
> -	return 0;
> -
> -unwind:
> -	while (--msbp >= msb) {
> -		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
> -						   -msbp->msb_delta, rsvd);
> -		ASSERT(error == 0);
> -	}
> -	spin_unlock(&mp->m_sb_lock);
> -	return error;
> -}
> -
> -/*
>   * xfs_getsb() is called to obtain the buffer for the superblock.
>   * The buffer is returned locked and read in from disk.
>   * The buffer should be released with a call to xfs_brelse().
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index 8970489..66f28c1 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -249,15 +249,6 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
>  }
>  
>  /*
> - * This structure is for use by the xfs_mod_incore_sb_batch() routine.
> - * xfs_growfs can specify a few fields which are more than int limit
> - */
> -typedef struct xfs_mod_sb {
> -	xfs_sb_field_t	msb_field;	/* Field to modify, see below */
> -	int64_t		msb_delta;	/* Change to make to specified field */
> -} xfs_mod_sb_t;
> -
> -/*
>   * Per-ag incore structure, copies of information in agf and agi, to improve the
>   * performance of allocation group selection.
>   */
> @@ -314,8 +305,6 @@ extern int	xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount,
>  
>  extern void	xfs_unmountfs(xfs_mount_t *);
>  extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
> -extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
> -			uint, int);
>  extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index 4e4bc5a..220ef2c 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -485,6 +485,54 @@ xfs_trans_apply_sb_deltas(
>  				  sizeof(sbp->sb_frextents) - 1);
>  }
>  
> +STATIC int
> +xfs_sb_mod8(
> +	uint8_t			*field,
> +	int8_t			delta)
> +{
> +	int8_t			counter = *field;
> +
> +	counter += delta;
> +	if (counter < 0) {
> +		ASSERT(0);
> +		return -EINVAL;
> +	}
> +	*field = counter;
> +	return 0;
> +}
> +
> +STATIC int
> +xfs_sb_mod32(
> +	uint32_t		*field,
> +	int32_t			delta)
> +{
> +	int32_t			counter = *field;
> +
> +	counter += delta;
> +	if (counter < 0) {
> +		ASSERT(0);
> +		return -EINVAL;
> +	}
> +	*field = counter;
> +	return 0;
> +}
> +
> +STATIC int
> +xfs_sb_mod64(
> +	uint64_t		*field,
> +	int64_t			delta)
> +{
> +	int64_t			counter = *field;
> +
> +	counter += delta;
> +	if (counter < 0) {
> +		ASSERT(0);
> +		return -EINVAL;
> +	}
> +	*field = counter;
> +	return 0;
> +}
> +
>  /*
>   * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
>   * and apply superblock counter changes to the in-core superblock.  The
> @@ -492,13 +540,6 @@ xfs_trans_apply_sb_deltas(
>   * applied to the in-core superblock.  The idea is that that has already been
>   * done.
>   *
> - * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
> - * However, we have to ensure that we only modify each superblock field only
> - * once because the application of the delta values may not be atomic. That can
> - * lead to ENOSPC races occurring if we have two separate modifcations of the
> - * free space counter to put back the entire reservation and then take away
> - * what we used.
> - *
>   * If we are not logging superblock counters, then the inode allocated/free and
>   * used block counts are not updated in the on disk superblock. In this case,
>   * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
> @@ -506,20 +547,15 @@ xfs_trans_apply_sb_deltas(
>   */
>  void
>  xfs_trans_unreserve_and_mod_sb(
> -	xfs_trans_t	*tp)
> +	struct xfs_trans	*tp)
>  {
> -	xfs_mod_sb_t	msb[9];	/* If you add cases, add entries */
> -	xfs_mod_sb_t	*msbp;
> -	xfs_mount_t	*mp = tp->t_mountp;
> -	/* REFERENCED */
> -	int		error;
> -	bool		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
> -	int64_t		blkdelta = 0;
> -	int64_t		rtxdelta = 0;
> -	int64_t		idelta = 0;
> -	int64_t		ifreedelta = 0;
> -
> -	msbp = msb;
> +	struct xfs_mount	*mp = tp->t_mountp;
> +	bool			rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
> +	int64_t			blkdelta = 0;
> +	int64_t			rtxdelta = 0;
> +	int64_t			idelta = 0;
> +	int64_t			ifreedelta = 0;
> +	int			error;
>  
>  	/* calculate deltas */
>  	if (tp->t_blk_res > 0)
> @@ -560,72 +596,90 @@ xfs_trans_unreserve_and_mod_sb(
>  			goto out_undo_icount;
>  	}
>  
> +	if (rtxdelta == 0 && !(tp->t_flags & XFS_TRANS_SB_DIRTY))
> +		return;
> +
>  	/* apply remaining deltas */
> +	spin_lock(&mp->m_sb_lock);
>  	if (rtxdelta) {
> -		error = xfs_mod_frextents(mp, rtxdelta);
> +		error = xfs_sb_mod64(&mp->m_sb.sb_frextents, rtxdelta);

Any reason why we don't continue to use the xfs_mod_frextents() function
introduced in the previous patch? Seems like we should be consistent one
way or the other.

Brian

>  		if (error)
>  			goto out_undo_ifree;
>  	}
>  
> -	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
> -		if (tp->t_dblocks_delta != 0) {
> -			msbp->msb_field = XFS_SBS_DBLOCKS;
> -			msbp->msb_delta = tp->t_dblocks_delta;
> -			msbp++;
> -		}
> -		if (tp->t_agcount_delta != 0) {
> -			msbp->msb_field = XFS_SBS_AGCOUNT;
> -			msbp->msb_delta = tp->t_agcount_delta;
> -			msbp++;
> -		}
> -		if (tp->t_imaxpct_delta != 0) {
> -			msbp->msb_field = XFS_SBS_IMAX_PCT;
> -			msbp->msb_delta = tp->t_imaxpct_delta;
> -			msbp++;
> -		}
> -		if (tp->t_rextsize_delta != 0) {
> -			msbp->msb_field = XFS_SBS_REXTSIZE;
> -			msbp->msb_delta = tp->t_rextsize_delta;
> -			msbp++;
> -		}
> -		if (tp->t_rbmblocks_delta != 0) {
> -			msbp->msb_field = XFS_SBS_RBMBLOCKS;
> -			msbp->msb_delta = tp->t_rbmblocks_delta;
> -			msbp++;
> -		}
> -		if (tp->t_rblocks_delta != 0) {
> -			msbp->msb_field = XFS_SBS_RBLOCKS;
> -			msbp->msb_delta = tp->t_rblocks_delta;
> -			msbp++;
> -		}
> -		if (tp->t_rextents_delta != 0) {
> -			msbp->msb_field = XFS_SBS_REXTENTS;
> -			msbp->msb_delta = tp->t_rextents_delta;
> -			msbp++;
> -		}
> -		if (tp->t_rextslog_delta != 0) {
> -			msbp->msb_field = XFS_SBS_REXTSLOG;
> -			msbp->msb_delta = tp->t_rextslog_delta;
> -			msbp++;
> -		}
> -	}
> -
> -	/*
> -	 * If we need to change anything, do it.
> -	 */
> -	if (msbp > msb) {
> -		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
> -			(uint)(msbp - msb), rsvd);
> +	if (tp->t_dblocks_delta != 0) {
> +		error = xfs_sb_mod64(&mp->m_sb.sb_dblocks, tp->t_dblocks_delta);
>  		if (error)
>  			goto out_undo_frextents;
>  	}
> -
> +	if (tp->t_agcount_delta != 0) {
> +		error = xfs_sb_mod32(&mp->m_sb.sb_agcount, tp->t_agcount_delta);
> +		if (error)
> +			goto out_undo_dblocks;
> +	}
> +	if (tp->t_imaxpct_delta != 0) {
> +		error = xfs_sb_mod8(&mp->m_sb.sb_imax_pct, tp->t_imaxpct_delta);
> +		if (error)
> +			goto out_undo_agcount;
> +	}
> +	if (tp->t_rextsize_delta != 0) {
> +		error = xfs_sb_mod32(&mp->m_sb.sb_rextsize,
> +				     tp->t_rextsize_delta);
> +		if (error)
> +			goto out_undo_imaxpct;
> +	}
> +	if (tp->t_rbmblocks_delta != 0) {
> +		error = xfs_sb_mod32(&mp->m_sb.sb_rbmblocks,
> +				     tp->t_rbmblocks_delta);
> +		if (error)
> +			goto out_undo_rextsize;
> +	}
> +	if (tp->t_rblocks_delta != 0) {
> +		error = xfs_sb_mod64(&mp->m_sb.sb_rblocks, tp->t_rblocks_delta);
> +		if (error)
> +			goto out_undo_rbmblocks;
> +	}
> +	if (tp->t_rextents_delta != 0) {
> +		error = xfs_sb_mod64(&mp->m_sb.sb_rextents,
> +				     tp->t_rextents_delta);
> +		if (error)
> +			goto out_undo_rblocks;
> +	}
> +	if (tp->t_rextslog_delta != 0) {
> +		error = xfs_sb_mod8(&mp->m_sb.sb_rextslog,
> +				     tp->t_rextslog_delta);
> +		if (error)
> +			goto out_undo_rextents;
> +	}
> +	spin_unlock(&mp->m_sb_lock);
>  	return;
>  
> +out_undo_rextents:
> +	if (tp->t_rextents_delta)
> +		xfs_sb_mod64(&mp->m_sb.sb_rextents, -tp->t_rextents_delta);
> +out_undo_rblocks:
> +	if (tp->t_rblocks_delta)
> +		xfs_sb_mod64(&mp->m_sb.sb_rblocks, -tp->t_rblocks_delta);
> +out_undo_rbmblocks:
> +	if (tp->t_rbmblocks_delta)
> +		xfs_sb_mod32(&mp->m_sb.sb_rbmblocks, -tp->t_rbmblocks_delta);
> +out_undo_rextsize:
> +	if (tp->t_rextsize_delta)
> +		xfs_sb_mod32(&mp->m_sb.sb_rextsize, -tp->t_rextsize_delta);
> +out_undo_imaxpct:
> +	if (tp->t_rextsize_delta)
> +		xfs_sb_mod8(&mp->m_sb.sb_imax_pct, -tp->t_imaxpct_delta);
> +out_undo_agcount:
> +	if (tp->t_agcount_delta)
> +		xfs_sb_mod32(&mp->m_sb.sb_agcount, -tp->t_agcount_delta);
> +out_undo_dblocks:
> +	if (tp->t_dblocks_delta)
> +		xfs_sb_mod64(&mp->m_sb.sb_dblocks, -tp->t_dblocks_delta);
>  out_undo_frextents:
>  	if (rtxdelta)
> -		xfs_mod_frextents(mp, -rtxdelta);
> +		xfs_sb_mod64(&mp->m_sb.sb_frextents, -rtxdelta);
>  out_undo_ifree:
> +	spin_unlock(&mp->m_sb_lock);
>  	if (ifreedelta)
>  		xfs_mod_ifree(mp, -ifreedelta);
>  out_undo_icount:
> -- 
> 2.0.0
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 7/7] xfs: remove xfs_mod_incore_sb API
  2015-02-04 20:54 ` [PATCH 7/7] xfs: remove xfs_mod_incore_sb API Dave Chinner
@ 2015-02-05 14:10   ` Brian Foster
  0 siblings, 0 replies; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:10 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 07:54:09AM +1100, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Now that there are no users of the bitfield based incore superblock
> modification API, just remove the whole damn lot of it, including
> all the bitfield definitions. This finally removes a lot of cruft
> that has been around for a long time.
> 
> Credit goes to Christoph Hellwig for providing a great patch
> connecting all the dots to enale us to do this. This patch is
> derived from that work.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_format.h |  62 ---------------------
>  fs/xfs/xfs_fsops.c         |   4 --
>  fs/xfs/xfs_mount.c         | 136 ---------------------------------------------
>  fs/xfs/xfs_mount.h         |   3 +-
>  4 files changed, 1 insertion(+), 204 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
> index 8eb7189..4daaa66 100644
> --- a/fs/xfs/libxfs/xfs_format.h
> +++ b/fs/xfs/libxfs/xfs_format.h
> @@ -264,68 +264,6 @@ typedef struct xfs_dsb {
>  	/* must be padded to 64 bit alignment */
>  } xfs_dsb_t;
>  
> -/*
> - * Sequence number values for the fields.
> - */
> -typedef enum {
> -	XFS_SBS_MAGICNUM, XFS_SBS_BLOCKSIZE, XFS_SBS_DBLOCKS, XFS_SBS_RBLOCKS,
> -	XFS_SBS_REXTENTS, XFS_SBS_UUID, XFS_SBS_LOGSTART, XFS_SBS_ROOTINO,
> -	XFS_SBS_RBMINO, XFS_SBS_RSUMINO, XFS_SBS_REXTSIZE, XFS_SBS_AGBLOCKS,
> -	XFS_SBS_AGCOUNT, XFS_SBS_RBMBLOCKS, XFS_SBS_LOGBLOCKS,
> -	XFS_SBS_VERSIONNUM, XFS_SBS_SECTSIZE, XFS_SBS_INODESIZE,
> -	XFS_SBS_INOPBLOCK, XFS_SBS_FNAME, XFS_SBS_BLOCKLOG,
> -	XFS_SBS_SECTLOG, XFS_SBS_INODELOG, XFS_SBS_INOPBLOG, XFS_SBS_AGBLKLOG,
> -	XFS_SBS_REXTSLOG, XFS_SBS_INPROGRESS, XFS_SBS_IMAX_PCT, XFS_SBS_ICOUNT,
> -	XFS_SBS_IFREE, XFS_SBS_FDBLOCKS, XFS_SBS_FREXTENTS, XFS_SBS_UQUOTINO,
> -	XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
> -	XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
> -	XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
> -	XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_FEATURES_COMPAT,
> -	XFS_SBS_FEATURES_RO_COMPAT, XFS_SBS_FEATURES_INCOMPAT,
> -	XFS_SBS_FEATURES_LOG_INCOMPAT, XFS_SBS_CRC, XFS_SBS_PAD,
> -	XFS_SBS_PQUOTINO, XFS_SBS_LSN,
> -	XFS_SBS_FIELDCOUNT
> -} xfs_sb_field_t;
> -
> -/*
> - * Mask values, defined based on the xfs_sb_field_t values.
> - * Only define the ones we're using.
> - */
> -#define	XFS_SB_MVAL(x)		(1LL << XFS_SBS_ ## x)
> -#define	XFS_SB_UUID		XFS_SB_MVAL(UUID)
> -#define	XFS_SB_FNAME		XFS_SB_MVAL(FNAME)
> -#define	XFS_SB_ROOTINO		XFS_SB_MVAL(ROOTINO)
> -#define	XFS_SB_RBMINO		XFS_SB_MVAL(RBMINO)
> -#define	XFS_SB_RSUMINO		XFS_SB_MVAL(RSUMINO)
> -#define	XFS_SB_VERSIONNUM	XFS_SB_MVAL(VERSIONNUM)
> -#define XFS_SB_UQUOTINO		XFS_SB_MVAL(UQUOTINO)
> -#define XFS_SB_GQUOTINO		XFS_SB_MVAL(GQUOTINO)
> -#define XFS_SB_QFLAGS		XFS_SB_MVAL(QFLAGS)
> -#define XFS_SB_SHARED_VN	XFS_SB_MVAL(SHARED_VN)
> -#define XFS_SB_UNIT		XFS_SB_MVAL(UNIT)
> -#define XFS_SB_WIDTH		XFS_SB_MVAL(WIDTH)
> -#define XFS_SB_ICOUNT		XFS_SB_MVAL(ICOUNT)
> -#define XFS_SB_IFREE		XFS_SB_MVAL(IFREE)
> -#define XFS_SB_FDBLOCKS		XFS_SB_MVAL(FDBLOCKS)
> -#define XFS_SB_FEATURES2	(XFS_SB_MVAL(FEATURES2) | \
> -				 XFS_SB_MVAL(BAD_FEATURES2))
> -#define XFS_SB_FEATURES_COMPAT	XFS_SB_MVAL(FEATURES_COMPAT)
> -#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT)
> -#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT)
> -#define XFS_SB_FEATURES_LOG_INCOMPAT XFS_SB_MVAL(FEATURES_LOG_INCOMPAT)
> -#define XFS_SB_CRC		XFS_SB_MVAL(CRC)
> -#define XFS_SB_PQUOTINO		XFS_SB_MVAL(PQUOTINO)
> -#define	XFS_SB_NUM_BITS		((int)XFS_SBS_FIELDCOUNT)
> -#define	XFS_SB_ALL_BITS		((1LL << XFS_SB_NUM_BITS) - 1)
> -#define	XFS_SB_MOD_BITS		\
> -	(XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
> -	 XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
> -	 XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
> -	 XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \
> -	 XFS_SB_FEATURES_COMPAT | XFS_SB_FEATURES_RO_COMPAT | \
> -	 XFS_SB_FEATURES_INCOMPAT | XFS_SB_FEATURES_LOG_INCOMPAT | \
> -	 XFS_SB_PQUOTINO)
> -
>  
>  /*
>   * Misc. Flags - warning - these will be cleared by xfs_repair unless
> diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> index a45c82b4..6c248bf 100644
> --- a/fs/xfs/xfs_fsops.c
> +++ b/fs/xfs/xfs_fsops.c
> @@ -686,10 +686,6 @@ xfs_reserve_blocks(
>  	 * what to do. This means that the amount of free space can
>  	 * change while we do this, so we need to retry if we end up
>  	 * trying to reserve more space than is available.
> -	 *
> -	 * We also use the xfs_mod_incore_sb() interface so that we
> -	 * don't have to care about whether per cpu counter are
> -	 * enabled, disabled or even compiled in....
>  	 */
>  retry:
>  	spin_lock(&mp->m_sb_lock);
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 9499e88..6e6bc40 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -1218,142 +1218,6 @@ xfs_mod_frextents(
>  }
>  
>  /*
> - * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
> - * a delta to a specified field in the in-core superblock.  Simply
> - * switch on the field indicated and apply the delta to that field.
> - * Fields are not allowed to dip below zero, so if the delta would
> - * do this do not apply it and return EINVAL.
> - *
> - * The m_sb_lock must be held when this routine is called.
> - */
> -STATIC int
> -xfs_mod_incore_sb_unlocked(
> -	xfs_mount_t	*mp,
> -	xfs_sb_field_t	field,
> -	int64_t		delta,
> -	int		rsvd)
> -{
> -	int		scounter;	/* short counter for 32 bit fields */
> -	long long	lcounter;	/* long counter for 64 bit fields */
> -
> -	/*
> -	 * With the in-core superblock spin lock held, switch
> -	 * on the indicated field.  Apply the delta to the
> -	 * proper field.  If the fields value would dip below
> -	 * 0, then do not apply the delta and return EINVAL.
> -	 */
> -	switch (field) {
> -	case XFS_SBS_ICOUNT:
> -	case XFS_SBS_IFREE:
> -	case XFS_SBS_FDBLOCKS:
> -	case XFS_SBS_FREXTENTS:
> -		ASSERT(0);
> -		return -EINVAL;
> -	case XFS_SBS_DBLOCKS:
> -		lcounter = (long long)mp->m_sb.sb_dblocks;
> -		lcounter += delta;
> -		if (lcounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_dblocks = lcounter;
> -		return 0;
> -	case XFS_SBS_AGCOUNT:
> -		scounter = mp->m_sb.sb_agcount;
> -		scounter += delta;
> -		if (scounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_agcount = scounter;
> -		return 0;
> -	case XFS_SBS_IMAX_PCT:
> -		scounter = mp->m_sb.sb_imax_pct;
> -		scounter += delta;
> -		if (scounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_imax_pct = scounter;
> -		return 0;
> -	case XFS_SBS_REXTSIZE:
> -		scounter = mp->m_sb.sb_rextsize;
> -		scounter += delta;
> -		if (scounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_rextsize = scounter;
> -		return 0;
> -	case XFS_SBS_RBMBLOCKS:
> -		scounter = mp->m_sb.sb_rbmblocks;
> -		scounter += delta;
> -		if (scounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_rbmblocks = scounter;
> -		return 0;
> -	case XFS_SBS_RBLOCKS:
> -		lcounter = (long long)mp->m_sb.sb_rblocks;
> -		lcounter += delta;
> -		if (lcounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_rblocks = lcounter;
> -		return 0;
> -	case XFS_SBS_REXTENTS:
> -		lcounter = (long long)mp->m_sb.sb_rextents;
> -		lcounter += delta;
> -		if (lcounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_rextents = lcounter;
> -		return 0;
> -	case XFS_SBS_REXTSLOG:
> -		scounter = mp->m_sb.sb_rextslog;
> -		scounter += delta;
> -		if (scounter < 0) {
> -			ASSERT(0);
> -			return -EINVAL;
> -		}
> -		mp->m_sb.sb_rextslog = scounter;
> -		return 0;
> -	default:
> -		ASSERT(0);
> -		return -EINVAL;
> -	}
> -}
> -
> -/*
> - * xfs_mod_incore_sb() is used to change a field in the in-core
> - * superblock structure by the specified delta.  This modification
> - * is protected by the m_sb_lock.  Just use the xfs_mod_incore_sb_unlocked()
> - * routine to do the work.
> - */
> -int
> -xfs_mod_incore_sb(
> -	struct xfs_mount	*mp,
> -	xfs_sb_field_t		field,
> -	int64_t			delta,
> -	int			rsvd)
> -{
> -	int			status;
> -
> -#ifdef HAVE_PERCPU_SB
> -	ASSERT(field < XFS_SBS_IFREE || field > XFS_SBS_FDBLOCKS);
> -#endif
> -
> -	spin_lock(&mp->m_sb_lock);
> -	status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
> -	spin_unlock(&mp->m_sb_lock);
> -
> -	return status;
> -}
> -
> -/*
>   * xfs_getsb() is called to obtain the buffer for the superblock.
>   * The buffer is returned locked and read in from disk.
>   * The buffer should be released with a call to xfs_brelse().
> diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> index 66f28c1..616e1ba 100644
> --- a/fs/xfs/xfs_mount.h
> +++ b/fs/xfs/xfs_mount.h
> @@ -302,9 +302,8 @@ extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
>  extern int	xfs_mountfs(xfs_mount_t *mp);
>  extern int	xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount,
>  				     xfs_agnumber_t *maxagi);
> -
>  extern void	xfs_unmountfs(xfs_mount_t *);
> -extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
> +
>  extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
>  extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
> -- 
> 2.0.0
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/7] xfs: use generic percpu counters for free block counter
  2015-02-05 14:10   ` Brian Foster
@ 2015-02-05 14:18     ` Brian Foster
  0 siblings, 0 replies; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:18 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

On Thu, Feb 05, 2015 at 09:10:15AM -0500, Brian Foster wrote:
> On Thu, Feb 05, 2015 at 07:54:05AM +1100, Dave Chinner wrote:
> > 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 <dchinner@redhat.com>
> > ---
> >  fs/xfs/libxfs/xfs_bmap.c |  32 ++++----
> >  fs/xfs/libxfs/xfs_sb.c   |   1 +
> >  fs/xfs/xfs_fsops.c       |   9 ++-
> >  fs/xfs/xfs_iomap.c       |   2 +-
> >  fs/xfs/xfs_mount.c       | 193 ++++++++++++++++++++++++-----------------------
> >  fs/xfs/xfs_mount.h       |   3 +
> >  fs/xfs/xfs_super.c       |  10 ++-
> >  fs/xfs/xfs_trans.c       |  16 ++--
> >  8 files changed, 135 insertions(+), 131 deletions(-)
> > 
> > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> > index 61ec015..e39c9e8 100644
> > --- a/fs/xfs/libxfs/xfs_bmap.c
> > +++ b/fs/xfs/libxfs/xfs_bmap.c
> > @@ -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;
> > @@ -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. */
> > @@ -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.
> >  		 */
> > @@ -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;
> >  
> > @@ -4200,7 +4196,7 @@ out_unreserve_blocks:
> >  	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 ?
> > @@ -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;
> > @@ -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);
> > diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
> > index b66aeab..31a3e97 100644
> > --- a/fs/xfs/libxfs/xfs_sb.c
> > +++ b/fs/xfs/libxfs/xfs_sb.c
> > @@ -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);
> > diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> > index fa74d03..fed97a9 100644
> > --- a/fs/xfs/xfs_fsops.c
> > +++ b/fs/xfs/xfs_fsops.c
> > @@ -633,9 +633,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;
> > @@ -710,7 +711,8 @@ retry:
> >  	} 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 */
> >  
> > @@ -749,8 +751,7 @@ out:
> >  		 * 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;
> >  	}
> > diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
> > index ccb1dd0..205b948 100644
> > --- a/fs/xfs/xfs_iomap.c
> > +++ b/fs/xfs/xfs_iomap.c
> > @@ -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])
> > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> > index 650e8f1..9e433b2 100644
> > --- a/fs/xfs/xfs_mount.c
> > +++ b/fs/xfs/xfs_mount.c
> > @@ -1114,7 +1114,6 @@ xfs_mod_icount(
> >  	return 0;
> >  }
> >  
> > -
> >  int
> >  xfs_mod_ifree(
> >  	struct xfs_mount	*mp,
> > @@ -1128,6 +1127,93 @@ xfs_mod_ifree(
> >  	}
> >  	return 0;
> >  }
> > +
> > +int
> > +xfs_mod_fdblocks(
> > +	struct xfs_mount	*mp,
> > +	int64_t			delta,
> > +	bool			rsvd)
> > +{
> > +	int64_t			lcounter;
> > +	long long		res_used;
> > +	s32			batch;
> > +
> > +	if (delta > 0) {
> > +		/*
> > +		 * If the reserve pool is depleted, put blocks back into it
> > +		 * first. Most of the time the pool is full.
> > +		 */
> > +		if (likely(mp->m_resblks == mp->m_resblks_avail)) {
> > +			percpu_counter_add(&mp->m_fdblocks, delta);
> > +			return 0;
> > +		}
> > +
> > +		spin_lock(&mp->m_sb_lock);
> > +		res_used = (long long)
> > +				(mp->m_resblks - mp->m_resblks_avail);
> > +
> > +		if (res_used > delta) {
> > +			mp->m_resblks_avail += delta;
> > +		} else {
> > +			delta -= res_used;
> > +				mp->m_resblks_avail = mp->m_resblks;
> 
> Extra tab on the line above.
> 

Forgot tag, this looks fine otherwise:

Reviewed-by: Brian Foster <bfoster@redhat.com>

> Brian
> 
> > +			percpu_counter_add(&mp->m_fdblocks, delta);
> > +		}
> > +		spin_unlock(&mp->m_sb_lock);
> > +		return 0;
> > +	}
> > +
> > +	/*
> > +	 * Taking blocks away, need to be more accurate the closer we
> > +	 * are to zero.
> > +	 *
> > +	 * batch size is set to a maximum of 1024 blocks - if we are
> > +	 * allocating of freeing extents larger than this then we aren't
> > +	 * going to be hammering the counter lock so a lock per update
> > +	 * is not a problem.
> > +	 *
> > +	 * If the counter has a value of less than 2 * max batch size,
> > +	 * then make everything serialise as we are real close to
> > +	 * ENOSPC.
> > +	 */
> > +#define __BATCH	1024
> > +	if (percpu_counter_compare(&mp->m_fdblocks, 2 * __BATCH) < 0)
> > +		batch = 1;
> > +	else
> > +		batch = __BATCH;
> > +#undef __BATCH
> > +
> > +	__percpu_counter_add(&mp->m_fdblocks, delta, batch);
> > +	if (percpu_counter_compare(&mp->m_fdblocks,
> > +				   XFS_ALLOC_SET_ASIDE(mp)) >= 0) {
> > +		/* we had space! */
> > +		return 0;
> > +	}
> > +
> > +	/*
> > +	 * lock up the sb for dipping into reserves before releasing the space
> > +	 * that took us to ENOSPC.
> > +	 */
> > +	spin_lock(&mp->m_sb_lock);
> > +	percpu_counter_add(&mp->m_fdblocks, -delta);
> > +	if (!rsvd)
> > +		goto fdblocks_enospc;
> > +
> > +	lcounter = (long long)mp->m_resblks_avail + delta;
> > +	if (lcounter >= 0) {
> > +		mp->m_resblks_avail = lcounter;
> > +		spin_unlock(&mp->m_sb_lock);
> > +		return 0;
> > +	}
> > +	printk_once(KERN_WARNING
> > +		"Filesystem \"%s\": reserve blocks depleted! "
> > +		"Consider increasing reserve pool size.",
> > +		mp->m_fsname);
> > +fdblocks_enospc:
> > +	spin_unlock(&mp->m_sb_lock);
> > +	return -ENOSPC;
> > +}
> > +
> >  /*
> >   * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
> >   * a delta to a specified field in the in-core superblock.  Simply
> > @@ -1146,7 +1232,6 @@ xfs_mod_incore_sb_unlocked(
> >  {
> >  	int		scounter;	/* short counter for 32 bit fields */
> >  	long long	lcounter;	/* long counter for 64 bit fields */
> > -	long long	res_used, rem;
> >  
> >  	/*
> >  	 * With the in-core superblock spin lock held, switch
> > @@ -1157,50 +1242,9 @@ xfs_mod_incore_sb_unlocked(
> >  	switch (field) {
> >  	case XFS_SBS_ICOUNT:
> >  	case XFS_SBS_IFREE:
> > +	case XFS_SBS_FDBLOCKS:
> >  		ASSERT(0);
> >  		return -EINVAL;
> > -	case XFS_SBS_FDBLOCKS:
> > -		lcounter = (long long)
> > -			mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> > -		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
> > -
> > -		if (delta > 0) {		/* Putting blocks back */
> > -			if (res_used > delta) {
> > -				mp->m_resblks_avail += delta;
> > -			} else {
> > -				rem = delta - res_used;
> > -				mp->m_resblks_avail = mp->m_resblks;
> > -				lcounter += rem;
> > -			}
> > -		} else {				/* Taking blocks away */
> > -			lcounter += delta;
> > -			if (lcounter >= 0) {
> > -				mp->m_sb.sb_fdblocks = lcounter +
> > -							XFS_ALLOC_SET_ASIDE(mp);
> > -				return 0;
> > -			}
> > -
> > -			/*
> > -			 * We are out of blocks, use any available reserved
> > -			 * blocks if were allowed to.
> > -			 */
> > -			if (!rsvd)
> > -				return -ENOSPC;
> > -
> > -			lcounter = (long long)mp->m_resblks_avail + delta;
> > -			if (lcounter >= 0) {
> > -				mp->m_resblks_avail = lcounter;
> > -				return 0;
> > -			}
> > -			printk_once(KERN_WARNING
> > -				"Filesystem \"%s\": reserve blocks depleted! "
> > -				"Consider increasing reserve pool size.",
> > -				mp->m_fsname);
> > -			return -ENOSPC;
> > -		}
> > -
> > -		mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
> > -		return 0;
> >  	case XFS_SBS_FREXTENTS:
> >  		lcounter = (long long)mp->m_sb.sb_frextents;
> >  		lcounter += delta;
> > @@ -1323,7 +1367,7 @@ xfs_mod_incore_sb(
> >   *
> >   * Note that this function may not be used for the superblock values that
> >   * are tracked with the in-memory per-cpu counters - a direct call to
> > - * xfs_icsb_modify_counters is required for these.
> > + * xfs_mod_incore_sb is required for these.
> >   */
> >  int
> >  xfs_mod_incore_sb_batch(
> > @@ -1508,7 +1552,6 @@ xfs_icsb_cpu_notify(
> >  	case CPU_ONLINE:
> >  	case CPU_ONLINE_FROZEN:
> >  		xfs_icsb_lock(mp);
> > -		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
> >  		xfs_icsb_unlock(mp);
> >  		break;
> >  	case CPU_DEAD:
> > @@ -1518,13 +1561,9 @@ xfs_icsb_cpu_notify(
> >  		 * re-enable the counters. */
> >  		xfs_icsb_lock(mp);
> >  		spin_lock(&mp->m_sb_lock);
> > -		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
> > -
> > -		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
> >  
> >  		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
> >  
> > -		xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
> >  		spin_unlock(&mp->m_sb_lock);
> >  		xfs_icsb_unlock(mp);
> >  		break;
> > @@ -1550,10 +1589,14 @@ xfs_icsb_init_counters(
> >  	if (error)
> >  		goto free_icount;
> >  
> > +	error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
> > +	if (error)
> > +		goto free_ifree;
> > +
> >  	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
> >  	if (!mp->m_sb_cnts) {
> >  		error = -ENOMEM;
> > -		goto free_ifree;
> > +		goto free_fdblocks;
> >  	}
> >  
> >  	for_each_online_cpu(i) {
> > @@ -1577,6 +1620,8 @@ xfs_icsb_init_counters(
> >  
> >  	return 0;
> >  
> > +free_fdblocks:
> > +	percpu_counter_destroy(&mp->m_fdblocks);
> >  free_ifree:
> >  	percpu_counter_destroy(&mp->m_ifree);
> >  free_icount:
> > @@ -1590,6 +1635,7 @@ xfs_icsb_reinit_counters(
> >  {
> >  	percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
> >  	percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
> > +	percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
> >  
> >  	xfs_icsb_lock(mp);
> >  	/*
> > @@ -1597,7 +1643,6 @@ xfs_icsb_reinit_counters(
> >  	 * initial balance kicks us off correctly
> >  	 */
> >  	mp->m_icsb_counters = -1;
> > -	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
> >  	xfs_icsb_unlock(mp);
> >  }
> >  
> > @@ -1612,6 +1657,7 @@ xfs_icsb_destroy_counters(
> >  
> >  	percpu_counter_destroy(&mp->m_icount);
> >  	percpu_counter_destroy(&mp->m_ifree);
> > +	percpu_counter_destroy(&mp->m_fdblocks);
> >  
> >  	mutex_destroy(&mp->m_icsb_mutex);
> >  }
> > @@ -1665,18 +1711,11 @@ xfs_icsb_count(
> >  	xfs_icsb_cnts_t	*cnt,
> >  	int		flags)
> >  {
> > -	xfs_icsb_cnts_t *cntp;
> > -	int		i;
> > -
> >  	memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
> >  
> >  	if (!(flags & XFS_ICSB_LAZY_COUNT))
> >  		xfs_icsb_lock_all_counters(mp);
> >  
> > -	for_each_online_cpu(i) {
> > -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
> > -		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
> > -	}
> >  
> >  	if (!(flags & XFS_ICSB_LAZY_COUNT))
> >  		xfs_icsb_unlock_all_counters(mp);
> > @@ -1687,7 +1726,6 @@ xfs_icsb_counter_disabled(
> >  	xfs_mount_t	*mp,
> >  	xfs_sb_field_t	field)
> >  {
> > -	ASSERT(field == XFS_SBS_FDBLOCKS);
> >  	return test_bit(field, &mp->m_icsb_counters);
> >  }
> >  
> > @@ -1698,8 +1736,6 @@ xfs_icsb_disable_counter(
> >  {
> >  	xfs_icsb_cnts_t	cnt;
> >  
> > -	ASSERT(field == XFS_SBS_FDBLOCKS);
> > -
> >  	/*
> >  	 * If we are already disabled, then there is nothing to do
> >  	 * here. We check before locking all the counters to avoid
> > @@ -1717,9 +1753,6 @@ xfs_icsb_disable_counter(
> >  
> >  		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
> >  		switch(field) {
> > -		case XFS_SBS_FDBLOCKS:
> > -			mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
> > -			break;
> >  		default:
> >  			BUG();
> >  		}
> > @@ -1735,18 +1768,11 @@ xfs_icsb_enable_counter(
> >  	uint64_t	count,
> >  	uint64_t	resid)
> >  {
> > -	xfs_icsb_cnts_t	*cntp;
> >  	int		i;
> >  
> > -	ASSERT(field == XFS_SBS_FDBLOCKS);
> > -
> >  	xfs_icsb_lock_all_counters(mp);
> >  	for_each_online_cpu(i) {
> > -		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
> >  		switch (field) {
> > -		case XFS_SBS_FDBLOCKS:
> > -			cntp->icsb_fdblocks = count + resid;
> > -			break;
> >  		default:
> >  			BUG();
> >  			break;
> > @@ -1765,9 +1791,6 @@ xfs_icsb_sync_counters_locked(
> >  	xfs_icsb_cnts_t	cnt;
> >  
> >  	xfs_icsb_count(mp, &cnt, flags);
> > -
> > -	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
> > -		mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
> >  }
> >  
> >  /*
> > @@ -1809,20 +1832,12 @@ xfs_icsb_balance_counter_locked(
> >  	int		min_per_cpu)
> >  {
> >  	uint64_t	count, resid;
> > -	int		weight = num_online_cpus();
> > -	uint64_t	min = (uint64_t)min_per_cpu;
> >  
> >  	/* disable counter and sync counter */
> >  	xfs_icsb_disable_counter(mp, field);
> >  
> >  	/* update counters  - first CPU gets residual*/
> >  	switch (field) {
> > -	case XFS_SBS_FDBLOCKS:
> > -		count = mp->m_sb.sb_fdblocks;
> > -		resid = do_div(count, weight);
> > -		if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
> > -			return;
> > -		break;
> >  	default:
> >  		BUG();
> >  		count = resid = 0;	/* quiet, gcc */
> > @@ -1851,7 +1866,6 @@ xfs_icsb_modify_counters(
> >  	int		rsvd)
> >  {
> >  	xfs_icsb_cnts_t	*icsbp;
> > -	long long	lcounter;	/* long counter for 64 bit fields */
> >  	int		ret = 0;
> >  
> >  	might_sleep();
> > @@ -1871,18 +1885,9 @@ again:
> >  	}
> >  
> >  	switch (field) {
> > -	case XFS_SBS_FDBLOCKS:
> > -		BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
> > -
> > -		lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> > -		lcounter += delta;
> > -		if (unlikely(lcounter < 0))
> > -			goto balance_counter;
> > -		icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
> > -		break;
> >  	default:
> >  		BUG();
> > -		break;
> > +		goto balance_counter; /* be still, gcc */
> >  	}
> >  	xfs_icsb_unlock_cntr(icsbp);
> >  	preempt_enable();
> > diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
> > index 0cb32ce..76f5d25 100644
> > --- a/fs/xfs/xfs_mount.h
> > +++ b/fs/xfs/xfs_mount.h
> > @@ -85,6 +85,7 @@ typedef struct xfs_mount {
> >  	spinlock_t		m_sb_lock;	/* sb counter lock */
> >  	struct percpu_counter	m_icount;	/* allocated inodes counter */
> >  	struct percpu_counter	m_ifree;	/* free inodes counter */
> > +	struct percpu_counter	m_fdblocks;	/* free block counter */
> >  
> >  	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
> >  	char			*m_fsname;	/* filesystem name */
> > @@ -382,6 +383,8 @@ extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
> >  			uint, int);
> >  extern int	xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
> >  extern int	xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
> > +extern int	xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
> > +				 bool reserved);
> >  extern int	xfs_mount_log_sb(xfs_mount_t *);
> >  extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
> >  extern int	xfs_readsb(xfs_mount_t *, int);
> > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> > index e06aa6b..4c6af31 100644
> > --- a/fs/xfs/xfs_super.c
> > +++ b/fs/xfs/xfs_super.c
> > @@ -1089,6 +1089,7 @@ xfs_fs_statfs(
> >  	__uint64_t		fakeinos, id;
> >  	__uint64_t		icount;
> >  	__uint64_t		ifree;
> > +	__uint64_t		fdblocks;
> >  	xfs_extlen_t		lsize;
> >  	__int64_t		ffree;
> >  
> > @@ -1102,13 +1103,17 @@ xfs_fs_statfs(
> >  	xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
> >  	icount = percpu_counter_sum(&mp->m_icount);
> >  	ifree = percpu_counter_sum(&mp->m_ifree);
> > +	fdblocks = percpu_counter_sum(&mp->m_fdblocks);
> >  
> >  	spin_lock(&mp->m_sb_lock);
> >  	statp->f_bsize = sbp->sb_blocksize;
> >  	lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
> >  	statp->f_blocks = sbp->sb_dblocks - lsize;
> > -	statp->f_bfree = statp->f_bavail =
> > -				sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> > +	spin_unlock(&mp->m_sb_lock);
> > +
> > +	statp->f_bfree = fdblocks - XFS_ALLOC_SET_ASIDE(mp);
> > +	statp->f_bavail = statp->f_bfree;
> > +
> >  	fakeinos = statp->f_bfree << sbp->sb_inopblog;
> >  	statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
> >  	if (mp->m_maxicount)
> > @@ -1120,7 +1125,6 @@ xfs_fs_statfs(
> >  	ffree = statp->f_files - (icount - ifree);
> >  	statp->f_ffree = max_t(__int64_t, ffree, 0);
> >  
> > -	spin_unlock(&mp->m_sb_lock);
> >  
> >  	if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
> >  	    ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) ==
> > diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> > index 68680ce..e99f5e5 100644
> > --- a/fs/xfs/xfs_trans.c
> > +++ b/fs/xfs/xfs_trans.c
> > @@ -173,7 +173,7 @@ xfs_trans_reserve(
> >  	uint			rtextents)
> >  {
> >  	int		error = 0;
> > -	int		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
> > +	bool		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
> >  
> >  	/* Mark this thread as being in a transaction */
> >  	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
> > @@ -184,8 +184,7 @@ xfs_trans_reserve(
> >  	 * fail if the count would go below zero.
> >  	 */
> >  	if (blocks > 0) {
> > -		error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
> > -					  -((int64_t)blocks), rsvd);
> > +		error = xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
> >  		if (error != 0) {
> >  			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
> >  			return -ENOSPC;
> > @@ -268,8 +267,7 @@ undo_log:
> >  
> >  undo_blocks:
> >  	if (blocks > 0) {
> > -		xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
> > -					 (int64_t)blocks, rsvd);
> > +		xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
> >  		tp->t_blk_res = 0;
> >  	}
> >  
> > @@ -516,14 +514,13 @@ xfs_trans_unreserve_and_mod_sb(
> >  	xfs_mount_t	*mp = tp->t_mountp;
> >  	/* REFERENCED */
> >  	int		error;
> > -	int		rsvd;
> > +	bool		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
> >  	int64_t		blkdelta = 0;
> >  	int64_t		rtxdelta = 0;
> >  	int64_t		idelta = 0;
> >  	int64_t		ifreedelta = 0;
> >  
> >  	msbp = msb;
> > -	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
> >  
> >  	/* calculate deltas */
> >  	if (tp->t_blk_res > 0)
> > @@ -547,8 +544,7 @@ xfs_trans_unreserve_and_mod_sb(
> >  
> >  	/* apply the per-cpu counters */
> >  	if (blkdelta) {
> > -		error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
> > -						 blkdelta, rsvd);
> > +		error = xfs_mod_fdblocks(mp, blkdelta, rsvd);
> >  		if (error)
> >  			goto out;
> >  	}
> > @@ -635,7 +631,7 @@ out_undo_icount:
> >  		xfs_mod_icount(mp, -idelta);
> >  out_undo_fdblocks:
> >  	if (blkdelta)
> > -		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
> > +		xfs_mod_fdblocks(mp, -blkdelta, rsvd);
> >  out:
> >  	ASSERT(error == 0);
> >  	return;
> > -- 
> > 2.0.0
> > 
> > _______________________________________________
> > xfs mailing list
> > xfs@oss.sgi.com
> > http://oss.sgi.com/mailman/listinfo/xfs
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 6/7] xfs: replace xfs_mod_incore_sb_batched
  2015-02-05 14:10   ` Brian Foster
@ 2015-02-05 14:19     ` Christoph Hellwig
  2015-02-05 14:27       ` Brian Foster
  0 siblings, 1 reply; 25+ messages in thread
From: Christoph Hellwig @ 2015-02-05 14:19 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs

On Thu, Feb 05, 2015 at 09:10:44AM -0500, Brian Foster wrote:
> >  	/* apply remaining deltas */
> > +	spin_lock(&mp->m_sb_lock);
> >  	if (rtxdelta) {
> > -		error = xfs_mod_frextents(mp, rtxdelta);
> > +		error = xfs_sb_mod64(&mp->m_sb.sb_frextents, rtxdelta);
> 
> Any reason why we don't continue to use the xfs_mod_frextents() function
> introduced in the previous patch? Seems like we should be consistent one
> way or the other.

We're already under the sb_lock and would need another lock roundtrip to
avoid a deadlock in that case.  But mit might be worth to simply make
the real time extent counter a percpu one to behave similar to the other
counters that can be manipulated outside of the transaction commit code.

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 6/7] xfs: replace xfs_mod_incore_sb_batched
  2015-02-05 14:19     ` Christoph Hellwig
@ 2015-02-05 14:27       ` Brian Foster
  0 siblings, 0 replies; 25+ messages in thread
From: Brian Foster @ 2015-02-05 14:27 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfs

On Thu, Feb 05, 2015 at 06:19:54AM -0800, Christoph Hellwig wrote:
> On Thu, Feb 05, 2015 at 09:10:44AM -0500, Brian Foster wrote:
> > >  	/* apply remaining deltas */
> > > +	spin_lock(&mp->m_sb_lock);
> > >  	if (rtxdelta) {
> > > -		error = xfs_mod_frextents(mp, rtxdelta);
> > > +		error = xfs_sb_mod64(&mp->m_sb.sb_frextents, rtxdelta);
> > 
> > Any reason why we don't continue to use the xfs_mod_frextents() function
> > introduced in the previous patch? Seems like we should be consistent one
> > way or the other.
> 
> We're already under the sb_lock and would need another lock roundtrip to
> avoid a deadlock in that case.  But mit might be worth to simply make
> the real time extent counter a percpu one to behave similar to the other
> counters that can be manipulated outside of the transaction commit code.
> 

Ah, thanks... missed that the lock was taken there. This one looks fine
to me as well:

Reviewed-by: Brian Foster <bfoster@redhat.com>

> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 0/7 V2] xfs: use generic percpu counters for icsb
  2015-02-05 14:08 ` [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Brian Foster
@ 2015-02-05 22:18   ` Dave Chinner
  0 siblings, 0 replies; 25+ messages in thread
From: Dave Chinner @ 2015-02-05 22:18 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs

On Thu, Feb 05, 2015 at 09:08:40AM -0500, Brian Foster wrote:
> On Thu, Feb 05, 2015 at 07:54:02AM +1100, Dave Chinner wrote:
> > Hi folks,
> > 
> > This is the second version of the generic per-cpu counter rework
> > patch series. The first version can be found here:
> > 
> > http://oss.sgi.com/archives/xfs/2015-02/msg00000.html
> > 
> > New in V2:
> > 
> > - drop the moving of the struct xfs_sb to xfs_super.h
> > - fixed all the little things that Christoph and Brian noted.
> > - keep the per-cpu counters in the struct xfs_mount and keep the
> >   functions to sync them with the struct xfs_sb values when read
> >   from disk or written to disk.
> > - integrated Christoph Hellwig's additional cleanup patch. This was
> >   done by:
> > 	- intergating xfs_mod_XXX factoring into the relevant percpu
> > 	  counter conversion patch
> > 	- separating out xfs_mod_frextents into it's won patch
> > 	- separating out the replacement of
> > 	  xfs_mod_incore_sb_batched
> > 	- doing all the now unused API removal in a separate patch
> > 
> > The series passes xfstests without regressions, and no scalability
> > issues have been seen in my performance tests on a 16p VM. SGI - you
> > still need to test this, though. :)
> > 
> > Thoughts, comments?
> > 
> 
> All in all this looks pretty good to me save a couple notes pointed out
> in the patches. In a quick test, this handles the imaxct overshoot
> problem Eric noted much better than the current implementation. That
> said, it's still not precise.

Right.

> My understanding is that's fine, but I wonder if we want to tack on a
> variant of Eric's original patch as well so when we still do overshoot
> imaxpct (albeit by much less than before: I reproduce an overshoot of
> <100 inodes vs several thousand) we at least report an accurate inode
> count. Thoughts?

Yes, Eric's patch is still necessary.

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/7] xfs: use generic percpu counters for inode counter
  2015-02-04 20:54 ` [PATCH 1/7] xfs: use generic percpu counters for inode counter Dave Chinner
  2015-02-05 14:09   ` Brian Foster
@ 2015-02-23 20:55   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Christoph Hellwig @ 2015-02-23 20:55 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/7] xfs: use generic percpu counters for free inode counter
  2015-02-04 20:54 ` [PATCH 2/7] xfs: use generic percpu counters for free " Dave Chinner
  2015-02-05 14:10   ` Brian Foster
@ 2015-02-23 20:56   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Christoph Hellwig @ 2015-02-23 20:56 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/7] xfs: use generic percpu counters for free block counter
  2015-02-04 20:54 ` [PATCH 3/7] xfs: use generic percpu counters for free block counter Dave Chinner
  2015-02-05 14:10   ` Brian Foster
@ 2015-02-23 20:57   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Christoph Hellwig @ 2015-02-23 20:57 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 4/7] xfs: Remove icsb infrastructure
  2015-02-04 20:54 ` [PATCH 4/7] xfs: Remove icsb infrastructure Dave Chinner
  2015-02-05 14:10   ` Brian Foster
@ 2015-02-23 20:59   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Christoph Hellwig @ 2015-02-23 20:59 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

Although it might be worth mentining that you moved the put_super
implementation around in the changelog.

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 5/7] xfs: introduce xfs_mod_frextents
  2015-02-04 20:54 ` [PATCH 5/7] xfs: introduce xfs_mod_frextents Dave Chinner
  2015-02-05 14:10   ` Brian Foster
@ 2015-02-23 21:02   ` Christoph Hellwig
  1 sibling, 0 replies; 25+ messages in thread
From: Christoph Hellwig @ 2015-02-23 21:02 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs

This and the next two are basically just a rebase of my patch, so
I not Reviewed-by as I can't really be reviewing my own code :)

But the rebased versions still look fine to me.

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2015-02-23 21:02 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-04 20:54 [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Dave Chinner
2015-02-04 20:54 ` [PATCH 1/7] xfs: use generic percpu counters for inode counter Dave Chinner
2015-02-05 14:09   ` Brian Foster
2015-02-23 20:55   ` Christoph Hellwig
2015-02-04 20:54 ` [PATCH 2/7] xfs: use generic percpu counters for free " Dave Chinner
2015-02-05 14:10   ` Brian Foster
2015-02-23 20:56   ` Christoph Hellwig
2015-02-04 20:54 ` [PATCH 3/7] xfs: use generic percpu counters for free block counter Dave Chinner
2015-02-05 14:10   ` Brian Foster
2015-02-05 14:18     ` Brian Foster
2015-02-23 20:57   ` Christoph Hellwig
2015-02-04 20:54 ` [PATCH 4/7] xfs: Remove icsb infrastructure Dave Chinner
2015-02-05 14:10   ` Brian Foster
2015-02-23 20:59   ` Christoph Hellwig
2015-02-04 20:54 ` [PATCH 5/7] xfs: introduce xfs_mod_frextents Dave Chinner
2015-02-05 14:10   ` Brian Foster
2015-02-23 21:02   ` Christoph Hellwig
2015-02-04 20:54 ` [PATCH 6/7] xfs: replace xfs_mod_incore_sb_batched Dave Chinner
2015-02-05 14:10   ` Brian Foster
2015-02-05 14:19     ` Christoph Hellwig
2015-02-05 14:27       ` Brian Foster
2015-02-04 20:54 ` [PATCH 7/7] xfs: remove xfs_mod_incore_sb API Dave Chinner
2015-02-05 14:10   ` Brian Foster
2015-02-05 14:08 ` [PATCH 0/7 V2] xfs: use generic percpu counters for icsb Brian Foster
2015-02-05 22:18   ` Dave Chinner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.