]> git.hungrycats.org Git - linux/commitdiff
[PATCH] blockgroup_lock: hashed spinlocks for ext2 and ext3
authorAndrew Morton <akpm@digeo.com>
Sat, 12 Apr 2003 20:00:09 +0000 (13:00 -0700)
committerJames Bottomley <jejb@raven.il.steeleye.com>
Sat, 12 Apr 2003 20:00:09 +0000 (13:00 -0700)
ext2 and ext3 per-blockgroup metadata needs locking.  An fs-wide lock is
expensive, and a per-blockgroup lock consumes too much storage (up to 32768
blockgroups per filesystem).  We need something in-between.

blockgroup_locks are very simple hashed spinlocks which provide this
compromise.  The size of the lock is scaled by NR_CPUS to implement an
additional speed/space tradeoff.

These locks are actually fairly generic.  However I presented it as something
which is specific to ext2 and ext3 so that people wouldn't go using them all
over the place.  They consume a lot of storage.

include/linux/blockgroup_lock.h [new file with mode: 0644]

diff --git a/include/linux/blockgroup_lock.h b/include/linux/blockgroup_lock.h
new file mode 100644 (file)
index 0000000..87a890c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Per-blockgroup locking for ext2 and ext3.
+ *
+ * Simple hashed spinlocking.
+ */
+
+#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+
+#ifdef CONFIG_SMP
+
+/*
+ * We want a power-of-two.  Is there a better way than this?
+ */
+
+#if NR_CPUS >= 32
+#define NR_BG_LOCKS    128
+#elif NR_CPUS >= 16
+#define NR_BG_LOCKS    64
+#elif NR_CPUS >= 8
+#define NR_BG_LOCKS    32
+#elif NR_CPUS >= 4
+#define NR_BG_LOCKS    16
+#elif NR_CPUS >= 2
+#define NR_BG_LOCKS    8
+#else
+#define NR_BG_LOCKS    4
+#endif
+
+#else  /* CONFIG_SMP */
+#define NR_BG_LOCKS    1
+#endif /* CONFIG_SMP */
+
+struct bgl_lock {
+       spinlock_t lock;
+} ____cacheline_aligned_in_smp;
+
+struct blockgroup_lock {
+       struct bgl_lock locks[NR_BG_LOCKS];
+};
+
+static inline void bgl_lock_init(struct blockgroup_lock *bgl)
+{
+       int i;
+
+       for (i = 0; i < NR_BG_LOCKS; i++)
+               spin_lock_init(&bgl->locks[i].lock);
+}
+
+/*
+ * The accessor is a macro so we can embed a blockgroup_lock into different
+ * superblock types
+ */
+#define sb_bgl_lock(sb, block_group) \
+       (&(sb)->s_blockgroup_lock.locks[(block_group) & (NR_BG_LOCKS-1)].lock)
+
+