aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid Chinner <dgc@sgi.com>2006-03-13 21:29:16 -0500
committerNathan Scott <nathans@sgi.com>2006-03-13 21:29:16 -0500
commit01e1b69cfcdcfdd5b405165eaba29428f8b18a7c (patch)
tree3ca7e8d0047ff03ca532f39b0fc4cd50381e8ecc /fs
parent87cbc49cd4b773a972bce56c5dd09c4717f3285b (diff)
[XFS] using a spinlock per cpu for superblock counter exclusion results in
a preēmpt counter overflow at 256p and above. Change the exclusion mechanism to use atomic bit operations and busy wait loops to emulate the spin lock exclusion mechanism but without the preempt count issues. SGI-PV: 950027 SGI-Modid: xfs-linux-melb:xfs-kern:25338a Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h1
-rw-r--r--fs/xfs/xfs_mount.c37
-rw-r--r--fs/xfs/xfs_mount.h4
3 files changed, 28 insertions, 14 deletions
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 9fdc14cffb70..bd88ccb0cad0 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -75,6 +75,7 @@
75#include <linux/sort.h> 75#include <linux/sort.h>
76#include <linux/cpu.h> 76#include <linux/cpu.h>
77#include <linux/notifier.h> 77#include <linux/notifier.h>
78#include <linux/delay.h>
78 79
79#include <asm/page.h> 80#include <asm/page.h>
80#include <asm/div64.h> 81#include <asm/div64.h>
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index a64110b9023b..d62aee027368 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1746,10 +1746,7 @@ xfs_icsb_cpu_notify(
1746 case CPU_UP_PREPARE: 1746 case CPU_UP_PREPARE:
1747 /* Easy Case - initialize the area and locks, and 1747 /* Easy Case - initialize the area and locks, and
1748 * then rebalance when online does everything else for us. */ 1748 * then rebalance when online does everything else for us. */
1749 spin_lock_init(&cntp->icsb_lock); 1749 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
1750 cntp->icsb_icount = 0;
1751 cntp->icsb_ifree = 0;
1752 cntp->icsb_fdblocks = 0;
1753 break; 1750 break;
1754 case CPU_ONLINE: 1751 case CPU_ONLINE:
1755 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); 1752 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
@@ -1769,9 +1766,7 @@ xfs_icsb_cpu_notify(
1769 mp->m_sb.sb_ifree += cntp->icsb_ifree; 1766 mp->m_sb.sb_ifree += cntp->icsb_ifree;
1770 mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks; 1767 mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
1771 1768
1772 cntp->icsb_icount = 0; 1769 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
1773 cntp->icsb_ifree = 0;
1774 cntp->icsb_fdblocks = 0;
1775 1770
1776 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED); 1771 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED);
1777 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED); 1772 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED);
@@ -1800,7 +1795,7 @@ xfs_icsb_init_counters(
1800 1795
1801 for_each_online_cpu(i) { 1796 for_each_online_cpu(i) {
1802 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 1797 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
1803 spin_lock_init(&cntp->icsb_lock); 1798 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
1804 } 1799 }
1805 /* 1800 /*
1806 * start with all counters disabled so that the 1801 * start with all counters disabled so that the
@@ -1820,6 +1815,22 @@ xfs_icsb_destroy_counters(
1820 } 1815 }
1821} 1816}
1822 1817
1818STATIC inline void
1819xfs_icsb_lock_cntr(
1820 xfs_icsb_cnts_t *icsbp)
1821{
1822 while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
1823 ndelay(1000);
1824 }
1825}
1826
1827STATIC inline void
1828xfs_icsb_unlock_cntr(
1829 xfs_icsb_cnts_t *icsbp)
1830{
1831 clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
1832}
1833
1823 1834
1824STATIC inline void 1835STATIC inline void
1825xfs_icsb_lock_all_counters( 1836xfs_icsb_lock_all_counters(
@@ -1830,7 +1841,7 @@ xfs_icsb_lock_all_counters(
1830 1841
1831 for_each_online_cpu(i) { 1842 for_each_online_cpu(i) {
1832 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 1843 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
1833 spin_lock(&cntp->icsb_lock); 1844 xfs_icsb_lock_cntr(cntp);
1834 } 1845 }
1835} 1846}
1836 1847
@@ -1843,7 +1854,7 @@ xfs_icsb_unlock_all_counters(
1843 1854
1844 for_each_online_cpu(i) { 1855 for_each_online_cpu(i) {
1845 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 1856 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
1846 spin_unlock(&cntp->icsb_lock); 1857 xfs_icsb_unlock_cntr(cntp);
1847 } 1858 }
1848} 1859}
1849 1860
@@ -2070,7 +2081,7 @@ xfs_icsb_modify_counters_int(
2070again: 2081again:
2071 cpu = get_cpu(); 2082 cpu = get_cpu();
2072 icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu), 2083 icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu),
2073 spin_lock(&icsbp->icsb_lock); 2084 xfs_icsb_lock_cntr(icsbp);
2074 if (unlikely(xfs_icsb_counter_disabled(mp, field))) 2085 if (unlikely(xfs_icsb_counter_disabled(mp, field)))
2075 goto slow_path; 2086 goto slow_path;
2076 2087
@@ -2104,7 +2115,7 @@ again:
2104 BUG(); 2115 BUG();
2105 break; 2116 break;
2106 } 2117 }
2107 spin_unlock(&icsbp->icsb_lock); 2118 xfs_icsb_unlock_cntr(icsbp);
2108 put_cpu(); 2119 put_cpu();
2109 if (locked) 2120 if (locked)
2110 XFS_SB_UNLOCK(mp, s); 2121 XFS_SB_UNLOCK(mp, s);
@@ -2120,7 +2131,7 @@ again:
2120 * manner. 2131 * manner.
2121 */ 2132 */
2122slow_path: 2133slow_path:
2123 spin_unlock(&icsbp->icsb_lock); 2134 xfs_icsb_unlock_cntr(icsbp);
2124 put_cpu(); 2135 put_cpu();
2125 2136
2126 /* need to hold superblock incase we need 2137 /* need to hold superblock incase we need
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 9d2ffbdc37a9..29cfcf0c11be 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -280,9 +280,11 @@ typedef struct xfs_icsb_cnts {
280 uint64_t icsb_fdblocks; 280 uint64_t icsb_fdblocks;
281 uint64_t icsb_ifree; 281 uint64_t icsb_ifree;
282 uint64_t icsb_icount; 282 uint64_t icsb_icount;
283 spinlock_t icsb_lock; 283 unsigned long icsb_flags;
284} xfs_icsb_cnts_t; 284} xfs_icsb_cnts_t;
285 285
286#define XFS_ICSB_FLAG_LOCK (1 << 0) /* counter lock bit */
287
286#define XFS_ICSB_SB_LOCKED (1 << 0) /* sb already locked */ 288#define XFS_ICSB_SB_LOCKED (1 << 0) /* sb already locked */
287#define XFS_ICSB_LAZY_COUNT (1 << 1) /* accuracy not needed */ 289#define XFS_ICSB_LAZY_COUNT (1 << 1) /* accuracy not needed */
288 290