[Cluster-devel] GFS2: Pull request (fixes)

2010-11-29 Thread Steven Whitehouse
Hi,

Please consider pulling the following fix,

Steve.

-
The following changes since commit e53beacd23d9cb47590da6a7a7f6d417b941a994:

  Linux 2.6.37-rc2 (2010-11-15 18:31:02 -0800)

are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git master

Abhijith Das (1):
  GFS2: Userland expects quota limit/warn/usage in 512b blocks

 fs/gfs2/quota.c |   15 ---
 1 files changed, 8 insertions(+), 7 deletions(-)
--

From 14870b457524e745f1a118e17873d104b1a47b70 Mon Sep 17 00:00:00 2001
From: Abhijith Das a...@redhat.com
Date: Thu, 18 Nov 2010 11:24:24 -0500
Subject: [PATCH] GFS2: Userland expects quota limit/warn/usage in 512b blocks

Userland programs using the quotactl() syscall assume limit/warn/usage
block counts in 512b basic blocks which were instead being read/written
in fs blocksize in gfs2. With this patch, gfs2 correctly interacts with
the syscall using 512b blocks.

Signed-off-by: Abhi Das a...@redhat.com
Reviewed-by: Christoph Hellwig h...@lst.de
Signed-off-by: Steven Whitehouse swhit...@redhat.com

diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 58a9b99..f606baf 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -631,6 +631,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t 
loc,
 struct fs_disk_quota *fdq)
 {
struct inode *inode = ip-i_inode;
+   struct gfs2_sbd *sdp = GFS2_SB(inode);
struct address_space *mapping = inode-i_mapping;
unsigned long index = loc  PAGE_CACHE_SHIFT;
unsigned offset = loc  (PAGE_CACHE_SIZE - 1);
@@ -658,11 +659,11 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, 
loff_t loc,
qd-qd_qb.qb_value = qp-qu_value;
if (fdq) {
if (fdq-d_fieldmask  FS_DQ_BSOFT) {
-   qp-qu_warn = cpu_to_be64(fdq-d_blk_softlimit);
+   qp-qu_warn = cpu_to_be64(fdq-d_blk_softlimit  
sdp-sd_fsb2bb_shift);
qd-qd_qb.qb_warn = qp-qu_warn;
}
if (fdq-d_fieldmask  FS_DQ_BHARD) {
-   qp-qu_limit = cpu_to_be64(fdq-d_blk_hardlimit);
+   qp-qu_limit = cpu_to_be64(fdq-d_blk_hardlimit  
sdp-sd_fsb2bb_shift);
qd-qd_qb.qb_limit = qp-qu_limit;
}
}
@@ -1497,9 +1498,9 @@ static int gfs2_get_dqblk(struct super_block *sb, int 
type, qid_t id,
fdq-d_version = FS_DQUOT_VERSION;
fdq-d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
fdq-d_id = id;
-   fdq-d_blk_hardlimit = be64_to_cpu(qlvb-qb_limit);
-   fdq-d_blk_softlimit = be64_to_cpu(qlvb-qb_warn);
-   fdq-d_bcount = be64_to_cpu(qlvb-qb_value);
+   fdq-d_blk_hardlimit = be64_to_cpu(qlvb-qb_limit)  
sdp-sd_fsb2bb_shift;
+   fdq-d_blk_softlimit = be64_to_cpu(qlvb-qb_warn)  
sdp-sd_fsb2bb_shift;
+   fdq-d_bcount = be64_to_cpu(qlvb-qb_value)  sdp-sd_fsb2bb_shift;
 
gfs2_glock_dq_uninit(q_gh);
 out:
@@ -1566,10 +1567,10 @@ static int gfs2_set_dqblk(struct super_block *sb, int 
type, qid_t id,
 
/* If nothing has changed, this is a no-op */
if ((fdq-d_fieldmask  FS_DQ_BSOFT) 
-   (fdq-d_blk_softlimit == be64_to_cpu(qd-qd_qb.qb_warn)))
+   ((fdq-d_blk_softlimit  sdp-sd_fsb2bb_shift) == 
be64_to_cpu(qd-qd_qb.qb_warn)))
fdq-d_fieldmask ^= FS_DQ_BSOFT;
if ((fdq-d_fieldmask  FS_DQ_BHARD) 
-   (fdq-d_blk_hardlimit == be64_to_cpu(qd-qd_qb.qb_limit)))
+   ((fdq-d_blk_hardlimit  sdp-sd_fsb2bb_shift) == 
be64_to_cpu(qd-qd_qb.qb_limit)))
fdq-d_fieldmask ^= FS_DQ_BHARD;
if (fdq-d_fieldmask == 0)
goto out_i;
-- 
1.7.2.3





[Cluster-devel] GFS2: Use rcu for glock hash table

2010-11-29 Thread Steven Whitehouse

This is an updated version of the RCU glock patch which I've
been working on, on and off for a while now. It has survived
some basic testing so far, I've not tried running very large
numbers of threads against it so far.

In order to apply this patch you'll need the latest -nmw tree
and also this patch:
http://git.kernel.org/?p=linux/kernel/git/npiggin/linux-npiggin.git;a=commitdiff;h=574d900af0cf01be2ab929a4030ed4a3d2a2b1de

which adds the rculist_bl.h header. Fingers crossed that or
something like it will be merged at the next merge window.

As per the previous posting, the main features are (a) reduced
code size, (b) rcu glock hash table to reduce contention on
lookups. Also, new this time, (c) spin locks for the write side
of hash table manipulation borrow 1 bit from the list heads (i.e.
use rculist_bl) so that the hash lock is now split up.

Further thoughts:
 - We should use a per-cpu counter for the per-sb glock counter.
 - We could use SLAB_DESTROY_BY_RCU, but I need to figure out how
   to alter the lookup routines in order to make that work.
 - Maybe add lockdep to spin_lock/unlock_bucket

I'm expecting that there will probably be further versions of this
patch before it is in its final form.

Signed-off-by: Steven Whitehouse swhit...@redhat.com

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 2dd1d72..ecacf3f 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -26,6 +26,8 @@
 #include linux/freezer.h
 #include linux/workqueue.h
 #include linux/jiffies.h
+#include linux/rcupdate.h
+#include linux/rculist_bl.h
 
 #include gfs2.h
 #include incore.h
@@ -41,10 +43,6 @@
 #define CREATE_TRACE_POINTS
 #include trace_gfs2.h
 
-struct gfs2_gl_hash_bucket {
-struct hlist_head hb_list;
-};
-
 struct gfs2_glock_iter {
int hash;   /* hash bucket index */
struct gfs2_sbd *sdp;   /* incore superblock */
@@ -54,7 +52,6 @@ struct gfs2_glock_iter {
 
 typedef void (*glock_examiner) (struct gfs2_glock * gl);
 
-static int gfs2_dump_lockstate(struct gfs2_sbd *sdp);
 static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
 #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); 
BUG(); } } while(0)
 static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned 
int target);
@@ -70,57 +67,9 @@ static DEFINE_SPINLOCK(lru_lock);
 #define GFS2_GL_HASH_SIZE   (1  GFS2_GL_HASH_SHIFT)
 #define GFS2_GL_HASH_MASK   (GFS2_GL_HASH_SIZE - 1)
 
