From 01e1b69cfcdcfdd5b405165eaba29428f8b18a7c Mon Sep 17 00:00:00 2001 From: David Chinner Date: Tue, 14 Mar 2006 13:29:16 +1100 Subject: =?UTF-8?q?[XFS]=20using=20a=20spinlock=20per=20cpu=20for=20superb?= =?UTF-8?q?lock=20counter=20exclusion=20results=20in=20a=20pre=C4=93mpt=20?= =?UTF-8?q?counter=20overflow=20at=20256p=20and=20above.=20Change=20the=20?= =?UTF-8?q?exclusion=20mechanism=20to=20use=20atomic=20bit=20operations=20?= =?UTF-8?q?and=20busy=20wait=20loops=20to=20emulate=20the=20spin=20lock=20?= =?UTF-8?q?exclusion=20mechanism=20but=20without=20the=20preempt=20count?= =?UTF-8?q?=20issues.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SGI-PV: 950027 SGI-Modid: xfs-linux-melb:xfs-kern:25338a Signed-off-by: David Chinner Signed-off-by: Nathan Scott --- fs/xfs/linux-2.6/xfs_linux.h | 1 + fs/xfs/xfs_mount.c | 37 ++++++++++++++++++++++++------------- fs/xfs/xfs_mount.h | 4 +++- 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 9fdc14cf..bd88ccb 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -75,6 +75,7 @@ #include #include #include +#include #include #include diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index a64110b..d62aee0 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1746,10 +1746,7 @@ xfs_icsb_cpu_notify( case CPU_UP_PREPARE: /* Easy Case - initialize the area and locks, and * then rebalance when online does everything else for us. */ - spin_lock_init(&cntp->icsb_lock); - cntp->icsb_icount = 0; - cntp->icsb_ifree = 0; - cntp->icsb_fdblocks = 0; + memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); break; case CPU_ONLINE: xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); @@ -1769,9 +1766,7 @@ xfs_icsb_cpu_notify( mp->m_sb.sb_ifree += cntp->icsb_ifree; mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks; - cntp->icsb_icount = 0; - cntp->icsb_ifree = 0; - cntp->icsb_fdblocks = 0; + memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED); xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED); @@ -1800,7 +1795,7 @@ xfs_icsb_init_counters( for_each_online_cpu(i) { cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); - spin_lock_init(&cntp->icsb_lock); + memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); } /* * start with all counters disabled so that the @@ -1820,6 +1815,22 @@ xfs_icsb_destroy_counters( } } +STATIC inline 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 inline void +xfs_icsb_unlock_cntr( + xfs_icsb_cnts_t *icsbp) +{ + clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags); +} + STATIC inline void xfs_icsb_lock_all_counters( @@ -1830,7 +1841,7 @@ xfs_icsb_lock_all_counters( for_each_online_cpu(i) { cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); - spin_lock(&cntp->icsb_lock); + xfs_icsb_lock_cntr(cntp); } } @@ -1843,7 +1854,7 @@ xfs_icsb_unlock_all_counters( for_each_online_cpu(i) { cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); - spin_unlock(&cntp->icsb_lock); + xfs_icsb_unlock_cntr(cntp); } } @@ -2070,7 +2081,7 @@ xfs_icsb_modify_counters_int( again: cpu = get_cpu(); icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu), - spin_lock(&icsbp->icsb_lock); + xfs_icsb_lock_cntr(icsbp); if (unlikely(xfs_icsb_counter_disabled(mp, field))) goto slow_path; @@ -2104,7 +2115,7 @@ again: BUG(); break; } - spin_unlock(&icsbp->icsb_lock); + xfs_icsb_unlock_cntr(icsbp); put_cpu(); if (locked) XFS_SB_UNLOCK(mp, s); @@ -2120,7 +2131,7 @@ again: * manner. */ slow_path: - spin_unlock(&icsbp->icsb_lock); + xfs_icsb_unlock_cntr(icsbp); put_cpu(); /* need to hold superblock incase we need diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 9d2ffbd..29cfcf0 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -280,9 +280,11 @@ typedef struct xfs_icsb_cnts { uint64_t icsb_fdblocks; uint64_t icsb_ifree; uint64_t icsb_icount; - spinlock_t icsb_lock; + unsigned long icsb_flags; } xfs_icsb_cnts_t; +#define XFS_ICSB_FLAG_LOCK (1 << 0) /* counter lock bit */ + #define XFS_ICSB_SB_LOCKED (1 << 0) /* sb already locked */ #define XFS_ICSB_LAZY_COUNT (1 << 1) /* accuracy not needed */ -- cgit v1.1