aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2015-02-23 05:19:28 -0500
committerDave Chinner <david@fromorbit.com>2015-02-23 05:19:28 -0500
commit501ab32387533924b211cacff36d19296414ec0b (patch)
tree47f131ce9bc31ae20949706a18d351b68944e581 /fs/xfs
parentc517d838eb7d07bbe9507871fab3931deccff539 (diff)
xfs: use generic percpu counters for inode counter
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> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c6
-rw-r--r--fs/xfs/libxfs/xfs_sb.c2
-rw-r--r--fs/xfs/xfs_fsops.c3
-rw-r--r--fs/xfs/xfs_mount.c76
-rw-r--r--fs/xfs/xfs_mount.h7
-rw-r--r--fs/xfs/xfs_super.c7
-rw-r--r--fs/xfs/xfs_trans.c5
7 files changed, 54 insertions, 52 deletions
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 116ef1ddb3e3..5b4ba9f6b37d 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -376,7 +376,8 @@ xfs_ialloc_ag_alloc(
376 */ 376 */
377 newlen = args.mp->m_ialloc_inos; 377 newlen = args.mp->m_ialloc_inos;
378 if (args.mp->m_maxicount && 378 if (args.mp->m_maxicount &&
379 args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount) 379 percpu_counter_read(&args.mp->m_icount) + newlen >
380 args.mp->m_maxicount)
380 return -ENOSPC; 381 return -ENOSPC;
381 args.minlen = args.maxlen = args.mp->m_ialloc_blks; 382 args.minlen = args.maxlen = args.mp->m_ialloc_blks;
382 /* 383 /*
@@ -1340,7 +1341,8 @@ xfs_dialloc(
1340 * inode. 1341 * inode.
1341 */ 1342 */
1342 if (mp->m_maxicount && 1343 if (mp->m_maxicount &&
1343 mp->m_sb.sb_icount + mp->m_ialloc_inos > mp->m_maxicount) { 1344 percpu_counter_read(&mp->m_icount) + mp->m_ialloc_inos >
1345 mp->m_maxicount) {
1344 noroom = 1; 1346 noroom = 1;
1345 okalloc = 0; 1347 okalloc = 0;
1346 } 1348 }
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index b0a5fe95a3e2..017cb2fc53eb 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -771,6 +771,8 @@ xfs_log_sb(
771 struct xfs_mount *mp = tp->t_mountp; 771 struct xfs_mount *mp = tp->t_mountp;
772 struct xfs_buf *bp = xfs_trans_getsb(tp, mp, 0); 772 struct xfs_buf *bp = xfs_trans_getsb(tp, mp, 0);
773 773
774 mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
775
774 xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); 776 xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);
775 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); 777 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
776 xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb)); 778 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 74efe5b760dc..b87a6f92263b 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -638,11 +638,12 @@ xfs_fs_counts(
638 xfs_fsop_counts_t *cnt) 638 xfs_fsop_counts_t *cnt)
639{ 639{
640 xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); 640 xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
641 cnt->allocino = percpu_counter_read_positive(&mp->m_icount);
642
641 spin_lock(&mp->m_sb_lock); 643 spin_lock(&mp->m_sb_lock);
642 cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); 644 cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
643 cnt->freertx = mp->m_sb.sb_frextents; 645 cnt->freertx = mp->m_sb.sb_frextents;
644 cnt->freeino = mp->m_sb.sb_ifree; 646 cnt->freeino = mp->m_sb.sb_ifree;
645 cnt->allocino = mp->m_sb.sb_icount;
646 spin_unlock(&mp->m_sb_lock); 647 spin_unlock(&mp->m_sb_lock);
647 return 0; 648 return 0;
648} 649}
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 4fa80e63eea2..702ea6a7e648 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1099,6 +1099,21 @@ xfs_log_sbcount(xfs_mount_t *mp)
1099 return xfs_sync_sb(mp, true); 1099 return xfs_sync_sb(mp, true);
1100} 1100}
1101 1101
1102int
1103xfs_mod_icount(
1104 struct xfs_mount *mp,
1105 int64_t delta)
1106{
1107 /* deltas are +/-64, hence the large batch size of 128. */
1108 __percpu_counter_add(&mp->m_icount, delta, 128);
1109 if (percpu_counter_compare(&mp->m_icount, 0) < 0) {
1110 ASSERT(0);
1111 percpu_counter_add(&mp->m_icount, -delta);
1112 return -EINVAL;
1113 }
1114 return 0;
1115}
1116
1102/* 1117/*
1103 * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply 1118 * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
1104 * a delta to a specified field in the in-core superblock. Simply 1119 * a delta to a specified field in the in-core superblock. Simply
@@ -1127,14 +1142,8 @@ xfs_mod_incore_sb_unlocked(
1127 */ 1142 */
1128 switch (field) { 1143 switch (field) {
1129 case XFS_SBS_ICOUNT: 1144 case XFS_SBS_ICOUNT:
1130 lcounter = (long long)mp->m_sb.sb_icount; 1145 ASSERT(0);
1131 lcounter += delta; 1146 return -ENOSPC;
1132 if (lcounter < 0) {
1133 ASSERT(0);
1134 return -EINVAL;
1135 }
1136 mp->m_sb.sb_icount = lcounter;
1137 return 0;
1138 case XFS_SBS_IFREE: 1147 case XFS_SBS_IFREE:
1139 lcounter = (long long)mp->m_sb.sb_ifree; 1148 lcounter = (long long)mp->m_sb.sb_ifree;
1140 lcounter += delta; 1149 lcounter += delta;
@@ -1288,8 +1297,9 @@ xfs_mod_incore_sb(
1288 int status; 1297 int status;
1289 1298
1290#ifdef HAVE_PERCPU_SB 1299#ifdef HAVE_PERCPU_SB
1291 ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS); 1300 ASSERT(field < XFS_SBS_IFREE || field > XFS_SBS_FDBLOCKS);
1292#endif 1301#endif
1302
1293 spin_lock(&mp->m_sb_lock); 1303 spin_lock(&mp->m_sb_lock);
1294 status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); 1304 status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
1295 spin_unlock(&mp->m_sb_lock); 1305 spin_unlock(&mp->m_sb_lock);
@@ -1492,7 +1502,6 @@ xfs_icsb_cpu_notify(
1492 case CPU_ONLINE: 1502 case CPU_ONLINE:
1493 case CPU_ONLINE_FROZEN: 1503 case CPU_ONLINE_FROZEN:
1494 xfs_icsb_lock(mp); 1504 xfs_icsb_lock(mp);
1495 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
1496 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); 1505 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
1497 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); 1506 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
1498 xfs_icsb_unlock(mp); 1507 xfs_icsb_unlock(mp);
@@ -1504,17 +1513,14 @@ xfs_icsb_cpu_notify(
1504 * re-enable the counters. */ 1513 * re-enable the counters. */
1505 xfs_icsb_lock(mp); 1514 xfs_icsb_lock(mp);
1506 spin_lock(&mp->m_sb_lock); 1515 spin_lock(&mp->m_sb_lock);
1507 xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
1508 xfs_icsb_disable_counter(mp, XFS_SBS_IFREE); 1516 xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
1509 xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS); 1517 xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
1510 1518
1511 mp->m_sb.sb_icount += cntp->icsb_icount;
1512 mp->m_sb.sb_ifree += cntp->icsb_ifree; 1519 mp->m_sb.sb_ifree += cntp->icsb_ifree;
1513 mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks; 1520 mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
1514 1521
1515 memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); 1522 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
1516 1523
1517 xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
1518 xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0); 1524 xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
1519 xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0); 1525 xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
1520 spin_unlock(&mp->m_sb_lock); 1526 spin_unlock(&mp->m_sb_lock);
@@ -1531,11 +1537,18 @@ xfs_icsb_init_counters(
1531 xfs_mount_t *mp) 1537 xfs_mount_t *mp)
1532{ 1538{
1533 xfs_icsb_cnts_t *cntp; 1539 xfs_icsb_cnts_t *cntp;
1540 int error;
1534 int i; 1541 int i;
1535 1542
1543 error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
1544 if (error)
1545 return error;
1546
1536 mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t); 1547 mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
1537 if (mp->m_sb_cnts == NULL) 1548 if (!mp->m_sb_cnts) {
1549 percpu_counter_destroy(&mp->m_icount);
1538 return -ENOMEM; 1550 return -ENOMEM;
1551 }
1539 1552
1540 for_each_online_cpu(i) { 1553 for_each_online_cpu(i) {
1541 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 1554 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
@@ -1563,13 +1576,14 @@ void
1563xfs_icsb_reinit_counters( 1576xfs_icsb_reinit_counters(
1564 xfs_mount_t *mp) 1577 xfs_mount_t *mp)
1565{ 1578{
1579 percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
1580
1566 xfs_icsb_lock(mp); 1581 xfs_icsb_lock(mp);
1567 /* 1582 /*
1568 * start with all counters disabled so that the 1583 * start with all counters disabled so that the
1569 * initial balance kicks us off correctly 1584 * initial balance kicks us off correctly
1570 */ 1585 */
1571 mp->m_icsb_counters = -1; 1586 mp->m_icsb_counters = -1;
1572 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
1573 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); 1587 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
1574 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); 1588 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
1575 xfs_icsb_unlock(mp); 1589 xfs_icsb_unlock(mp);
@@ -1583,6 +1597,9 @@ xfs_icsb_destroy_counters(
1583 unregister_hotcpu_notifier(&mp->m_icsb_notifier); 1597 unregister_hotcpu_notifier(&mp->m_icsb_notifier);
1584 free_percpu(mp->m_sb_cnts); 1598 free_percpu(mp->m_sb_cnts);
1585 } 1599 }
1600
1601 percpu_counter_destroy(&mp->m_icount);
1602
1586 mutex_destroy(&mp->m_icsb_mutex); 1603 mutex_destroy(&mp->m_icsb_mutex);
1587} 1604}
1588 1605
@@ -1645,7 +1662,6 @@ xfs_icsb_count(
1645 1662
1646 for_each_online_cpu(i) { 1663 for_each_online_cpu(i) {
1647 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 1664 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
1648 cnt->icsb_icount += cntp->icsb_icount;
1649 cnt->icsb_ifree += cntp->icsb_ifree; 1665 cnt->icsb_ifree += cntp->icsb_ifree;
1650 cnt->icsb_fdblocks += cntp->icsb_fdblocks; 1666 cnt->icsb_fdblocks += cntp->icsb_fdblocks;
1651 } 1667 }
@@ -1659,7 +1675,7 @@ xfs_icsb_counter_disabled(
1659 xfs_mount_t *mp, 1675 xfs_mount_t *mp,
1660 xfs_sb_field_t field) 1676 xfs_sb_field_t field)
1661{ 1677{
1662 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); 1678 ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
1663 return test_bit(field, &mp->m_icsb_counters); 1679 return test_bit(field, &mp->m_icsb_counters);
1664} 1680}
1665 1681
@@ -1670,7 +1686,7 @@ xfs_icsb_disable_counter(
1670{ 1686{
1671 xfs_icsb_cnts_t cnt; 1687 xfs_icsb_cnts_t cnt;
1672 1688
1673 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); 1689 ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
1674 1690
1675 /* 1691 /*
1676 * If we are already disabled, then there is nothing to do 1692 * If we are already disabled, then there is nothing to do
@@ -1689,9 +1705,6 @@ xfs_icsb_disable_counter(
1689 1705
1690 xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT); 1706 xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
1691 switch(field) { 1707 switch(field) {
1692 case XFS_SBS_ICOUNT:
1693 mp->m_sb.sb_icount = cnt.icsb_icount;
1694 break;
1695 case XFS_SBS_IFREE: 1708 case XFS_SBS_IFREE:
1696 mp->m_sb.sb_ifree = cnt.icsb_ifree; 1709 mp->m_sb.sb_ifree = cnt.icsb_ifree;
1697 break; 1710 break;
@@ -1716,15 +1729,12 @@ xfs_icsb_enable_counter(
1716 xfs_icsb_cnts_t *cntp; 1729 xfs_icsb_cnts_t *cntp;
1717 int i; 1730 int i;
1718 1731
1719 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); 1732 ASSERT((field >= XFS_SBS_IFREE) && (field <= XFS_SBS_FDBLOCKS));
1720 1733
1721 xfs_icsb_lock_all_counters(mp); 1734 xfs_icsb_lock_all_counters(mp);
1722 for_each_online_cpu(i) { 1735 for_each_online_cpu(i) {
1723 cntp = per_cpu_ptr(mp->m_sb_cnts, i); 1736 cntp = per_cpu_ptr(mp->m_sb_cnts, i);
1724 switch (field) { 1737 switch (field) {
1725 case XFS_SBS_ICOUNT:
1726 cntp->icsb_icount = count + resid;
1727 break;
1728 case XFS_SBS_IFREE: 1738 case XFS_SBS_IFREE:
1729 cntp->icsb_ifree = count + resid; 1739 cntp->icsb_ifree = count + resid;
1730 break; 1740 break;
@@ -1750,8 +1760,6 @@ xfs_icsb_sync_counters_locked(
1750 1760
1751 xfs_icsb_count(mp, &cnt, flags); 1761 xfs_icsb_count(mp, &cnt, flags);
1752 1762
1753 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
1754 mp->m_sb.sb_icount = cnt.icsb_icount;
1755 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE)) 1763 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
1756 mp->m_sb.sb_ifree = cnt.icsb_ifree; 1764 mp->m_sb.sb_ifree = cnt.icsb_ifree;
1757 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS)) 1765 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
@@ -1805,12 +1813,6 @@ xfs_icsb_balance_counter_locked(
1805 1813
1806 /* update counters - first CPU gets residual*/ 1814 /* update counters - first CPU gets residual*/
1807 switch (field) { 1815 switch (field) {
1808 case XFS_SBS_ICOUNT:
1809 count = mp->m_sb.sb_icount;
1810 resid = do_div(count, weight);
1811 if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
1812 return;
1813 break;
1814 case XFS_SBS_IFREE: 1816 case XFS_SBS_IFREE:
1815 count = mp->m_sb.sb_ifree; 1817 count = mp->m_sb.sb_ifree;
1816 resid = do_div(count, weight); 1818 resid = do_div(count, weight);
@@ -1871,14 +1873,6 @@ again:
1871 } 1873 }
1872 1874
1873 switch (field) { 1875 switch (field) {
1874 case XFS_SBS_ICOUNT:
1875 lcounter = icsbp->icsb_icount;
1876 lcounter += delta;
1877 if (unlikely(lcounter < 0))
1878 goto balance_counter;
1879 icsbp->icsb_icount = lcounter;
1880 break;
1881
1882 case XFS_SBS_IFREE: 1876 case XFS_SBS_IFREE:
1883 lcounter = icsbp->icsb_ifree; 1877 lcounter = icsbp->icsb_ifree;
1884 lcounter += delta; 1878 lcounter += delta;
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 0d8abd6364d9..76b18c8c58c5 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -41,7 +41,6 @@ struct xfs_da_geometry;
41typedef struct xfs_icsb_cnts { 41typedef struct xfs_icsb_cnts {
42 uint64_t icsb_fdblocks; 42 uint64_t icsb_fdblocks;
43 uint64_t icsb_ifree; 43 uint64_t icsb_ifree;
44 uint64_t icsb_icount;
45 unsigned long icsb_flags; 44 unsigned long icsb_flags;
46} xfs_icsb_cnts_t; 45} xfs_icsb_cnts_t;
47 46
@@ -81,8 +80,11 @@ typedef struct xfs_mount {
81 struct super_block *m_super; 80 struct super_block *m_super;
82 xfs_tid_t m_tid; /* next unused tid for fs */ 81 xfs_tid_t m_tid; /* next unused tid for fs */
83 struct xfs_ail *m_ail; /* fs active log item list */ 82 struct xfs_ail *m_ail; /* fs active log item list */
84 xfs_sb_t m_sb; /* copy of fs superblock */ 83
84 struct xfs_sb m_sb; /* copy of fs superblock */
85 spinlock_t m_sb_lock; /* sb counter lock */ 85 spinlock_t m_sb_lock; /* sb counter lock */
86 struct percpu_counter m_icount; /* allocated inodes counter */
87
86 struct xfs_buf *m_sb_bp; /* buffer for superblock */ 88 struct xfs_buf *m_sb_bp; /* buffer for superblock */
87 char *m_fsname; /* filesystem name */ 89 char *m_fsname; /* filesystem name */
88 int m_fsname_len; /* strlen of fs name */ 90 int m_fsname_len; /* strlen of fs name */
@@ -388,6 +390,7 @@ extern void xfs_unmountfs(xfs_mount_t *);
388extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int); 390extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
389extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, 391extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
390 uint, int); 392 uint, int);
393extern int xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
391extern int xfs_mount_log_sb(xfs_mount_t *); 394extern int xfs_mount_log_sb(xfs_mount_t *);
392extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); 395extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
393extern int xfs_readsb(xfs_mount_t *, int); 396extern int xfs_readsb(xfs_mount_t *, int);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 8fcc4ccc5c79..0aa4428bfa31 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1085,6 +1085,7 @@ xfs_fs_statfs(
1085 xfs_sb_t *sbp = &mp->m_sb; 1085 xfs_sb_t *sbp = &mp->m_sb;
1086 struct xfs_inode *ip = XFS_I(dentry->d_inode); 1086 struct xfs_inode *ip = XFS_I(dentry->d_inode);
1087 __uint64_t fakeinos, id; 1087 __uint64_t fakeinos, id;
1088 __uint64_t icount;
1088 xfs_extlen_t lsize; 1089 xfs_extlen_t lsize;
1089 __int64_t ffree; 1090 __int64_t ffree;
1090 1091
@@ -1096,6 +1097,7 @@ xfs_fs_statfs(
1096 statp->f_fsid.val[1] = (u32)(id >> 32); 1097 statp->f_fsid.val[1] = (u32)(id >> 32);
1097 1098
1098 xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); 1099 xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
1100 icount = percpu_counter_sum(&mp->m_icount);
1099 1101
1100 spin_lock(&mp->m_sb_lock); 1102 spin_lock(&mp->m_sb_lock);
1101 statp->f_bsize = sbp->sb_blocksize; 1103 statp->f_bsize = sbp->sb_blocksize;
@@ -1104,8 +1106,7 @@ xfs_fs_statfs(
1104 statp->f_bfree = statp->f_bavail = 1106 statp->f_bfree = statp->f_bavail =
1105 sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); 1107 sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
1106 fakeinos = statp->f_bfree << sbp->sb_inopblog; 1108 fakeinos = statp->f_bfree << sbp->sb_inopblog;
1107 statp->f_files = 1109 statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
1108 MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
1109 if (mp->m_maxicount) 1110 if (mp->m_maxicount)
1110 statp->f_files = min_t(typeof(statp->f_files), 1111 statp->f_files = min_t(typeof(statp->f_files),
1111 statp->f_files, 1112 statp->f_files,
@@ -1117,7 +1118,7 @@ xfs_fs_statfs(
1117 sbp->sb_icount); 1118 sbp->sb_icount);
1118 1119
1119 /* make sure statp->f_ffree does not underflow */ 1120 /* make sure statp->f_ffree does not underflow */
1120 ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree); 1121 ffree = statp->f_files - (icount - sbp->sb_ifree);
1121 statp->f_ffree = max_t(__int64_t, ffree, 0); 1122 statp->f_ffree = max_t(__int64_t, ffree, 0);
1122 1123
1123 spin_unlock(&mp->m_sb_lock); 1124 spin_unlock(&mp->m_sb_lock);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index eb90cd59a0ec..9bc742b65f24 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -554,8 +554,7 @@ xfs_trans_unreserve_and_mod_sb(
554 } 554 }
555 555
556 if (idelta) { 556 if (idelta) {
557 error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, 557 error = xfs_mod_icount(mp, idelta);
558 idelta, rsvd);
559 if (error) 558 if (error)
560 goto out_undo_fdblocks; 559 goto out_undo_fdblocks;
561 } 560 }
@@ -634,7 +633,7 @@ out_undo_ifreecount:
634 xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd); 633 xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
635out_undo_icount: 634out_undo_icount:
636 if (idelta) 635 if (idelta)
637 xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd); 636 xfs_mod_icount(mp, -idelta);
638out_undo_fdblocks: 637out_undo_fdblocks:
639 if (blkdelta) 638 if (blkdelta)
640 xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd); 639 xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);