-static struct gfs2_gl_hash_bucket gl_hash_table[GFS2_GL_HASH_SIZE];
+static struct hlist_bl_head gl_hash_table[GFS2_GL_HASH_SIZE];
 static struct dentry *gfs2_root;
 
-/*
- * Despite what you might think, the numbers below are not arbitrary :-)
- * They are taken from the ipv4 routing hash code, which is well tested
- * and thus should be nearly optimal. Later on we might tweek the numbers
- * but for now this should be fine.
- *
- * The reason for putting the locks in a separate array from the list heads
- * is that we can have fewer locks than list heads and save memory. We use
- * the same hash function for both, but with a different hash mask.
- */
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) || \
-   defined(CONFIG_PROVE_LOCKING)
-
-#ifdef CONFIG_LOCKDEP
-# define GL_HASH_LOCK_SZ256
-#else
-# if NR_CPUS = 32
-#  define GL_HASH_LOCK_SZ   4096
-# elif NR_CPUS = 16
-#  define GL_HASH_LOCK_SZ   2048
-# elif NR_CPUS = 8
-#  define GL_HASH_LOCK_SZ   1024
-# elif NR_CPUS = 4
-#  define GL_HASH_LOCK_SZ   512
-# else
-#  define GL_HASH_LOCK_SZ   256
-# endif
-#endif
-
-/* We never want more locks than chains */
-#if GFS2_GL_HASH_SIZE  GL_HASH_LOCK_SZ
-# undef GL_HASH_LOCK_SZ
-# define GL_HASH_LOCK_SZ GFS2_GL_HASH_SIZE
-#endif
-
-static rwlock_t gl_hash_locks[GL_HASH_LOCK_SZ];
-
-static inline rwlock_t *gl_lock_addr(unsigned int x)
-{
-   return gl_hash_locks[x  (GL_HASH_LOCK_SZ-1)];
-}
-#else /* not SMP, so no spinlocks required */
-static inline rwlock_t *gl_lock_addr(unsigned int x)
-{
-   return NULL;
-}
-#endif
-
 /**
  * gl_hash() - Turn glock number into hash bucket number
  * @lock: The glock number
@@ -141,25 +90,30 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp,
return h;
 }
 
-/**
- * glock_free() - Perform a few checks and then release struct gfs2_glock
- * @gl: The glock to release
- *
- * Also calls lock module to release its internal structure for this glock.
- *
- */
+static inline void spin_lock_bucket(unsigned int hash)
+{
+   struct hlist_bl_head *bl = gl_hash_table[hash];
+   bit_spin_lock(0, (unsigned long *)bl);
+}
+
+static inline void spin_unlock_bucket(unsigned int hash)
+{
+   struct hlist_bl_head *bl = gl_hash_table[hash];
+   __bit_spin_unlock(0, (unsigned long *)bl);
+}
 
-static void glock_free(struct gfs2_glock *gl)
+void gfs2_glock_free(struct rcu_head *rcu)
 {
+   struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);