xfs: use percpu_counter_read_positive for mp->m_icount

Function percpu_counter_read just return the current counter, which can be
negative. This will cause the checking of "allocated inode
counts <= m_maxicount" false positive. Use percpu_counter_read_positive can
solve this problem, and be consistent with the purpose to introduce percpu
mechanism to xfs.

Signed-off-by: George Wang <xuw2015@gmail.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>


diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index 25f7508..ffc3e45 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -173,8 +173,9 @@
 #define rcu_read_unlock()	((void) 0)
 #define WARN_ON_ONCE(expr)	((void) 0)
 
-#define percpu_counter_read(x)	(*x)
-#define percpu_counter_sum(x)	(*x)
+#define percpu_counter_read(x)		(*x)
+#define percpu_counter_read_positive(x)	((*x) > 0 ? (*x) : 0)
+#define percpu_counter_sum(x)		(*x)
 
 /*
  * prandom_u32 is used for di_gen inode allocation, it must be zero for libxfs
diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c
index 5e512be..b57f89a 100644
--- a/libxfs/xfs_ialloc.c
+++ b/libxfs/xfs_ialloc.c
@@ -621,7 +621,7 @@
 	 */
 	newlen = args.mp->m_ialloc_inos;
 	if (args.mp->m_maxicount &&
-	    percpu_counter_read(&args.mp->m_icount) + newlen >
+	    percpu_counter_read_positive(&args.mp->m_icount) + newlen >
 							args.mp->m_maxicount)
 		return -ENOSPC;
 	args.minlen = args.maxlen = args.mp->m_ialloc_blks;
@@ -1699,10 +1699,13 @@
 	 * If we have already hit the ceiling of inode blocks then clear
 	 * okalloc so we scan all available agi structures for a free
 	 * inode.
+	 *
+	 * Read rough value of mp->m_icount by percpu_counter_read_positive,
+	 * which will sacrifice the preciseness but improve the performance.
 	 */
 	if (mp->m_maxicount &&
-	    percpu_counter_read(&mp->m_icount) + mp->m_ialloc_inos >
-							mp->m_maxicount) {
+	    percpu_counter_read_positive(&mp->m_icount) + mp->m_ialloc_inos
+							> mp->m_maxicount) {
 		noroom = 1;
 		okalloc = 0;
 	}