]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
[XFS] using a spinlock per cpu for superblock counter exclusion results in
authorDavid Chinner <dgc@sgi.com>
Tue, 14 Mar 2006 02:29:16 +0000 (13:29 +1100)
committerNathan Scott <nathans@sgi.com>
Tue, 14 Mar 2006 02:29:16 +0000 (13:29 +1100)
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>
fs/xfs/linux-2.6/xfs_linux.h
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h

index 9fdc14cffb70cb6c808e728455fc7ccfb7ac0295..bd88ccb0cad04b825762ec35053d2a654b2e3b6b 100644 (file)
@@ -75,6 +75,7 @@
 #include <linux/sort.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
+#include <linux/delay.h>
 
 #include <asm/page.h>
 #include <asm/div64.h>
index a64110b9023bc45f331fdadf503b1071942790e6..d62aee027368fc522a23f3724c7b4a42eb5d86a5 100644 (file)
@@ -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
index 9d2ffbdc37a9977e93326e338018edf680c3a9c3..29cfcf0c11be9c287fd65f7c4349b2995775efd0 100644 (file)
@@ -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 */