All of lore.kernel.org
 help / color / mirror / Atom feed
* [Cluster-devel] [GFS2 PATCH 0/2] Increase GFS2 glock scalability
@ 2015-07-09 18:25 Bob Peterson
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 1/2] GFS2: Move glock superblock pointer to field gl_name Bob Peterson
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks Bob Peterson
  0 siblings, 2 replies; 14+ messages in thread
From: Bob Peterson @ 2015-07-09 18:25 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,

GFS2's glocks don't scale well. You can demonstrate this pretty easily by
running fs_mark with this command:

./fs_mark -t8 -D 10000 -S0 -n 100000 -s 0 -L 10 -d /mnt/gfs2/

Here is output from one of my test systems showing the problem:

FSUse%        Count         Size    Files/sec     App Overhead
     4       800000            0      13082.9          7914165
     8      1600000            0      10381.9          8065812
    11      2400000            0       8105.7          8325730
    15      3200000            0       7006.3          7644981
    19      4000000            0       5460.8          7585682
    23      4800000            0       5331.7          7802480
    27      5600000            0       4733.9          7778611
    31      6400000            0       4292.6          7873069
    35      7200000            0       3754.7          7712113
    39      8000000            0       3593.4          7771494

The scalability problem is due to the fact that the glocks are all kept in
a normal rcu-based hash table.

This patch set changes GFS2 so it uses a resizeable hash table (rhashtable)
to increase scalability. There are two patches:

1. First, we move the glock's superblock pointer from the glock itself to
   its gl_name sub-structure. That means we can uniquely identify any
   glock in existence by its gl_name, no matter which mount point it's from.
2. Second, we switch from hash table to rhashtable. This simplifies a lot
   of code. The result is vastly better scalability, as shown with the same
   command:

FSUse%        Count         Size    Files/sec     App Overhead
     4       800000            0      12995.4          8113549
     8      1600000            0      12555.7          8248789
    11      2400000            0      13459.2          8154784
    15      3200000            0      14151.9          8677595
    19      4000000            0      12702.6         10187935
    23      4800000            0      13662.7          8153093
    27      5600000            0      12174.7          8121007
    31      6400000            0      13408.2          8444204
    35      7200000            0      13324.5          8243381
    39      8000000            0      12476.3          8165069

Regards,

Bob Peterson
Red Hat File Systems

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---


Bob Peterson (2):
  GFS2: Move glock superblock pointer to field gl_name
  GFS2: Use resizable hash table for glocks

 fs/gfs2/glock.c      | 304 ++++++++++++++++++++-------------------------------
 fs/gfs2/glops.c      |  38 ++++---
 fs/gfs2/incore.h     |  13 ++-
 fs/gfs2/lock_dlm.c   |  10 +-
 fs/gfs2/lops.c       |   6 +-
 fs/gfs2/meta_io.c    |   6 +-
 fs/gfs2/meta_io.h    |   2 +-
 fs/gfs2/quota.c      |  22 ++--
 fs/gfs2/rgrp.c       |   2 +-
 fs/gfs2/trace_gfs2.h |  18 +--
 fs/gfs2/trans.c      |   4 +-
 11 files changed, 181 insertions(+), 244 deletions(-)

-- 
2.1.0



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 1/2] GFS2: Move glock superblock pointer to field gl_name
  2015-07-09 18:25 [Cluster-devel] [GFS2 PATCH 0/2] Increase GFS2 glock scalability Bob Peterson
@ 2015-07-09 18:25 ` Bob Peterson
  2015-07-13 11:19   ` Steven Whitehouse
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks Bob Peterson
  1 sibling, 1 reply; 14+ messages in thread
From: Bob Peterson @ 2015-07-09 18:25 UTC (permalink / raw)
  To: cluster-devel.redhat.com

What uniquely identifies a glock in the glock hash table is not
gl_name, but gl_name and its superblock pointer. This patch makes
the gl_name field correspond to a unique glock identifier. That will
allow us to simplify hashing with a future patch, since the hash
algorithm can then take the gl_name and hash its components in one
operation.
---
 fs/gfs2/glock.c      | 32 +++++++++++++++-----------------
 fs/gfs2/glops.c      | 38 ++++++++++++++++++++------------------
 fs/gfs2/incore.h     |  9 +++++----
 fs/gfs2/lock_dlm.c   | 10 +++++-----
 fs/gfs2/lops.c       |  6 +++---
 fs/gfs2/meta_io.c    |  6 +++---
 fs/gfs2/meta_io.h    |  2 +-
 fs/gfs2/quota.c      | 22 +++++++++++-----------
 fs/gfs2/rgrp.c       |  2 +-
 fs/gfs2/trace_gfs2.h | 18 +++++++++---------
 fs/gfs2/trans.c      |  4 ++--
 11 files changed, 75 insertions(+), 74 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index a38e38f..25e0389 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -119,7 +119,7 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
 
 void gfs2_glock_free(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
 	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
 	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
@@ -192,7 +192,7 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
 
 void gfs2_glock_put(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct address_space *mapping = gfs2_glock2aspace(gl);
 
 	if (lockref_put_or_lock(&gl->gl_lockref))
@@ -220,7 +220,6 @@ void gfs2_glock_put(struct gfs2_glock *gl)
  */
 
 static struct gfs2_glock *search_bucket(unsigned int hash,
-					const struct gfs2_sbd *sdp,
 					const struct lm_lockname *name)
 {
 	struct gfs2_glock *gl;
@@ -229,8 +228,6 @@ static struct gfs2_glock *search_bucket(unsigned int hash,
 	hlist_bl_for_each_entry_rcu(gl, h, &gl_hash_table[hash], gl_list) {
 		if (!lm_name_equal(&gl->gl_name, name))
 			continue;
-		if (gl->gl_sbd != sdp)
-			continue;
 		if (lockref_get_not_dead(&gl->gl_lockref))
 			return gl;
 	}
@@ -506,7 +503,7 @@ __releases(&gl->gl_spin)
 __acquires(&gl->gl_spin)
 {
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	unsigned int lck_flags = gh ? gh->gh_flags : 0;
 	int ret;
 
@@ -628,7 +625,7 @@ out_unlock:
 static void delete_work_func(struct work_struct *work)
 {
 	struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete);
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip;
 	struct inode *inode;
 	u64 no_addr = gl->gl_name.ln_number;
@@ -704,14 +701,16 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 		   struct gfs2_glock **glp)
 {
 	struct super_block *s = sdp->sd_vfs;
-	struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type };
+	struct lm_lockname name = { .ln_number = number,
+				    .ln_type = glops->go_type,
+				    .ln_sbd = sdp };
 	struct gfs2_glock *gl, *tmp;
 	unsigned int hash = gl_hash(sdp, &name);
 	struct address_space *mapping;
 	struct kmem_cache *cachep;
 
 	rcu_read_lock();
-	gl = search_bucket(hash, sdp, &name);
+	gl = search_bucket(hash, &name);
 	rcu_read_unlock();
 
 	*glp = gl;
@@ -739,7 +738,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	}
 
 	atomic_inc(&sdp->sd_glock_disposal);
-	gl->gl_sbd = sdp;
 	gl->gl_flags = 0;
 	gl->gl_name = name;
 	gl->gl_lockref.count = 1;
@@ -772,7 +770,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	}
 
 	spin_lock_bucket(hash);
-	tmp = search_bucket(hash, sdp, &name);
+	tmp = search_bucket(hash, &name);
 	if (tmp) {
 		spin_unlock_bucket(hash);
 		kfree(gl->gl_lksb.sb_lvbptr);
@@ -928,7 +926,7 @@ __releases(&gl->gl_spin)
 __acquires(&gl->gl_spin)
 {
 	struct gfs2_glock *gl = gh->gh_gl;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct list_head *insert_pt = NULL;
 	struct gfs2_holder *gh2;
 	int try_futile = 0;
@@ -1006,7 +1004,7 @@ trap_recursive:
 int gfs2_glock_nq(struct gfs2_holder *gh)
 {
 	struct gfs2_glock *gl = gh->gh_gl;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	int error = 0;
 
 	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
@@ -1313,7 +1311,7 @@ static int gfs2_should_freeze(const struct gfs2_glock *gl)
 
 void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
 {
-	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
 
 	spin_lock(&gl->gl_spin);
 	gl->gl_reply = ret;
@@ -1471,7 +1469,7 @@ static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
 
 	rcu_read_lock();
 	hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
-		if ((gl->gl_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
+		if ((gl->gl_name.ln_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
 			examiner(gl);
 	}
 	rcu_read_unlock();
@@ -1569,7 +1567,7 @@ void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
 	int ret;
 
 	ret = gfs2_truncatei_resume(ip);
-	gfs2_assert_withdraw(gl->gl_sbd, ret == 0);
+	gfs2_assert_withdraw(gl->gl_name.ln_sbd, ret == 0);
 
 	spin_lock(&gl->gl_spin);
 	clear_bit(GLF_LOCK, &gl->gl_flags);
@@ -1872,7 +1870,7 @@ static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
 			gi->nhash = 0;
 		}
 	/* Skip entries for other sb and dead entries */
-	} while (gi->sdp != gi->gl->gl_sbd ||
+	} while (gi->sdp != gi->gl->gl_name.ln_sbd ||
 		 __lockref_is_dead(&gi->gl->gl_lockref));
 
 	return 0;
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index fa3fa5e..1f6c9c3 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -32,13 +32,15 @@ struct workqueue_struct *gfs2_freeze_wq;
 
 static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
 {
-	fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n",
+	fs_err(gl->gl_name.ln_sbd,
+	       "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page "
+	       "state 0x%lx\n",
 	       bh, (unsigned long long)bh->b_blocknr, bh->b_state,
 	       bh->b_page->mapping, bh->b_page->flags);
-	fs_err(gl->gl_sbd, "AIL glock %u:%llu mapping %p\n",
+	fs_err(gl->gl_name.ln_sbd, "AIL glock %u:%llu mapping %p\n",
 	       gl->gl_name.ln_type, gl->gl_name.ln_number,
 	       gfs2_glock2aspace(gl));
-	gfs2_lm_withdraw(gl->gl_sbd, "AIL error\n");
+	gfs2_lm_withdraw(gl->gl_name.ln_sbd, "AIL error\n");
 }
 
 /**
@@ -52,7 +54,7 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
 static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
 			     unsigned int nr_revokes)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct list_head *head = &gl->gl_ail_list;
 	struct gfs2_bufdata *bd, *tmp;
 	struct buffer_head *bh;
@@ -80,7 +82,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
 
 static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_trans tr;
 
 	memset(&tr, 0, sizeof(tr));
@@ -109,7 +111,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 
 void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	unsigned int revokes = atomic_read(&gl->gl_ail_count);
 	unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
 	int ret;
@@ -139,7 +141,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
 static void rgrp_go_sync(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct address_space *mapping = &sdp->sd_aspace;
 	struct gfs2_rgrpd *rgd;
 	int error;
@@ -179,7 +181,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 
 static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct address_space *mapping = &sdp->sd_aspace;
 	struct gfs2_rgrpd *rgd = gl->gl_object;
 
@@ -218,7 +220,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
 	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-	gfs2_log_flush(gl->gl_sbd, gl, NORMAL_FLUSH);
+	gfs2_log_flush(gl->gl_name.ln_sbd, gl, NORMAL_FLUSH);
 	filemap_fdatawrite(metamapping);
 	if (ip) {
 		struct address_space *mapping = ip->i_inode.i_mapping;
@@ -252,7 +254,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 {
 	struct gfs2_inode *ip = gl->gl_object;
 
-	gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
+	gfs2_assert_withdraw(gl->gl_name.ln_sbd, !atomic_read(&gl->gl_ail_count));
 
 	if (flags & DIO_METADATA) {
 		struct address_space *mapping = gfs2_glock2aspace(gl);
@@ -264,9 +266,9 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 		}
 	}
 
-	if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) {
-		gfs2_log_flush(gl->gl_sbd, NULL, NORMAL_FLUSH);
-		gl->gl_sbd->sd_rindex_uptodate = 0;
+	if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
+		gfs2_log_flush(gl->gl_name.ln_sbd, NULL, NORMAL_FLUSH);
+		gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
 	}
 	if (ip && S_ISREG(ip->i_inode.i_mode))
 		truncate_inode_pages(ip->i_inode.i_mapping, 0);
@@ -281,7 +283,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 
 static int inode_go_demote_ok(const struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_holder *gh;
 
 	if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object)
@@ -416,7 +418,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip)
 static int inode_go_lock(struct gfs2_holder *gh)
 {
 	struct gfs2_glock *gl = gh->gh_gl;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = gl->gl_object;
 	int error = 0;
 
@@ -477,7 +479,7 @@ static void inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
 static void freeze_go_sync(struct gfs2_glock *gl)
 {
 	int error = 0;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
 	if (gl->gl_state == LM_ST_SHARED &&
 	    test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
@@ -500,7 +502,7 @@ static void freeze_go_sync(struct gfs2_glock *gl)
 
 static int freeze_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
 	struct gfs2_glock *j_gl = ip->i_gl;
 	struct gfs2_log_header_host head;
@@ -545,7 +547,7 @@ static int freeze_go_demote_ok(const struct gfs2_glock *gl)
 static void iopen_go_callback(struct gfs2_glock *gl, bool remote)
 {
 	struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
 	if (!remote || (sdp->sd_vfs->s_flags & MS_RDONLY))
 		return;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index a1ec7c2..4de7853 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -205,11 +205,13 @@ enum {
 struct lm_lockname {
 	u64 ln_number;
 	unsigned int ln_type;
+	struct gfs2_sbd *ln_sbd;
 };
 
 #define lm_name_equal(name1, name2) \
-        (((name1)->ln_number == (name2)->ln_number) && \
-         ((name1)->ln_type == (name2)->ln_type))
+        (((name1)->ln_number == (name2)->ln_number) &&	\
+	 ((name1)->ln_type == (name2)->ln_type) &&	\
+	 ((name1)->ln_sbd == (name2)->ln_sbd))
 
 
 struct gfs2_glock_operations {
@@ -327,7 +329,6 @@ enum {
 
 struct gfs2_glock {
 	struct hlist_bl_node gl_list;
-	struct gfs2_sbd *gl_sbd;
 	unsigned long gl_flags;		/* GLF_... */
 	struct lm_lockname gl_name;
 
@@ -835,7 +836,7 @@ static inline void gfs2_glstats_inc(struct gfs2_glock *gl, int which)
 
 static inline void gfs2_sbstats_inc(const struct gfs2_glock *gl, int which)
 {
-	const struct gfs2_sbd *sdp = gl->gl_sbd;
+	const struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	preempt_disable();
 	this_cpu_ptr(sdp->sd_lkstats)->lkstats[gl->gl_name.ln_type].stats[which]++;
 	preempt_enable();
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 641383a..c962cfc 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -80,7 +80,7 @@ static inline void gfs2_update_reply_times(struct gfs2_glock *gl)
 
 	preempt_disable();
 	rtt = ktime_to_ns(ktime_sub(ktime_get_real(), gl->gl_dstamp));
-	lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats);
+	lks = this_cpu_ptr(gl->gl_name.ln_sbd->sd_lkstats);
 	gfs2_update_stats(&gl->gl_stats, index, rtt);		/* Local */
 	gfs2_update_stats(&lks->lkstats[gltype], index, rtt);	/* Global */
 	preempt_enable();
@@ -108,7 +108,7 @@ static inline void gfs2_update_request_times(struct gfs2_glock *gl)
 	dstamp = gl->gl_dstamp;
 	gl->gl_dstamp = ktime_get_real();
 	irt = ktime_to_ns(ktime_sub(gl->gl_dstamp, dstamp));
-	lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats);
+	lks = this_cpu_ptr(gl->gl_name.ln_sbd->sd_lkstats);
 	gfs2_update_stats(&gl->gl_stats, GFS2_LKS_SIRT, irt);		/* Local */
 	gfs2_update_stats(&lks->lkstats[gltype], GFS2_LKS_SIRT, irt);	/* Global */
 	preempt_enable();
@@ -253,7 +253,7 @@ static void gfs2_reverse_hex(char *c, u64 value)
 static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
 		     unsigned int flags)
 {
-	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
 	int req;
 	u32 lkf;
 	char strname[GDLM_STRNAME_BYTES] = "";
@@ -281,7 +281,7 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
 
 static void gdlm_put_lock(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
 	int lvb_needs_unlock = 0;
 	int error;
@@ -319,7 +319,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
 
 static void gdlm_cancel(struct gfs2_glock *gl)
 {
-	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
 	dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
 }
 
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 2c1ae86..7833394 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -70,7 +70,7 @@ static bool buffer_is_rgrp(const struct gfs2_bufdata *bd)
 static void maybe_release_space(struct gfs2_bufdata *bd)
 {
 	struct gfs2_glock *gl = bd->bd_gl;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_rgrpd *rgd = gl->gl_object;
 	unsigned int index = bd->bd_bh->b_blocknr - gl->gl_name.ln_number;
 	struct gfs2_bitmap *bi = rgd->rd_bits + index;
@@ -585,7 +585,7 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
 static void gfs2_meta_sync(struct gfs2_glock *gl)
 {
 	struct address_space *mapping = gfs2_glock2aspace(gl);
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	int error;
 
 	if (mapping == NULL)
@@ -595,7 +595,7 @@ static void gfs2_meta_sync(struct gfs2_glock *gl)
 	error = filemap_fdatawait(mapping);
 
 	if (error)
-		gfs2_io_error(gl->gl_sbd);
+		gfs2_io_error(gl->gl_name.ln_sbd);
 }
 
 static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index b984a6e..0e1d4be 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -114,7 +114,7 @@ const struct address_space_operations gfs2_rgrp_aops = {
 struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
 {
 	struct address_space *mapping = gfs2_glock2aspace(gl);
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct page *page;
 	struct buffer_head *bh;
 	unsigned int shift;
@@ -200,7 +200,7 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
 int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
 		   struct buffer_head **bhp)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct buffer_head *bh;
 
 	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
@@ -362,7 +362,7 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
 
 struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct buffer_head *first_bh, *bh;
 	u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >>
 			  sdp->sd_sb.sb_bsize_shift;
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index ac5d802..8ca1615 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -44,7 +44,7 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
 {
 	struct inode *inode = mapping->host;
 	if (mapping->a_ops == &gfs2_meta_aops)
-		return (((struct gfs2_glock *)mapping) - 1)->gl_sbd;
+		return (((struct gfs2_glock *)mapping) - 1)->gl_name.ln_sbd;
 	else if (mapping->a_ops == &gfs2_rgrp_aops)
 		return container_of(mapping, struct gfs2_sbd, sd_aspace);
 	else
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 9b61f92..3a31226 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -119,7 +119,7 @@ static void gfs2_qd_dispose(struct list_head *list)
 
 	while (!list_empty(list)) {
 		qd = list_entry(list->next, struct gfs2_quota_data, qd_lru);
-		sdp = qd->qd_gl->gl_sbd;
+		sdp = qd->qd_gl->gl_name.ln_sbd;
 
 		list_del(&qd->qd_lru);
 
@@ -302,7 +302,7 @@ static int qd_get(struct gfs2_sbd *sdp, struct kqid qid,
 
 static void qd_hold(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	gfs2_assert(sdp, !__lockref_is_dead(&qd->qd_lockref));
 	lockref_get(&qd->qd_lockref);
 }
@@ -367,7 +367,7 @@ static void slot_put(struct gfs2_quota_data *qd)
 
 static int bh_get(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
 	unsigned int block, offset;
 	struct buffer_head *bh;
@@ -414,7 +414,7 @@ fail:
 
 static void bh_put(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 
 	mutex_lock(&sdp->sd_quota_mutex);
 	gfs2_assert(sdp, qd->qd_bh_count);
@@ -486,7 +486,7 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp)
 
 static void qd_unlock(struct gfs2_quota_data *qd)
 {
-	gfs2_assert_warn(qd->qd_gl->gl_sbd,
+	gfs2_assert_warn(qd->qd_gl->gl_name.ln_sbd,
 			 test_bit(QDF_LOCKED, &qd->qd_flags));
 	clear_bit(QDF_LOCKED, &qd->qd_flags);
 	bh_put(qd);
@@ -614,7 +614,7 @@ static int sort_qd(const void *a, const void *b)
 
 static void do_qc(struct gfs2_quota_data *qd, s64 change)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
 	struct gfs2_quota_change *qc = qd->qd_bh_qc;
 	s64 x;
@@ -831,7 +831,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
 
 static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
 {
-	struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
 	struct gfs2_alloc_parms ap = { .aflags = 0, };
 	unsigned int data_blocks, ind_blocks;
@@ -922,7 +922,7 @@ out:
 		gfs2_glock_dq_uninit(&ghs[qx]);
 	mutex_unlock(&ip->i_inode.i_mutex);
 	kfree(ghs);
-	gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl, NORMAL_FLUSH);
+	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl, NORMAL_FLUSH);
 	return error;
 }
 
@@ -954,7 +954,7 @@ static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
 static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
 		    struct gfs2_holder *q_gh)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
 	struct gfs2_holder i_gh;
 	int error;
@@ -1037,7 +1037,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
 
 static int need_sync(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	struct gfs2_tune *gt = &sdp->sd_tune;
 	s64 value;
 	unsigned int num, den;
@@ -1125,7 +1125,7 @@ out:
 
 static int print_message(struct gfs2_quota_data *qd, char *type)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 
 	fs_info(sdp, "quota %s for %s %u\n",
 		type,
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index c6c6232..c92ae7fd 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1860,7 +1860,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
 static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops)
 {
 	const struct gfs2_glock *gl = rgd->rd_gl;
-	const struct gfs2_sbd *sdp = gl->gl_sbd;
+	const struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_lkstats *st;
 	s64 r_dcount, l_dcount;
 	s64 l_srttb, a_srttb = 0;
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
index 20c007d..fff47d0 100644
--- a/fs/gfs2/trace_gfs2.h
+++ b/fs/gfs2/trace_gfs2.h
@@ -104,7 +104,7 @@ TRACE_EVENT(gfs2_glock_state_change,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->glnum		= gl->gl_name.ln_number;
 		__entry->gltype		= gl->gl_name.ln_type;
 		__entry->cur_state	= glock_trace_state(gl->gl_state);
@@ -140,7 +140,7 @@ TRACE_EVENT(gfs2_glock_put,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->gltype		= gl->gl_name.ln_type;
 		__entry->glnum		= gl->gl_name.ln_number;
 		__entry->cur_state	= glock_trace_state(gl->gl_state);
@@ -174,7 +174,7 @@ TRACE_EVENT(gfs2_demote_rq,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->gltype		= gl->gl_name.ln_type;
 		__entry->glnum		= gl->gl_name.ln_number;
 		__entry->cur_state	= glock_trace_state(gl->gl_state);
@@ -209,7 +209,7 @@ TRACE_EVENT(gfs2_promote,
 	),
 
 	TP_fast_assign(
-		__entry->dev	= gh->gh_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev	= gh->gh_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->glnum	= gh->gh_gl->gl_name.ln_number;
 		__entry->gltype	= gh->gh_gl->gl_name.ln_type;
 		__entry->first	= first;
@@ -239,7 +239,7 @@ TRACE_EVENT(gfs2_glock_queue,
 	),
 
 	TP_fast_assign(
-		__entry->dev	= gh->gh_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev	= gh->gh_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->glnum	= gh->gh_gl->gl_name.ln_number;
 		__entry->gltype	= gh->gh_gl->gl_name.ln_type;
 		__entry->queue	= queue;
@@ -278,7 +278,7 @@ TRACE_EVENT(gfs2_glock_lock_time,
 	),
 
 	TP_fast_assign(
-		__entry->dev            = gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev            = gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->glnum          = gl->gl_name.ln_number;
 		__entry->gltype         = gl->gl_name.ln_type;
 		__entry->status		= gl->gl_lksb.sb_status;
@@ -333,7 +333,7 @@ TRACE_EVENT(gfs2_pin,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= bd->bd_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= bd->bd_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->pin		= pin;
 		__entry->len		= bd->bd_bh->b_size;
 		__entry->block		= bd->bd_bh->b_blocknr;
@@ -449,7 +449,7 @@ TRACE_EVENT(gfs2_bmap,
 	),
 
 	TP_fast_assign(
-		__entry->dev            = ip->i_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev            = ip->i_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->lblock		= lblock;
 		__entry->pblock		= buffer_mapped(bh) ?  bh->b_blocknr : 0;
 		__entry->inum		= ip->i_no_addr;
@@ -489,7 +489,7 @@ TRACE_EVENT(gfs2_block_alloc,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= rgd->rd_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= rgd->rd_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->start		= block;
 		__entry->inum		= ip->i_no_addr;
 		__entry->len		= len;
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 88bff24..b95d0d6 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -158,7 +158,7 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
 void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
 {
 	struct gfs2_trans *tr = current->journal_info;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct address_space *mapping = bh->b_page->mapping;
 	struct gfs2_inode *ip = GFS2_I(mapping->host);
 	struct gfs2_bufdata *bd;
@@ -224,7 +224,7 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
 void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
 {
 
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_bufdata *bd;
 
 	lock_buffer(bh);
-- 
2.1.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks
  2015-07-09 18:25 [Cluster-devel] [GFS2 PATCH 0/2] Increase GFS2 glock scalability Bob Peterson
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 1/2] GFS2: Move glock superblock pointer to field gl_name Bob Peterson
@ 2015-07-09 18:25 ` Bob Peterson
  2015-07-13 11:19   ` Steven Whitehouse
                     ` (3 more replies)
  1 sibling, 4 replies; 14+ messages in thread
From: Bob Peterson @ 2015-07-09 18:25 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch changes the glock hash table from a normal hash table to
a resizable hash table, which scales better. This also simplifies
a lot of code.
---
 fs/gfs2/glock.c  | 282 +++++++++++++++++++++----------------------------------
 fs/gfs2/incore.h |   4 +-
 2 files changed, 111 insertions(+), 175 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 25e0389..813de00 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -34,6 +34,7 @@
 #include <linux/percpu.h>
 #include <linux/list_sort.h>
 #include <linux/lockref.h>
+#include <linux/rhashtable.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -51,8 +52,12 @@
 
 struct gfs2_glock_iter {
 	int hash;			/* hash bucket index           */
-	unsigned nhash;			/* Index within current bucket */
 	struct gfs2_sbd *sdp;		/* incore superblock           */
+};
+
+struct gfs2_glock_rht_iter {
+	struct gfs2_sbd *sdp;		/* incore superblock           */
+	struct rhashtable_iter hti;	/* rhashtable iterator         */
 	struct gfs2_glock *gl;		/* current glock struct        */
 	loff_t last_pos;		/* last position               */
 };
@@ -70,44 +75,20 @@ static DEFINE_SPINLOCK(lru_lock);
 
 #define GFS2_GL_HASH_SHIFT      15
 #define GFS2_GL_HASH_SIZE       (1 << GFS2_GL_HASH_SHIFT)
-#define GFS2_GL_HASH_MASK       (GFS2_GL_HASH_SIZE - 1)
-
-static struct hlist_bl_head gl_hash_table[GFS2_GL_HASH_SIZE];
-static struct dentry *gfs2_root;
-
-/**
- * gl_hash() - Turn glock number into hash bucket number
- * @lock: The glock number
- *
- * Returns: The number of the corresponding hash bucket
- */
-
-static unsigned int gl_hash(const struct gfs2_sbd *sdp,
-			    const struct lm_lockname *name)
-{
-	unsigned int h;
-
-	h = jhash(&name->ln_number, sizeof(u64), 0);
-	h = jhash(&name->ln_type, sizeof(unsigned int), h);
-	h = jhash(&sdp, sizeof(struct gfs2_sbd *), h);
-	h &= GFS2_GL_HASH_MASK;
-
-	return h;
-}
 
-static inline void spin_lock_bucket(unsigned int hash)
-{
-	hlist_bl_lock(&gl_hash_table[hash]);
-}
+struct rhashtable_params ht_parms = {
+	.nelem_hint = GFS2_GL_HASH_SIZE * 3 / 4,
+	.key_len = sizeof(struct lm_lockname),
+	.key_offset = offsetof(struct gfs2_glock, gl_name),
+	.head_offset = offsetof(struct gfs2_glock, gl_node),
+	.hashfn = jhash,
+};
 
-static inline void spin_unlock_bucket(unsigned int hash)
-{
-	hlist_bl_unlock(&gl_hash_table[hash]);
-}
+static struct rhashtable gl_hash_table;
 
-static void gfs2_glock_dealloc(struct rcu_head *rcu)
+void gfs2_glock_free(struct gfs2_glock *gl)
 {
-	struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
 	if (gl->gl_ops->go_flags & GLOF_ASPACE) {
 		kmem_cache_free(gfs2_glock_aspace_cachep, gl);
@@ -115,13 +96,6 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
 		kfree(gl->gl_lksb.sb_lvbptr);
 		kmem_cache_free(gfs2_glock_cachep, gl);
 	}
-}
-
-void gfs2_glock_free(struct gfs2_glock *gl)
-{
-	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
-
-	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
 	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
 		wake_up(&sdp->sd_glock_wait);
 }
@@ -202,9 +176,8 @@ void gfs2_glock_put(struct gfs2_glock *gl)
 
 	gfs2_glock_remove_from_lru(gl);
 	spin_unlock(&gl->gl_lockref.lock);
-	spin_lock_bucket(gl->gl_hash);
-	hlist_bl_del_rcu(&gl->gl_list);
-	spin_unlock_bucket(gl->gl_hash);
+	if (gl->gl_node.next != NULL)
+		rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms);
 	GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
 	GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
 	trace_gfs2_glock_put(gl);
@@ -212,30 +185,6 @@ void gfs2_glock_put(struct gfs2_glock *gl)
 }
 
 /**
- * search_bucket() - Find struct gfs2_glock by lock number
- * @bucket: the bucket to search
- * @name: The lock name
- *
- * Returns: NULL, or the struct gfs2_glock with the requested number
- */
-
-static struct gfs2_glock *search_bucket(unsigned int hash,
-					const struct lm_lockname *name)
-{
-	struct gfs2_glock *gl;
-	struct hlist_bl_node *h;
-
-	hlist_bl_for_each_entry_rcu(gl, h, &gl_hash_table[hash], gl_list) {
-		if (!lm_name_equal(&gl->gl_name, name))
-			continue;
-		if (lockref_get_not_dead(&gl->gl_lockref))
-			return gl;
-	}
-
-	return NULL;
-}
-
-/**
  * may_grant - check if its ok to grant a new lock
  * @gl: The glock
  * @gh: The lock request which we wish to grant
@@ -704,14 +653,14 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	struct lm_lockname name = { .ln_number = number,
 				    .ln_type = glops->go_type,
 				    .ln_sbd = sdp };
-	struct gfs2_glock *gl, *tmp;
-	unsigned int hash = gl_hash(sdp, &name);
+	struct gfs2_glock *gl, *tmp = NULL;
 	struct address_space *mapping;
 	struct kmem_cache *cachep;
+	int ret, tries = 0;
 
-	rcu_read_lock();
-	gl = search_bucket(hash, &name);
-	rcu_read_unlock();
+	gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
+	if (gl && !lockref_get_not_dead(&gl->gl_lockref))
+		gl = NULL;
 
 	*glp = gl;
 	if (gl)
@@ -738,13 +687,13 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	}
 
 	atomic_inc(&sdp->sd_glock_disposal);
+	gl->gl_node.next = NULL;
 	gl->gl_flags = 0;
 	gl->gl_name = name;
 	gl->gl_lockref.count = 1;
 	gl->gl_state = LM_ST_UNLOCKED;
 	gl->gl_target = LM_ST_UNLOCKED;
 	gl->gl_demote_state = LM_ST_EXCLUSIVE;
-	gl->gl_hash = hash;
 	gl->gl_ops = glops;
 	gl->gl_dstamp = ktime_set(0, 0);
 	preempt_disable();
@@ -769,22 +718,34 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 		mapping->writeback_index = 0;
 	}
 
-	spin_lock_bucket(hash);
-	tmp = search_bucket(hash, &name);
-	if (tmp) {
-		spin_unlock_bucket(hash);
-		kfree(gl->gl_lksb.sb_lvbptr);
-		kmem_cache_free(cachep, gl);
-		atomic_dec(&sdp->sd_glock_disposal);
-		gl = tmp;
-	} else {
-		hlist_bl_add_head_rcu(&gl->gl_list, &gl_hash_table[hash]);
-		spin_unlock_bucket(hash);
+again:
+	ret = rhashtable_lookup_insert_fast(&gl_hash_table, &gl->gl_node,
+					    ht_parms);
+	if (ret == 0) {
+		*glp = gl;
+		return 0;
 	}
 
-	*glp = gl;
+	if (ret == -EEXIST) {
+		ret = 0;
+		tmp = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
+		if (tmp == NULL || !lockref_get_not_dead(&tmp->gl_lockref)) {
+			if (++tries < 100) {
+				cond_resched();
+				goto again;
+			}
+			tmp = NULL;
+			ret = -ENOMEM;
+		}
+	} else {
+		WARN_ON_ONCE(ret);
+	}
+	kfree(gl->gl_lksb.sb_lvbptr);
+	kmem_cache_free(cachep, gl);
+	atomic_dec(&sdp->sd_glock_disposal);
+	*glp = tmp;
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -1460,31 +1421,24 @@ static struct shrinker glock_shrinker = {
  *
  */
 
-static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
-			  unsigned int hash)
+static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
 {
 	struct gfs2_glock *gl;
-	struct hlist_bl_head *head = &gl_hash_table[hash];
-	struct hlist_bl_node *pos;
+	struct rhash_head *pos, *next;
+	const struct bucket_table *tbl;
+	int i;
 
-	rcu_read_lock();
-	hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
-		if ((gl->gl_name.ln_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
-			examiner(gl);
+	tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
+	for (i = 0; i < tbl->size; i++) {
+		rht_for_each_entry_safe(gl, pos, next, tbl, i, gl_node) {
+			if ((gl->gl_name.ln_sbd == sdp) &&
+			    lockref_get_not_dead(&gl->gl_lockref))
+				examiner(gl);
+		}
 	}
-	rcu_read_unlock();
 	cond_resched();
 }
 
-static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
-{
-	unsigned x;
-
-	for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
-		examine_bucket(examiner, sdp, x);
-}
-
-
 /**
  * thaw_glock - thaw out a glock which has an unprocessed reply waiting
  * @gl: The glock to thaw
@@ -1802,20 +1756,24 @@ static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
 
 int __init gfs2_glock_init(void)
 {
-	unsigned i;
-	for(i = 0; i < GFS2_GL_HASH_SIZE; i++) {
-		INIT_HLIST_BL_HEAD(&gl_hash_table[i]);
-	}
+	int ret;
+
+	ret = rhashtable_init(&gl_hash_table, &ht_parms);
+	if (ret < 0)
+		return ret;
 
 	glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
 					  WQ_HIGHPRI | WQ_FREEZABLE, 0);
-	if (!glock_workqueue)
+	if (!glock_workqueue) {
+		rhashtable_destroy(&gl_hash_table);
 		return -ENOMEM;
+	}
 	gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
 						WQ_MEM_RECLAIM | WQ_FREEZABLE,
 						0);
 	if (!gfs2_delete_workqueue) {
 		destroy_workqueue(glock_workqueue);
+		rhashtable_destroy(&gl_hash_table);
 		return -ENOMEM;
 	}
 
@@ -1827,72 +1785,36 @@ int __init gfs2_glock_init(void)
 void gfs2_glock_exit(void)
 {
 	unregister_shrinker(&glock_shrinker);
+	rhashtable_destroy(&gl_hash_table);
 	destroy_workqueue(glock_workqueue);
 	destroy_workqueue(gfs2_delete_workqueue);
 }
 
-static inline struct gfs2_glock *glock_hash_chain(unsigned hash)
+static void gfs2_glock_iter_next(struct gfs2_glock_rht_iter *gi)
 {
-	return hlist_bl_entry(hlist_bl_first_rcu(&gl_hash_table[hash]),
-			      struct gfs2_glock, gl_list);
-}
-
-static inline struct gfs2_glock *glock_hash_next(struct gfs2_glock *gl)
-{
-	return hlist_bl_entry(rcu_dereference(gl->gl_list.next),
-			      struct gfs2_glock, gl_list);
-}
-
-static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
-{
-	struct gfs2_glock *gl;
-
 	do {
-		gl = gi->gl;
-		if (gl) {
-			gi->gl = glock_hash_next(gl);
-			gi->nhash++;
-		} else {
-			if (gi->hash >= GFS2_GL_HASH_SIZE) {
-				rcu_read_unlock();
-				return 1;
-			}
-			gi->gl = glock_hash_chain(gi->hash);
-			gi->nhash = 0;
-		}
-		while (gi->gl == NULL) {
-			gi->hash++;
-			if (gi->hash >= GFS2_GL_HASH_SIZE) {
-				rcu_read_unlock();
-				return 1;
-			}
-			gi->gl = glock_hash_chain(gi->hash);
-			gi->nhash = 0;
-		}
+		gi->gl = rhashtable_walk_next(&gi->hti);
 	/* Skip entries for other sb and dead entries */
-	} while (gi->sdp != gi->gl->gl_name.ln_sbd ||
-		 __lockref_is_dead(&gi->gl->gl_lockref));
-
-	return 0;
+	} while ((gi->gl) && ((gi->sdp != gi->gl->gl_name.ln_sbd) ||
+			      __lockref_is_dead(&gi->gl->gl_lockref)));
 }
 
 static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct gfs2_glock_iter *gi = seq->private;
+	struct gfs2_glock_rht_iter *gi = seq->private;
 	loff_t n = *pos;
+	int ret;
 
 	if (gi->last_pos <= *pos)
-		n = gi->nhash + (*pos - gi->last_pos);
-	else
-		gi->hash = 0;
+		n = (*pos - gi->last_pos);
 
-	gi->nhash = 0;
-	rcu_read_lock();
+	ret = rhashtable_walk_start(&gi->hti);
+	if (ret)
+		return NULL;
 
 	do {
-		if (gfs2_glock_iter_next(gi))
-			return NULL;
-	} while (n--);
+		gfs2_glock_iter_next(gi);
+	} while (gi->gl && n--);
 
 	gi->last_pos = *pos;
 	return gi->gl;
@@ -1901,23 +1823,20 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
 static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
 				 loff_t *pos)
 {
-	struct gfs2_glock_iter *gi = seq->private;
+	struct gfs2_glock_rht_iter *gi = seq->private;
 
 	(*pos)++;
 	gi->last_pos = *pos;
-	if (gfs2_glock_iter_next(gi))
-		return NULL;
-
+	gfs2_glock_iter_next(gi);
 	return gi->gl;
 }
 
 static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
 {
-	struct gfs2_glock_iter *gi = seq->private;
+	struct gfs2_glock_rht_iter *gi = seq->private;
 
-	if (gi->gl)
-		rcu_read_unlock();
 	gi->gl = NULL;
+	rhashtable_walk_stop(&gi->hti);
 }
 
 static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
@@ -1981,29 +1900,46 @@ static const struct seq_operations gfs2_sbstats_seq_ops = {
 static int gfs2_glocks_open(struct inode *inode, struct file *file)
 {
 	int ret = seq_open_private(file, &gfs2_glock_seq_ops,
-				   sizeof(struct gfs2_glock_iter));
+				   sizeof(struct gfs2_glock_rht_iter));
 	if (ret == 0) {
 		struct seq_file *seq = file->private_data;
-		struct gfs2_glock_iter *gi = seq->private;
+		struct gfs2_glock_rht_iter *gi = seq->private;
+
 		gi->sdp = inode->i_private;
+		gi->last_pos = 0;
 		seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
 		if (seq->buf)
 			seq->size = GFS2_SEQ_GOODSIZE;
+		gi->gl = NULL;
+		ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
 	}
 	return ret;
 }
 
+static int gfs2_glocks_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = file->private_data;
+	struct gfs2_glock_rht_iter *gi = seq->private;
+
+	gi->gl = NULL;
+	rhashtable_walk_exit(&gi->hti);
+	return seq_release_private(inode, file);
+}
+
 static int gfs2_glstats_open(struct inode *inode, struct file *file)
 {
 	int ret = seq_open_private(file, &gfs2_glstats_seq_ops,
-				   sizeof(struct gfs2_glock_iter));
+				   sizeof(struct gfs2_glock_rht_iter));
 	if (ret == 0) {
 		struct seq_file *seq = file->private_data;
-		struct gfs2_glock_iter *gi = seq->private;
+		struct gfs2_glock_rht_iter *gi = seq->private;
 		gi->sdp = inode->i_private;
+		gi->last_pos = 0;
 		seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
 		if (seq->buf)
 			seq->size = GFS2_SEQ_GOODSIZE;
+		gi->gl = NULL;
+		ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
 	}
 	return ret;
 }
@@ -2025,7 +1961,7 @@ static const struct file_operations gfs2_glocks_fops = {
 	.open    = gfs2_glocks_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release_private,
+	.release = gfs2_glocks_release,
 };
 
 static const struct file_operations gfs2_glstats_fops = {
@@ -2033,7 +1969,7 @@ static const struct file_operations gfs2_glstats_fops = {
 	.open    = gfs2_glstats_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release_private,
+	.release = gfs2_glocks_release,
 };
 
 static const struct file_operations gfs2_sbstats_fops = {
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 4de7853..0d63715 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -22,6 +22,7 @@
 #include <linux/ktime.h>
 #include <linux/percpu.h>
 #include <linux/lockref.h>
+#include <linux/rhashtable.h>
 
 #define DIO_WAIT	0x00000010
 #define DIO_METADATA	0x00000020
@@ -342,7 +343,6 @@ struct gfs2_glock {
 		     gl_req:2,		/* State in last dlm request */
 		     gl_reply:8;	/* Last reply from the dlm */
 
-	unsigned int gl_hash;
 	unsigned long gl_demote_time; /* time of first demote request */
 	long gl_hold_time;
 	struct list_head gl_holders;
@@ -368,7 +368,7 @@ struct gfs2_glock {
 			loff_t end;
 		} gl_vm;
 	};
-	struct rcu_head gl_rcu;
+	struct rhash_head gl_node;
 };
 
 #define GFS2_MIN_LVB_SIZE 32	/* Min size of LVB that gfs2 supports */
-- 
2.1.0



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 1/2] GFS2: Move glock superblock pointer to field gl_name
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 1/2] GFS2: Move glock superblock pointer to field gl_name Bob Peterson
@ 2015-07-13 11:19   ` Steven Whitehouse
  2015-07-13 13:39     ` [Cluster-devel] [GFS2 PATCH 1/2][TRY #2] " Bob Peterson
  0 siblings, 1 reply; 14+ messages in thread
From: Steven Whitehouse @ 2015-07-13 11:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,

On 09/07/15 19:25, Bob Peterson wrote:
> What uniquely identifies a glock in the glock hash table is not
> gl_name, but gl_name and its superblock pointer. This patch makes
> the gl_name field correspond to a unique glock identifier. That will
> allow us to simplify hashing with a future patch, since the hash
> algorithm can then take the gl_name and hash its components in one
> operation.
> ---
[snip]
> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> index a1ec7c2..4de7853 100644
> --- a/fs/gfs2/incore.h
> +++ b/fs/gfs2/incore.h
> @@ -205,11 +205,13 @@ enum {
>   struct lm_lockname {
>   	u64 ln_number;
>   	unsigned int ln_type;
> +	struct gfs2_sbd *ln_sbd;
>   };
>   
This looks like its adding a hole on 64 bit arches... can we swap the 
order of ln_type and ln_sbd, or even make the sbd the first element of 
this? That way a memcmp of two of lm_locknames doesn't have to include 
the hole in the comparison, which I assume is what you want here?

Steve.



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks Bob Peterson
@ 2015-07-13 11:19   ` Steven Whitehouse
  2015-08-24 13:16   ` Andreas Gruenbacher
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: Steven Whitehouse @ 2015-07-13 11:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,

Looks good. Acked-by: Steven Whitehouse <swhiteho@redhat.com>

Steve.

On 09/07/15 19:25, Bob Peterson wrote:
> This patch changes the glock hash table from a normal hash table to
> a resizable hash table, which scales better. This also simplifies
> a lot of code.
> ---
>   fs/gfs2/glock.c  | 282 +++++++++++++++++++++----------------------------------
>   fs/gfs2/incore.h |   4 +-
>   2 files changed, 111 insertions(+), 175 deletions(-)
>
> diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
> index 25e0389..813de00 100644
> --- a/fs/gfs2/glock.c
> +++ b/fs/gfs2/glock.c
> @@ -34,6 +34,7 @@
>   #include <linux/percpu.h>
>   #include <linux/list_sort.h>
>   #include <linux/lockref.h>
> +#include <linux/rhashtable.h>
>   
>   #include "gfs2.h"
>   #include "incore.h"
> @@ -51,8 +52,12 @@
>   
>   struct gfs2_glock_iter {
>   	int hash;			/* hash bucket index           */
> -	unsigned nhash;			/* Index within current bucket */
>   	struct gfs2_sbd *sdp;		/* incore superblock           */
> +};
> +
> +struct gfs2_glock_rht_iter {
> +	struct gfs2_sbd *sdp;		/* incore superblock           */
> +	struct rhashtable_iter hti;	/* rhashtable iterator         */
>   	struct gfs2_glock *gl;		/* current glock struct        */
>   	loff_t last_pos;		/* last position               */
>   };
> @@ -70,44 +75,20 @@ static DEFINE_SPINLOCK(lru_lock);
>   
>   #define GFS2_GL_HASH_SHIFT      15
>   #define GFS2_GL_HASH_SIZE       (1 << GFS2_GL_HASH_SHIFT)
> -#define GFS2_GL_HASH_MASK       (GFS2_GL_HASH_SIZE - 1)
> -
> -static struct hlist_bl_head gl_hash_table[GFS2_GL_HASH_SIZE];
> -static struct dentry *gfs2_root;
> -
> -/**
> - * gl_hash() - Turn glock number into hash bucket number
> - * @lock: The glock number
> - *
> - * Returns: The number of the corresponding hash bucket
> - */
> -
> -static unsigned int gl_hash(const struct gfs2_sbd *sdp,
> -			    const struct lm_lockname *name)
> -{
> -	unsigned int h;
> -
> -	h = jhash(&name->ln_number, sizeof(u64), 0);
> -	h = jhash(&name->ln_type, sizeof(unsigned int), h);
> -	h = jhash(&sdp, sizeof(struct gfs2_sbd *), h);
> -	h &= GFS2_GL_HASH_MASK;
> -
> -	return h;
> -}
>   
> -static inline void spin_lock_bucket(unsigned int hash)
> -{
> -	hlist_bl_lock(&gl_hash_table[hash]);
> -}
> +struct rhashtable_params ht_parms = {
> +	.nelem_hint = GFS2_GL_HASH_SIZE * 3 / 4,
> +	.key_len = sizeof(struct lm_lockname),
> +	.key_offset = offsetof(struct gfs2_glock, gl_name),
> +	.head_offset = offsetof(struct gfs2_glock, gl_node),
> +	.hashfn = jhash,
> +};
>   
> -static inline void spin_unlock_bucket(unsigned int hash)
> -{
> -	hlist_bl_unlock(&gl_hash_table[hash]);
> -}
> +static struct rhashtable gl_hash_table;
>   
> -static void gfs2_glock_dealloc(struct rcu_head *rcu)
> +void gfs2_glock_free(struct gfs2_glock *gl)
>   {
> -	struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   
>   	if (gl->gl_ops->go_flags & GLOF_ASPACE) {
>   		kmem_cache_free(gfs2_glock_aspace_cachep, gl);
> @@ -115,13 +96,6 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
>   		kfree(gl->gl_lksb.sb_lvbptr);
>   		kmem_cache_free(gfs2_glock_cachep, gl);
>   	}
> -}
> -
> -void gfs2_glock_free(struct gfs2_glock *gl)
> -{
> -	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
> -
> -	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
>   	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
>   		wake_up(&sdp->sd_glock_wait);
>   }
> @@ -202,9 +176,8 @@ void gfs2_glock_put(struct gfs2_glock *gl)
>   
>   	gfs2_glock_remove_from_lru(gl);
>   	spin_unlock(&gl->gl_lockref.lock);
> -	spin_lock_bucket(gl->gl_hash);
> -	hlist_bl_del_rcu(&gl->gl_list);
> -	spin_unlock_bucket(gl->gl_hash);
> +	if (gl->gl_node.next != NULL)
> +		rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms);
>   	GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
>   	GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
>   	trace_gfs2_glock_put(gl);
> @@ -212,30 +185,6 @@ void gfs2_glock_put(struct gfs2_glock *gl)
>   }
>   
>   /**
> - * search_bucket() - Find struct gfs2_glock by lock number
> - * @bucket: the bucket to search
> - * @name: The lock name
> - *
> - * Returns: NULL, or the struct gfs2_glock with the requested number
> - */
> -
> -static struct gfs2_glock *search_bucket(unsigned int hash,
> -					const struct lm_lockname *name)
> -{
> -	struct gfs2_glock *gl;
> -	struct hlist_bl_node *h;
> -
> -	hlist_bl_for_each_entry_rcu(gl, h, &gl_hash_table[hash], gl_list) {
> -		if (!lm_name_equal(&gl->gl_name, name))
> -			continue;
> -		if (lockref_get_not_dead(&gl->gl_lockref))
> -			return gl;
> -	}
> -
> -	return NULL;
> -}
> -
> -/**
>    * may_grant - check if its ok to grant a new lock
>    * @gl: The glock
>    * @gh: The lock request which we wish to grant
> @@ -704,14 +653,14 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>   	struct lm_lockname name = { .ln_number = number,
>   				    .ln_type = glops->go_type,
>   				    .ln_sbd = sdp };
> -	struct gfs2_glock *gl, *tmp;
> -	unsigned int hash = gl_hash(sdp, &name);
> +	struct gfs2_glock *gl, *tmp = NULL;
>   	struct address_space *mapping;
>   	struct kmem_cache *cachep;
> +	int ret, tries = 0;
>   
> -	rcu_read_lock();
> -	gl = search_bucket(hash, &name);
> -	rcu_read_unlock();
> +	gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
> +	if (gl && !lockref_get_not_dead(&gl->gl_lockref))
> +		gl = NULL;
>   
>   	*glp = gl;
>   	if (gl)
> @@ -738,13 +687,13 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>   	}
>   
>   	atomic_inc(&sdp->sd_glock_disposal);
> +	gl->gl_node.next = NULL;
>   	gl->gl_flags = 0;
>   	gl->gl_name = name;
>   	gl->gl_lockref.count = 1;
>   	gl->gl_state = LM_ST_UNLOCKED;
>   	gl->gl_target = LM_ST_UNLOCKED;
>   	gl->gl_demote_state = LM_ST_EXCLUSIVE;
> -	gl->gl_hash = hash;
>   	gl->gl_ops = glops;
>   	gl->gl_dstamp = ktime_set(0, 0);
>   	preempt_disable();
> @@ -769,22 +718,34 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>   		mapping->writeback_index = 0;
>   	}
>   
> -	spin_lock_bucket(hash);
> -	tmp = search_bucket(hash, &name);
> -	if (tmp) {
> -		spin_unlock_bucket(hash);
> -		kfree(gl->gl_lksb.sb_lvbptr);
> -		kmem_cache_free(cachep, gl);
> -		atomic_dec(&sdp->sd_glock_disposal);
> -		gl = tmp;
> -	} else {
> -		hlist_bl_add_head_rcu(&gl->gl_list, &gl_hash_table[hash]);
> -		spin_unlock_bucket(hash);
> +again:
> +	ret = rhashtable_lookup_insert_fast(&gl_hash_table, &gl->gl_node,
> +					    ht_parms);
> +	if (ret == 0) {
> +		*glp = gl;
> +		return 0;
>   	}
>   
> -	*glp = gl;
> +	if (ret == -EEXIST) {
> +		ret = 0;
> +		tmp = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
> +		if (tmp == NULL || !lockref_get_not_dead(&tmp->gl_lockref)) {
> +			if (++tries < 100) {
> +				cond_resched();
> +				goto again;
> +			}
> +			tmp = NULL;
> +			ret = -ENOMEM;
> +		}
> +	} else {
> +		WARN_ON_ONCE(ret);
> +	}
> +	kfree(gl->gl_lksb.sb_lvbptr);
> +	kmem_cache_free(cachep, gl);
> +	atomic_dec(&sdp->sd_glock_disposal);
> +	*glp = tmp;
>   
> -	return 0;
> +	return ret;
>   }
>   
>   /**
> @@ -1460,31 +1421,24 @@ static struct shrinker glock_shrinker = {
>    *
>    */
>   
> -static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
> -			  unsigned int hash)
> +static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
>   {
>   	struct gfs2_glock *gl;
> -	struct hlist_bl_head *head = &gl_hash_table[hash];
> -	struct hlist_bl_node *pos;
> +	struct rhash_head *pos, *next;
> +	const struct bucket_table *tbl;
> +	int i;
>   
> -	rcu_read_lock();
> -	hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
> -		if ((gl->gl_name.ln_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
> -			examiner(gl);
> +	tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
> +	for (i = 0; i < tbl->size; i++) {
> +		rht_for_each_entry_safe(gl, pos, next, tbl, i, gl_node) {
> +			if ((gl->gl_name.ln_sbd == sdp) &&
> +			    lockref_get_not_dead(&gl->gl_lockref))
> +				examiner(gl);
> +		}
>   	}
> -	rcu_read_unlock();
>   	cond_resched();
>   }
>   
> -static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
> -{
> -	unsigned x;
> -
> -	for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
> -		examine_bucket(examiner, sdp, x);
> -}
> -
> -
>   /**
>    * thaw_glock - thaw out a glock which has an unprocessed reply waiting
>    * @gl: The glock to thaw
> @@ -1802,20 +1756,24 @@ static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
>   
>   int __init gfs2_glock_init(void)
>   {
> -	unsigned i;
> -	for(i = 0; i < GFS2_GL_HASH_SIZE; i++) {
> -		INIT_HLIST_BL_HEAD(&gl_hash_table[i]);
> -	}
> +	int ret;
> +
> +	ret = rhashtable_init(&gl_hash_table, &ht_parms);
> +	if (ret < 0)
> +		return ret;
>   
>   	glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
>   					  WQ_HIGHPRI | WQ_FREEZABLE, 0);
> -	if (!glock_workqueue)
> +	if (!glock_workqueue) {
> +		rhashtable_destroy(&gl_hash_table);
>   		return -ENOMEM;
> +	}
>   	gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
>   						WQ_MEM_RECLAIM | WQ_FREEZABLE,
>   						0);
>   	if (!gfs2_delete_workqueue) {
>   		destroy_workqueue(glock_workqueue);
> +		rhashtable_destroy(&gl_hash_table);
>   		return -ENOMEM;
>   	}
>   
> @@ -1827,72 +1785,36 @@ int __init gfs2_glock_init(void)
>   void gfs2_glock_exit(void)
>   {
>   	unregister_shrinker(&glock_shrinker);
> +	rhashtable_destroy(&gl_hash_table);
>   	destroy_workqueue(glock_workqueue);
>   	destroy_workqueue(gfs2_delete_workqueue);
>   }
>   
> -static inline struct gfs2_glock *glock_hash_chain(unsigned hash)
> +static void gfs2_glock_iter_next(struct gfs2_glock_rht_iter *gi)
>   {
> -	return hlist_bl_entry(hlist_bl_first_rcu(&gl_hash_table[hash]),
> -			      struct gfs2_glock, gl_list);
> -}
> -
> -static inline struct gfs2_glock *glock_hash_next(struct gfs2_glock *gl)
> -{
> -	return hlist_bl_entry(rcu_dereference(gl->gl_list.next),
> -			      struct gfs2_glock, gl_list);
> -}
> -
> -static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
> -{
> -	struct gfs2_glock *gl;
> -
>   	do {
> -		gl = gi->gl;
> -		if (gl) {
> -			gi->gl = glock_hash_next(gl);
> -			gi->nhash++;
> -		} else {
> -			if (gi->hash >= GFS2_GL_HASH_SIZE) {
> -				rcu_read_unlock();
> -				return 1;
> -			}
> -			gi->gl = glock_hash_chain(gi->hash);
> -			gi->nhash = 0;
> -		}
> -		while (gi->gl == NULL) {
> -			gi->hash++;
> -			if (gi->hash >= GFS2_GL_HASH_SIZE) {
> -				rcu_read_unlock();
> -				return 1;
> -			}
> -			gi->gl = glock_hash_chain(gi->hash);
> -			gi->nhash = 0;
> -		}
> +		gi->gl = rhashtable_walk_next(&gi->hti);
>   	/* Skip entries for other sb and dead entries */
> -	} while (gi->sdp != gi->gl->gl_name.ln_sbd ||
> -		 __lockref_is_dead(&gi->gl->gl_lockref));
> -
> -	return 0;
> +	} while ((gi->gl) && ((gi->sdp != gi->gl->gl_name.ln_sbd) ||
> +			      __lockref_is_dead(&gi->gl->gl_lockref)));
>   }
>   
>   static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
>   {
> -	struct gfs2_glock_iter *gi = seq->private;
> +	struct gfs2_glock_rht_iter *gi = seq->private;
>   	loff_t n = *pos;
> +	int ret;
>   
>   	if (gi->last_pos <= *pos)
> -		n = gi->nhash + (*pos - gi->last_pos);
> -	else
> -		gi->hash = 0;
> +		n = (*pos - gi->last_pos);
>   
> -	gi->nhash = 0;
> -	rcu_read_lock();
> +	ret = rhashtable_walk_start(&gi->hti);
> +	if (ret)
> +		return NULL;
>   
>   	do {
> -		if (gfs2_glock_iter_next(gi))
> -			return NULL;
> -	} while (n--);
> +		gfs2_glock_iter_next(gi);
> +	} while (gi->gl && n--);
>   
>   	gi->last_pos = *pos;
>   	return gi->gl;
> @@ -1901,23 +1823,20 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
>   static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
>   				 loff_t *pos)
>   {
> -	struct gfs2_glock_iter *gi = seq->private;
> +	struct gfs2_glock_rht_iter *gi = seq->private;
>   
>   	(*pos)++;
>   	gi->last_pos = *pos;
> -	if (gfs2_glock_iter_next(gi))
> -		return NULL;
> -
> +	gfs2_glock_iter_next(gi);
>   	return gi->gl;
>   }
>   
>   static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
>   {
> -	struct gfs2_glock_iter *gi = seq->private;
> +	struct gfs2_glock_rht_iter *gi = seq->private;
>   
> -	if (gi->gl)
> -		rcu_read_unlock();
>   	gi->gl = NULL;
> +	rhashtable_walk_stop(&gi->hti);
>   }
>   
>   static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
> @@ -1981,29 +1900,46 @@ static const struct seq_operations gfs2_sbstats_seq_ops = {
>   static int gfs2_glocks_open(struct inode *inode, struct file *file)
>   {
>   	int ret = seq_open_private(file, &gfs2_glock_seq_ops,
> -				   sizeof(struct gfs2_glock_iter));
> +				   sizeof(struct gfs2_glock_rht_iter));
>   	if (ret == 0) {
>   		struct seq_file *seq = file->private_data;
> -		struct gfs2_glock_iter *gi = seq->private;
> +		struct gfs2_glock_rht_iter *gi = seq->private;
> +
>   		gi->sdp = inode->i_private;
> +		gi->last_pos = 0;
>   		seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
>   		if (seq->buf)
>   			seq->size = GFS2_SEQ_GOODSIZE;
> +		gi->gl = NULL;
> +		ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
>   	}
>   	return ret;
>   }
>   
> +static int gfs2_glocks_release(struct inode *inode, struct file *file)
> +{
> +	struct seq_file *seq = file->private_data;
> +	struct gfs2_glock_rht_iter *gi = seq->private;
> +
> +	gi->gl = NULL;
> +	rhashtable_walk_exit(&gi->hti);
> +	return seq_release_private(inode, file);
> +}
> +
>   static int gfs2_glstats_open(struct inode *inode, struct file *file)
>   {
>   	int ret = seq_open_private(file, &gfs2_glstats_seq_ops,
> -				   sizeof(struct gfs2_glock_iter));
> +				   sizeof(struct gfs2_glock_rht_iter));
>   	if (ret == 0) {
>   		struct seq_file *seq = file->private_data;
> -		struct gfs2_glock_iter *gi = seq->private;
> +		struct gfs2_glock_rht_iter *gi = seq->private;
>   		gi->sdp = inode->i_private;
> +		gi->last_pos = 0;
>   		seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
>   		if (seq->buf)
>   			seq->size = GFS2_SEQ_GOODSIZE;
> +		gi->gl = NULL;
> +		ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
>   	}
>   	return ret;
>   }
> @@ -2025,7 +1961,7 @@ static const struct file_operations gfs2_glocks_fops = {
>   	.open    = gfs2_glocks_open,
>   	.read    = seq_read,
>   	.llseek  = seq_lseek,
> -	.release = seq_release_private,
> +	.release = gfs2_glocks_release,
>   };
>   
>   static const struct file_operations gfs2_glstats_fops = {
> @@ -2033,7 +1969,7 @@ static const struct file_operations gfs2_glstats_fops = {
>   	.open    = gfs2_glstats_open,
>   	.read    = seq_read,
>   	.llseek  = seq_lseek,
> -	.release = seq_release_private,
> +	.release = gfs2_glocks_release,
>   };
>   
>   static const struct file_operations gfs2_sbstats_fops = {
> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> index 4de7853..0d63715 100644
> --- a/fs/gfs2/incore.h
> +++ b/fs/gfs2/incore.h
> @@ -22,6 +22,7 @@
>   #include <linux/ktime.h>
>   #include <linux/percpu.h>
>   #include <linux/lockref.h>
> +#include <linux/rhashtable.h>
>   
>   #define DIO_WAIT	0x00000010
>   #define DIO_METADATA	0x00000020
> @@ -342,7 +343,6 @@ struct gfs2_glock {
>   		     gl_req:2,		/* State in last dlm request */
>   		     gl_reply:8;	/* Last reply from the dlm */
>   
> -	unsigned int gl_hash;
>   	unsigned long gl_demote_time; /* time of first demote request */
>   	long gl_hold_time;
>   	struct list_head gl_holders;
> @@ -368,7 +368,7 @@ struct gfs2_glock {
>   			loff_t end;
>   		} gl_vm;
>   	};
> -	struct rcu_head gl_rcu;
> +	struct rhash_head gl_node;
>   };
>   
>   #define GFS2_MIN_LVB_SIZE 32	/* Min size of LVB that gfs2 supports */



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 1/2][TRY #2] GFS2: Move glock superblock pointer to field gl_name
  2015-07-13 11:19   ` Steven Whitehouse
@ 2015-07-13 13:39     ` Bob Peterson
  2015-07-13 19:19       ` Steven Whitehouse
  0 siblings, 1 reply; 14+ messages in thread
From: Bob Peterson @ 2015-07-13 13:39 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,

----- Original Message -----
> Hi,
> 
> On 09/07/15 19:25, Bob Peterson wrote:
> > What uniquely identifies a glock in the glock hash table is not
> > gl_name, but gl_name and its superblock pointer. This patch makes
> > the gl_name field correspond to a unique glock identifier. That will
> > allow us to simplify hashing with a future patch, since the hash
> > algorithm can then take the gl_name and hash its components in one
> > operation.
> > ---
> [snip]
> > diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> > index a1ec7c2..4de7853 100644
> > --- a/fs/gfs2/incore.h
> > +++ b/fs/gfs2/incore.h
> > @@ -205,11 +205,13 @@ enum {
> >   struct lm_lockname {
> >   	u64 ln_number;
> >   	unsigned int ln_type;
> > +	struct gfs2_sbd *ln_sbd;
> >   };
> >   
> This looks like its adding a hole on 64 bit arches... can we swap the
> order of ln_type and ln_sbd, or even make the sbd the first element of
> this? That way a memcmp of two of lm_locknames doesn't have to include
> the hole in the comparison, which I assume is what you want here?
> 
> Steve.

Good catch. This replacement for patch #1 is identical except for
the placement of ln_sbd in the lm_lockname structure.

Regards,

Bob Peterson
Red Hat File Systems
---
commit 0ed2b820a4f3d44e447b3e724f5355cd2f7ee4ee
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Mon Mar 16 11:52:05 2015 -0500

GFS2: Move glock superblock pointer to field gl_name

What uniquely identifies a glock in the glock hash table is not
gl_name, but gl_name and its superblock pointer. This patch makes
the gl_name field correspond to a unique glock identifier. That will
allow us to simplify hashing with a future patch, since the hash
algorithm can then take the gl_name and hash its components in one
operation.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
---
 fs/gfs2/glock.c      | 32 +++++++++++++++-----------------
 fs/gfs2/glops.c      | 38 ++++++++++++++++++++------------------
 fs/gfs2/incore.h     |  9 +++++----
 fs/gfs2/lock_dlm.c   | 10 +++++-----
 fs/gfs2/lops.c       |  6 +++---
 fs/gfs2/meta_io.c    |  6 +++---
 fs/gfs2/meta_io.h    |  2 +-
 fs/gfs2/quota.c      | 22 +++++++++++-----------
 fs/gfs2/rgrp.c       |  2 +-
 fs/gfs2/trace_gfs2.h | 18 +++++++++---------
 fs/gfs2/trans.c      |  4 ++--
 11 files changed, 75 insertions(+), 74 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index a38e38f..25e0389 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -119,7 +119,7 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
 
 void gfs2_glock_free(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
 	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
 	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
@@ -192,7 +192,7 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
 
 void gfs2_glock_put(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct address_space *mapping = gfs2_glock2aspace(gl);
 
 	if (lockref_put_or_lock(&gl->gl_lockref))
@@ -220,7 +220,6 @@ void gfs2_glock_put(struct gfs2_glock *gl)
  */
 
 static struct gfs2_glock *search_bucket(unsigned int hash,
-					const struct gfs2_sbd *sdp,
 					const struct lm_lockname *name)
 {
 	struct gfs2_glock *gl;
@@ -229,8 +228,6 @@ static struct gfs2_glock *search_bucket(unsigned int hash,
 	hlist_bl_for_each_entry_rcu(gl, h, &gl_hash_table[hash], gl_list) {
 		if (!lm_name_equal(&gl->gl_name, name))
 			continue;
-		if (gl->gl_sbd != sdp)
-			continue;
 		if (lockref_get_not_dead(&gl->gl_lockref))
 			return gl;
 	}
@@ -506,7 +503,7 @@ __releases(&gl->gl_spin)
 __acquires(&gl->gl_spin)
 {
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	unsigned int lck_flags = gh ? gh->gh_flags : 0;
 	int ret;
 
@@ -628,7 +625,7 @@ out_unlock:
 static void delete_work_func(struct work_struct *work)
 {
 	struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete);
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip;
 	struct inode *inode;
 	u64 no_addr = gl->gl_name.ln_number;
@@ -704,14 +701,16 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 		   struct gfs2_glock **glp)
 {
 	struct super_block *s = sdp->sd_vfs;
-	struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type };
+	struct lm_lockname name = { .ln_number = number,
+				    .ln_type = glops->go_type,
+				    .ln_sbd = sdp };
 	struct gfs2_glock *gl, *tmp;
 	unsigned int hash = gl_hash(sdp, &name);
 	struct address_space *mapping;
 	struct kmem_cache *cachep;
 
 	rcu_read_lock();
-	gl = search_bucket(hash, sdp, &name);
+	gl = search_bucket(hash, &name);
 	rcu_read_unlock();
 
 	*glp = gl;
@@ -739,7 +738,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	}
 
 	atomic_inc(&sdp->sd_glock_disposal);
-	gl->gl_sbd = sdp;
 	gl->gl_flags = 0;
 	gl->gl_name = name;
 	gl->gl_lockref.count = 1;
@@ -772,7 +770,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	}
 
 	spin_lock_bucket(hash);
-	tmp = search_bucket(hash, sdp, &name);
+	tmp = search_bucket(hash, &name);
 	if (tmp) {
 		spin_unlock_bucket(hash);
 		kfree(gl->gl_lksb.sb_lvbptr);
@@ -928,7 +926,7 @@ __releases(&gl->gl_spin)
 __acquires(&gl->gl_spin)
 {
 	struct gfs2_glock *gl = gh->gh_gl;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct list_head *insert_pt = NULL;
 	struct gfs2_holder *gh2;
 	int try_futile = 0;
@@ -1006,7 +1004,7 @@ trap_recursive:
 int gfs2_glock_nq(struct gfs2_holder *gh)
 {
 	struct gfs2_glock *gl = gh->gh_gl;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	int error = 0;
 
 	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
@@ -1313,7 +1311,7 @@ static int gfs2_should_freeze(const struct gfs2_glock *gl)
 
 void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
 {
-	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
 
 	spin_lock(&gl->gl_spin);
 	gl->gl_reply = ret;
@@ -1471,7 +1469,7 @@ static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
 
 	rcu_read_lock();
 	hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
-		if ((gl->gl_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
+		if ((gl->gl_name.ln_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
 			examiner(gl);
 	}
 	rcu_read_unlock();
@@ -1569,7 +1567,7 @@ void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
 	int ret;
 
 	ret = gfs2_truncatei_resume(ip);
-	gfs2_assert_withdraw(gl->gl_sbd, ret == 0);
+	gfs2_assert_withdraw(gl->gl_name.ln_sbd, ret == 0);
 
 	spin_lock(&gl->gl_spin);
 	clear_bit(GLF_LOCK, &gl->gl_flags);
@@ -1872,7 +1870,7 @@ static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
 			gi->nhash = 0;
 		}
 	/* Skip entries for other sb and dead entries */
-	} while (gi->sdp != gi->gl->gl_sbd ||
+	} while (gi->sdp != gi->gl->gl_name.ln_sbd ||
 		 __lockref_is_dead(&gi->gl->gl_lockref));
 
 	return 0;
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index fa3fa5e..1f6c9c3 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -32,13 +32,15 @@ struct workqueue_struct *gfs2_freeze_wq;
 
 static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
 {
-	fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n",
+	fs_err(gl->gl_name.ln_sbd,
+	       "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page "
+	       "state 0x%lx\n",
 	       bh, (unsigned long long)bh->b_blocknr, bh->b_state,
 	       bh->b_page->mapping, bh->b_page->flags);
-	fs_err(gl->gl_sbd, "AIL glock %u:%llu mapping %p\n",
+	fs_err(gl->gl_name.ln_sbd, "AIL glock %u:%llu mapping %p\n",
 	       gl->gl_name.ln_type, gl->gl_name.ln_number,
 	       gfs2_glock2aspace(gl));
-	gfs2_lm_withdraw(gl->gl_sbd, "AIL error\n");
+	gfs2_lm_withdraw(gl->gl_name.ln_sbd, "AIL error\n");
 }
 
 /**
@@ -52,7 +54,7 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
 static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
 			     unsigned int nr_revokes)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct list_head *head = &gl->gl_ail_list;
 	struct gfs2_bufdata *bd, *tmp;
 	struct buffer_head *bh;
@@ -80,7 +82,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
 
 static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_trans tr;
 
 	memset(&tr, 0, sizeof(tr));
@@ -109,7 +111,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 
 void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	unsigned int revokes = atomic_read(&gl->gl_ail_count);
 	unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
 	int ret;
@@ -139,7 +141,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
 static void rgrp_go_sync(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct address_space *mapping = &sdp->sd_aspace;
 	struct gfs2_rgrpd *rgd;
 	int error;
@@ -179,7 +181,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 
 static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct address_space *mapping = &sdp->sd_aspace;
 	struct gfs2_rgrpd *rgd = gl->gl_object;
 
@@ -218,7 +220,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
 
 	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-	gfs2_log_flush(gl->gl_sbd, gl, NORMAL_FLUSH);
+	gfs2_log_flush(gl->gl_name.ln_sbd, gl, NORMAL_FLUSH);
 	filemap_fdatawrite(metamapping);
 	if (ip) {
 		struct address_space *mapping = ip->i_inode.i_mapping;
@@ -252,7 +254,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 {
 	struct gfs2_inode *ip = gl->gl_object;
 
-	gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
+	gfs2_assert_withdraw(gl->gl_name.ln_sbd, !atomic_read(&gl->gl_ail_count));
 
 	if (flags & DIO_METADATA) {
 		struct address_space *mapping = gfs2_glock2aspace(gl);
@@ -264,9 +266,9 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 		}
 	}
 
-	if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) {
-		gfs2_log_flush(gl->gl_sbd, NULL, NORMAL_FLUSH);
-		gl->gl_sbd->sd_rindex_uptodate = 0;
+	if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
+		gfs2_log_flush(gl->gl_name.ln_sbd, NULL, NORMAL_FLUSH);
+		gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
 	}
 	if (ip && S_ISREG(ip->i_inode.i_mode))
 		truncate_inode_pages(ip->i_inode.i_mapping, 0);
@@ -281,7 +283,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 
 static int inode_go_demote_ok(const struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_holder *gh;
 
 	if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object)
@@ -416,7 +418,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip)
 static int inode_go_lock(struct gfs2_holder *gh)
 {
 	struct gfs2_glock *gl = gh->gh_gl;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = gl->gl_object;
 	int error = 0;
 
@@ -477,7 +479,7 @@ static void inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
 static void freeze_go_sync(struct gfs2_glock *gl)
 {
 	int error = 0;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
 	if (gl->gl_state == LM_ST_SHARED &&
 	    test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
@@ -500,7 +502,7 @@ static void freeze_go_sync(struct gfs2_glock *gl)
 
 static int freeze_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
 	struct gfs2_glock *j_gl = ip->i_gl;
 	struct gfs2_log_header_host head;
@@ -545,7 +547,7 @@ static int freeze_go_demote_ok(const struct gfs2_glock *gl)
 static void iopen_go_callback(struct gfs2_glock *gl, bool remote)
 {
 	struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 
 	if (!remote || (sdp->sd_vfs->s_flags & MS_RDONLY))
 		return;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index a1ec7c2..35a55f3 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -203,13 +203,15 @@ enum {
 };
 
 struct lm_lockname {
+	struct gfs2_sbd *ln_sbd;
 	u64 ln_number;
 	unsigned int ln_type;
 };
 
 #define lm_name_equal(name1, name2) \
-        (((name1)->ln_number == (name2)->ln_number) && \
-         ((name1)->ln_type == (name2)->ln_type))
+        (((name1)->ln_number == (name2)->ln_number) &&	\
+	 ((name1)->ln_type == (name2)->ln_type) &&	\
+	 ((name1)->ln_sbd == (name2)->ln_sbd))
 
 
 struct gfs2_glock_operations {
@@ -327,7 +329,6 @@ enum {
 
 struct gfs2_glock {
 	struct hlist_bl_node gl_list;
-	struct gfs2_sbd *gl_sbd;
 	unsigned long gl_flags;		/* GLF_... */
 	struct lm_lockname gl_name;
 
@@ -835,7 +836,7 @@ static inline void gfs2_glstats_inc(struct gfs2_glock *gl, int which)
 
 static inline void gfs2_sbstats_inc(const struct gfs2_glock *gl, int which)
 {
-	const struct gfs2_sbd *sdp = gl->gl_sbd;
+	const struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	preempt_disable();
 	this_cpu_ptr(sdp->sd_lkstats)->lkstats[gl->gl_name.ln_type].stats[which]++;
 	preempt_enable();
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 641383a..c962cfc 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -80,7 +80,7 @@ static inline void gfs2_update_reply_times(struct gfs2_glock *gl)
 
 	preempt_disable();
 	rtt = ktime_to_ns(ktime_sub(ktime_get_real(), gl->gl_dstamp));
-	lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats);
+	lks = this_cpu_ptr(gl->gl_name.ln_sbd->sd_lkstats);
 	gfs2_update_stats(&gl->gl_stats, index, rtt);		/* Local */
 	gfs2_update_stats(&lks->lkstats[gltype], index, rtt);	/* Global */
 	preempt_enable();
@@ -108,7 +108,7 @@ static inline void gfs2_update_request_times(struct gfs2_glock *gl)
 	dstamp = gl->gl_dstamp;
 	gl->gl_dstamp = ktime_get_real();
 	irt = ktime_to_ns(ktime_sub(gl->gl_dstamp, dstamp));
-	lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats);
+	lks = this_cpu_ptr(gl->gl_name.ln_sbd->sd_lkstats);
 	gfs2_update_stats(&gl->gl_stats, GFS2_LKS_SIRT, irt);		/* Local */
 	gfs2_update_stats(&lks->lkstats[gltype], GFS2_LKS_SIRT, irt);	/* Global */
 	preempt_enable();
@@ -253,7 +253,7 @@ static void gfs2_reverse_hex(char *c, u64 value)
 static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
 		     unsigned int flags)
 {
-	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
 	int req;
 	u32 lkf;
 	char strname[GDLM_STRNAME_BYTES] = "";
@@ -281,7 +281,7 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
 
 static void gdlm_put_lock(struct gfs2_glock *gl)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
 	int lvb_needs_unlock = 0;
 	int error;
@@ -319,7 +319,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
 
 static void gdlm_cancel(struct gfs2_glock *gl)
 {
-	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
+	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
 	dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
 }
 
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 2c1ae86..7833394 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -70,7 +70,7 @@ static bool buffer_is_rgrp(const struct gfs2_bufdata *bd)
 static void maybe_release_space(struct gfs2_bufdata *bd)
 {
 	struct gfs2_glock *gl = bd->bd_gl;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_rgrpd *rgd = gl->gl_object;
 	unsigned int index = bd->bd_bh->b_blocknr - gl->gl_name.ln_number;
 	struct gfs2_bitmap *bi = rgd->rd_bits + index;
@@ -585,7 +585,7 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
 static void gfs2_meta_sync(struct gfs2_glock *gl)
 {
 	struct address_space *mapping = gfs2_glock2aspace(gl);
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	int error;
 
 	if (mapping == NULL)
@@ -595,7 +595,7 @@ static void gfs2_meta_sync(struct gfs2_glock *gl)
 	error = filemap_fdatawait(mapping);
 
 	if (error)
-		gfs2_io_error(gl->gl_sbd);
+		gfs2_io_error(gl->gl_name.ln_sbd);
 }
 
 static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index b984a6e..0e1d4be 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -114,7 +114,7 @@ const struct address_space_operations gfs2_rgrp_aops = {
 struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
 {
 	struct address_space *mapping = gfs2_glock2aspace(gl);
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct page *page;
 	struct buffer_head *bh;
 	unsigned int shift;
@@ -200,7 +200,7 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
 int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
 		   struct buffer_head **bhp)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct buffer_head *bh;
 
 	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
@@ -362,7 +362,7 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
 
 struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
 {
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct buffer_head *first_bh, *bh;
 	u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >>
 			  sdp->sd_sb.sb_bsize_shift;
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index ac5d802..8ca1615 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -44,7 +44,7 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
 {
 	struct inode *inode = mapping->host;
 	if (mapping->a_ops == &gfs2_meta_aops)
-		return (((struct gfs2_glock *)mapping) - 1)->gl_sbd;
+		return (((struct gfs2_glock *)mapping) - 1)->gl_name.ln_sbd;
 	else if (mapping->a_ops == &gfs2_rgrp_aops)
 		return container_of(mapping, struct gfs2_sbd, sd_aspace);
 	else
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 9b61f92..3a31226 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -119,7 +119,7 @@ static void gfs2_qd_dispose(struct list_head *list)
 
 	while (!list_empty(list)) {
 		qd = list_entry(list->next, struct gfs2_quota_data, qd_lru);
-		sdp = qd->qd_gl->gl_sbd;
+		sdp = qd->qd_gl->gl_name.ln_sbd;
 
 		list_del(&qd->qd_lru);
 
@@ -302,7 +302,7 @@ static int qd_get(struct gfs2_sbd *sdp, struct kqid qid,
 
 static void qd_hold(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	gfs2_assert(sdp, !__lockref_is_dead(&qd->qd_lockref));
 	lockref_get(&qd->qd_lockref);
 }
@@ -367,7 +367,7 @@ static void slot_put(struct gfs2_quota_data *qd)
 
 static int bh_get(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
 	unsigned int block, offset;
 	struct buffer_head *bh;
@@ -414,7 +414,7 @@ fail:
 
 static void bh_put(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 
 	mutex_lock(&sdp->sd_quota_mutex);
 	gfs2_assert(sdp, qd->qd_bh_count);
@@ -486,7 +486,7 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp)
 
 static void qd_unlock(struct gfs2_quota_data *qd)
 {
-	gfs2_assert_warn(qd->qd_gl->gl_sbd,
+	gfs2_assert_warn(qd->qd_gl->gl_name.ln_sbd,
 			 test_bit(QDF_LOCKED, &qd->qd_flags));
 	clear_bit(QDF_LOCKED, &qd->qd_flags);
 	bh_put(qd);
@@ -614,7 +614,7 @@ static int sort_qd(const void *a, const void *b)
 
 static void do_qc(struct gfs2_quota_data *qd, s64 change)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
 	struct gfs2_quota_change *qc = qd->qd_bh_qc;
 	s64 x;
@@ -831,7 +831,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
 
 static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
 {
-	struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
 	struct gfs2_alloc_parms ap = { .aflags = 0, };
 	unsigned int data_blocks, ind_blocks;
@@ -922,7 +922,7 @@ out:
 		gfs2_glock_dq_uninit(&ghs[qx]);
 	mutex_unlock(&ip->i_inode.i_mutex);
 	kfree(ghs);
-	gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl, NORMAL_FLUSH);
+	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl, NORMAL_FLUSH);
 	return error;
 }
 
@@ -954,7 +954,7 @@ static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
 static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
 		    struct gfs2_holder *q_gh)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
 	struct gfs2_holder i_gh;
 	int error;
@@ -1037,7 +1037,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
 
 static int need_sync(struct gfs2_quota_data *qd)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 	struct gfs2_tune *gt = &sdp->sd_tune;
 	s64 value;
 	unsigned int num, den;
@@ -1125,7 +1125,7 @@ out:
 
 static int print_message(struct gfs2_quota_data *qd, char *type)
 {
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
+	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
 
 	fs_info(sdp, "quota %s for %s %u\n",
 		type,
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index c6c6232..c92ae7fd 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1860,7 +1860,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
 static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops)
 {
 	const struct gfs2_glock *gl = rgd->rd_gl;
-	const struct gfs2_sbd *sdp = gl->gl_sbd;
+	const struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_lkstats *st;
 	s64 r_dcount, l_dcount;
 	s64 l_srttb, a_srttb = 0;
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
index 20c007d..fff47d0 100644
--- a/fs/gfs2/trace_gfs2.h
+++ b/fs/gfs2/trace_gfs2.h
@@ -104,7 +104,7 @@ TRACE_EVENT(gfs2_glock_state_change,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->glnum		= gl->gl_name.ln_number;
 		__entry->gltype		= gl->gl_name.ln_type;
 		__entry->cur_state	= glock_trace_state(gl->gl_state);
@@ -140,7 +140,7 @@ TRACE_EVENT(gfs2_glock_put,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->gltype		= gl->gl_name.ln_type;
 		__entry->glnum		= gl->gl_name.ln_number;
 		__entry->cur_state	= glock_trace_state(gl->gl_state);
@@ -174,7 +174,7 @@ TRACE_EVENT(gfs2_demote_rq,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->gltype		= gl->gl_name.ln_type;
 		__entry->glnum		= gl->gl_name.ln_number;
 		__entry->cur_state	= glock_trace_state(gl->gl_state);
@@ -209,7 +209,7 @@ TRACE_EVENT(gfs2_promote,
 	),
 
 	TP_fast_assign(
-		__entry->dev	= gh->gh_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev	= gh->gh_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->glnum	= gh->gh_gl->gl_name.ln_number;
 		__entry->gltype	= gh->gh_gl->gl_name.ln_type;
 		__entry->first	= first;
@@ -239,7 +239,7 @@ TRACE_EVENT(gfs2_glock_queue,
 	),
 
 	TP_fast_assign(
-		__entry->dev	= gh->gh_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev	= gh->gh_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->glnum	= gh->gh_gl->gl_name.ln_number;
 		__entry->gltype	= gh->gh_gl->gl_name.ln_type;
 		__entry->queue	= queue;
@@ -278,7 +278,7 @@ TRACE_EVENT(gfs2_glock_lock_time,
 	),
 
 	TP_fast_assign(
-		__entry->dev            = gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev            = gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->glnum          = gl->gl_name.ln_number;
 		__entry->gltype         = gl->gl_name.ln_type;
 		__entry->status		= gl->gl_lksb.sb_status;
@@ -333,7 +333,7 @@ TRACE_EVENT(gfs2_pin,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= bd->bd_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= bd->bd_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->pin		= pin;
 		__entry->len		= bd->bd_bh->b_size;
 		__entry->block		= bd->bd_bh->b_blocknr;
@@ -449,7 +449,7 @@ TRACE_EVENT(gfs2_bmap,
 	),
 
 	TP_fast_assign(
-		__entry->dev            = ip->i_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev            = ip->i_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->lblock		= lblock;
 		__entry->pblock		= buffer_mapped(bh) ?  bh->b_blocknr : 0;
 		__entry->inum		= ip->i_no_addr;
@@ -489,7 +489,7 @@ TRACE_EVENT(gfs2_block_alloc,
 	),
 
 	TP_fast_assign(
-		__entry->dev		= rgd->rd_gl->gl_sbd->sd_vfs->s_dev;
+		__entry->dev		= rgd->rd_gl->gl_name.ln_sbd->sd_vfs->s_dev;
 		__entry->start		= block;
 		__entry->inum		= ip->i_no_addr;
 		__entry->len		= len;
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 88bff24..b95d0d6 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -158,7 +158,7 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
 void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
 {
 	struct gfs2_trans *tr = current->journal_info;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct address_space *mapping = bh->b_page->mapping;
 	struct gfs2_inode *ip = GFS2_I(mapping->host);
 	struct gfs2_bufdata *bd;
@@ -224,7 +224,7 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
 void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
 {
 
-	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
 	struct gfs2_bufdata *bd;
 
 	lock_buffer(bh);



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 1/2][TRY #2] GFS2: Move glock superblock pointer to field gl_name
  2015-07-13 13:39     ` [Cluster-devel] [GFS2 PATCH 1/2][TRY #2] " Bob Peterson
@ 2015-07-13 19:19       ` Steven Whitehouse
  2015-08-22 22:00         ` Andreas Gruenbacher
  0 siblings, 1 reply; 14+ messages in thread
From: Steven Whitehouse @ 2015-07-13 19:19 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,

On 13/07/15 14:39, Bob Peterson wrote:
> Hi,
>
> ----- Original Message -----
>> Hi,
>>
>> On 09/07/15 19:25, Bob Peterson wrote:
>>> What uniquely identifies a glock in the glock hash table is not
>>> gl_name, but gl_name and its superblock pointer. This patch makes
>>> the gl_name field correspond to a unique glock identifier. That will
>>> allow us to simplify hashing with a future patch, since the hash
>>> algorithm can then take the gl_name and hash its components in one
>>> operation.
>>> ---
>> [snip]
>>> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
>>> index a1ec7c2..4de7853 100644
>>> --- a/fs/gfs2/incore.h
>>> +++ b/fs/gfs2/incore.h
>>> @@ -205,11 +205,13 @@ enum {
>>>    struct lm_lockname {
>>>    	u64 ln_number;
>>>    	unsigned int ln_type;
>>> +	struct gfs2_sbd *ln_sbd;
>>>    };
>>>    
>> This looks like its adding a hole on 64 bit arches... can we swap the
>> order of ln_type and ln_sbd, or even make the sbd the first element of
>> this? That way a memcmp of two of lm_locknames doesn't have to include
>> the hole in the comparison, which I assume is what you want here?
>>
>> Steve.
> Good catch. This replacement for patch #1 is identical except for
> the placement of ln_sbd in the lm_lockname structure.
>
> Regards,
>
> Bob Peterson
> Red Hat File Systems
> ---

That looks good now. Acked-by: Steven Whitehouse <swhiteho@redhat.com>

Steve.

> commit 0ed2b820a4f3d44e447b3e724f5355cd2f7ee4ee
> Author: Bob Peterson <rpeterso@redhat.com>
> Date:   Mon Mar 16 11:52:05 2015 -0500
>
> GFS2: Move glock superblock pointer to field gl_name
>
> What uniquely identifies a glock in the glock hash table is not
> gl_name, but gl_name and its superblock pointer. This patch makes
> the gl_name field correspond to a unique glock identifier. That will
> allow us to simplify hashing with a future patch, since the hash
> algorithm can then take the gl_name and hash its components in one
> operation.
>
> Signed-off-by: Bob Peterson <rpeterso@redhat.com>
> ---
>   fs/gfs2/glock.c      | 32 +++++++++++++++-----------------
>   fs/gfs2/glops.c      | 38 ++++++++++++++++++++------------------
>   fs/gfs2/incore.h     |  9 +++++----
>   fs/gfs2/lock_dlm.c   | 10 +++++-----
>   fs/gfs2/lops.c       |  6 +++---
>   fs/gfs2/meta_io.c    |  6 +++---
>   fs/gfs2/meta_io.h    |  2 +-
>   fs/gfs2/quota.c      | 22 +++++++++++-----------
>   fs/gfs2/rgrp.c       |  2 +-
>   fs/gfs2/trace_gfs2.h | 18 +++++++++---------
>   fs/gfs2/trans.c      |  4 ++--
>   11 files changed, 75 insertions(+), 74 deletions(-)
>
> diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
> index a38e38f..25e0389 100644
> --- a/fs/gfs2/glock.c
> +++ b/fs/gfs2/glock.c
> @@ -119,7 +119,7 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
>   
>   void gfs2_glock_free(struct gfs2_glock *gl)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   
>   	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
>   	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
> @@ -192,7 +192,7 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
>   
>   void gfs2_glock_put(struct gfs2_glock *gl)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct address_space *mapping = gfs2_glock2aspace(gl);
>   
>   	if (lockref_put_or_lock(&gl->gl_lockref))
> @@ -220,7 +220,6 @@ void gfs2_glock_put(struct gfs2_glock *gl)
>    */
>   
>   static struct gfs2_glock *search_bucket(unsigned int hash,
> -					const struct gfs2_sbd *sdp,
>   					const struct lm_lockname *name)
>   {
>   	struct gfs2_glock *gl;
> @@ -229,8 +228,6 @@ static struct gfs2_glock *search_bucket(unsigned int hash,
>   	hlist_bl_for_each_entry_rcu(gl, h, &gl_hash_table[hash], gl_list) {
>   		if (!lm_name_equal(&gl->gl_name, name))
>   			continue;
> -		if (gl->gl_sbd != sdp)
> -			continue;
>   		if (lockref_get_not_dead(&gl->gl_lockref))
>   			return gl;
>   	}
> @@ -506,7 +503,7 @@ __releases(&gl->gl_spin)
>   __acquires(&gl->gl_spin)
>   {
>   	const struct gfs2_glock_operations *glops = gl->gl_ops;
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	unsigned int lck_flags = gh ? gh->gh_flags : 0;
>   	int ret;
>   
> @@ -628,7 +625,7 @@ out_unlock:
>   static void delete_work_func(struct work_struct *work)
>   {
>   	struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete);
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct gfs2_inode *ip;
>   	struct inode *inode;
>   	u64 no_addr = gl->gl_name.ln_number;
> @@ -704,14 +701,16 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>   		   struct gfs2_glock **glp)
>   {
>   	struct super_block *s = sdp->sd_vfs;
> -	struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type };
> +	struct lm_lockname name = { .ln_number = number,
> +				    .ln_type = glops->go_type,
> +				    .ln_sbd = sdp };
>   	struct gfs2_glock *gl, *tmp;
>   	unsigned int hash = gl_hash(sdp, &name);
>   	struct address_space *mapping;
>   	struct kmem_cache *cachep;
>   
>   	rcu_read_lock();
> -	gl = search_bucket(hash, sdp, &name);
> +	gl = search_bucket(hash, &name);
>   	rcu_read_unlock();
>   
>   	*glp = gl;
> @@ -739,7 +738,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>   	}
>   
>   	atomic_inc(&sdp->sd_glock_disposal);
> -	gl->gl_sbd = sdp;
>   	gl->gl_flags = 0;
>   	gl->gl_name = name;
>   	gl->gl_lockref.count = 1;
> @@ -772,7 +770,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>   	}
>   
>   	spin_lock_bucket(hash);
> -	tmp = search_bucket(hash, sdp, &name);
> +	tmp = search_bucket(hash, &name);
>   	if (tmp) {
>   		spin_unlock_bucket(hash);
>   		kfree(gl->gl_lksb.sb_lvbptr);
> @@ -928,7 +926,7 @@ __releases(&gl->gl_spin)
>   __acquires(&gl->gl_spin)
>   {
>   	struct gfs2_glock *gl = gh->gh_gl;
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct list_head *insert_pt = NULL;
>   	struct gfs2_holder *gh2;
>   	int try_futile = 0;
> @@ -1006,7 +1004,7 @@ trap_recursive:
>   int gfs2_glock_nq(struct gfs2_holder *gh)
>   {
>   	struct gfs2_glock *gl = gh->gh_gl;
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	int error = 0;
>   
>   	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
> @@ -1313,7 +1311,7 @@ static int gfs2_should_freeze(const struct gfs2_glock *gl)
>   
>   void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
>   {
> -	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
> +	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
>   
>   	spin_lock(&gl->gl_spin);
>   	gl->gl_reply = ret;
> @@ -1471,7 +1469,7 @@ static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
>   
>   	rcu_read_lock();
>   	hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
> -		if ((gl->gl_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
> +		if ((gl->gl_name.ln_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
>   			examiner(gl);
>   	}
>   	rcu_read_unlock();
> @@ -1569,7 +1567,7 @@ void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
>   	int ret;
>   
>   	ret = gfs2_truncatei_resume(ip);
> -	gfs2_assert_withdraw(gl->gl_sbd, ret == 0);
> +	gfs2_assert_withdraw(gl->gl_name.ln_sbd, ret == 0);
>   
>   	spin_lock(&gl->gl_spin);
>   	clear_bit(GLF_LOCK, &gl->gl_flags);
> @@ -1872,7 +1870,7 @@ static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
>   			gi->nhash = 0;
>   		}
>   	/* Skip entries for other sb and dead entries */
> -	} while (gi->sdp != gi->gl->gl_sbd ||
> +	} while (gi->sdp != gi->gl->gl_name.ln_sbd ||
>   		 __lockref_is_dead(&gi->gl->gl_lockref));
>   
>   	return 0;
> diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
> index fa3fa5e..1f6c9c3 100644
> --- a/fs/gfs2/glops.c
> +++ b/fs/gfs2/glops.c
> @@ -32,13 +32,15 @@ struct workqueue_struct *gfs2_freeze_wq;
>   
>   static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
>   {
> -	fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n",
> +	fs_err(gl->gl_name.ln_sbd,
> +	       "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page "
> +	       "state 0x%lx\n",
>   	       bh, (unsigned long long)bh->b_blocknr, bh->b_state,
>   	       bh->b_page->mapping, bh->b_page->flags);
> -	fs_err(gl->gl_sbd, "AIL glock %u:%llu mapping %p\n",
> +	fs_err(gl->gl_name.ln_sbd, "AIL glock %u:%llu mapping %p\n",
>   	       gl->gl_name.ln_type, gl->gl_name.ln_number,
>   	       gfs2_glock2aspace(gl));
> -	gfs2_lm_withdraw(gl->gl_sbd, "AIL error\n");
> +	gfs2_lm_withdraw(gl->gl_name.ln_sbd, "AIL error\n");
>   }
>   
>   /**
> @@ -52,7 +54,7 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
>   static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
>   			     unsigned int nr_revokes)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct list_head *head = &gl->gl_ail_list;
>   	struct gfs2_bufdata *bd, *tmp;
>   	struct buffer_head *bh;
> @@ -80,7 +82,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
>   
>   static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct gfs2_trans tr;
>   
>   	memset(&tr, 0, sizeof(tr));
> @@ -109,7 +111,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
>   
>   void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	unsigned int revokes = atomic_read(&gl->gl_ail_count);
>   	unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
>   	int ret;
> @@ -139,7 +141,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
>   
>   static void rgrp_go_sync(struct gfs2_glock *gl)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct address_space *mapping = &sdp->sd_aspace;
>   	struct gfs2_rgrpd *rgd;
>   	int error;
> @@ -179,7 +181,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
>   
>   static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct address_space *mapping = &sdp->sd_aspace;
>   	struct gfs2_rgrpd *rgd = gl->gl_object;
>   
> @@ -218,7 +220,7 @@ static void inode_go_sync(struct gfs2_glock *gl)
>   
>   	GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
>   
> -	gfs2_log_flush(gl->gl_sbd, gl, NORMAL_FLUSH);
> +	gfs2_log_flush(gl->gl_name.ln_sbd, gl, NORMAL_FLUSH);
>   	filemap_fdatawrite(metamapping);
>   	if (ip) {
>   		struct address_space *mapping = ip->i_inode.i_mapping;
> @@ -252,7 +254,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
>   {
>   	struct gfs2_inode *ip = gl->gl_object;
>   
> -	gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
> +	gfs2_assert_withdraw(gl->gl_name.ln_sbd, !atomic_read(&gl->gl_ail_count));
>   
>   	if (flags & DIO_METADATA) {
>   		struct address_space *mapping = gfs2_glock2aspace(gl);
> @@ -264,9 +266,9 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
>   		}
>   	}
>   
> -	if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) {
> -		gfs2_log_flush(gl->gl_sbd, NULL, NORMAL_FLUSH);
> -		gl->gl_sbd->sd_rindex_uptodate = 0;
> +	if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
> +		gfs2_log_flush(gl->gl_name.ln_sbd, NULL, NORMAL_FLUSH);
> +		gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
>   	}
>   	if (ip && S_ISREG(ip->i_inode.i_mode))
>   		truncate_inode_pages(ip->i_inode.i_mapping, 0);
> @@ -281,7 +283,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
>   
>   static int inode_go_demote_ok(const struct gfs2_glock *gl)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct gfs2_holder *gh;
>   
>   	if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object)
> @@ -416,7 +418,7 @@ int gfs2_inode_refresh(struct gfs2_inode *ip)
>   static int inode_go_lock(struct gfs2_holder *gh)
>   {
>   	struct gfs2_glock *gl = gh->gh_gl;
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct gfs2_inode *ip = gl->gl_object;
>   	int error = 0;
>   
> @@ -477,7 +479,7 @@ static void inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
>   static void freeze_go_sync(struct gfs2_glock *gl)
>   {
>   	int error = 0;
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   
>   	if (gl->gl_state == LM_ST_SHARED &&
>   	    test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
> @@ -500,7 +502,7 @@ static void freeze_go_sync(struct gfs2_glock *gl)
>   
>   static int freeze_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
>   	struct gfs2_glock *j_gl = ip->i_gl;
>   	struct gfs2_log_header_host head;
> @@ -545,7 +547,7 @@ static int freeze_go_demote_ok(const struct gfs2_glock *gl)
>   static void iopen_go_callback(struct gfs2_glock *gl, bool remote)
>   {
>   	struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object;
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   
>   	if (!remote || (sdp->sd_vfs->s_flags & MS_RDONLY))
>   		return;
> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> index a1ec7c2..35a55f3 100644
> --- a/fs/gfs2/incore.h
> +++ b/fs/gfs2/incore.h
> @@ -203,13 +203,15 @@ enum {
>   };
>   
>   struct lm_lockname {
> +	struct gfs2_sbd *ln_sbd;
>   	u64 ln_number;
>   	unsigned int ln_type;
>   };
>   
>   #define lm_name_equal(name1, name2) \
> -        (((name1)->ln_number == (name2)->ln_number) && \
> -         ((name1)->ln_type == (name2)->ln_type))
> +        (((name1)->ln_number == (name2)->ln_number) &&	\
> +	 ((name1)->ln_type == (name2)->ln_type) &&	\
> +	 ((name1)->ln_sbd == (name2)->ln_sbd))
>   
>   
>   struct gfs2_glock_operations {
> @@ -327,7 +329,6 @@ enum {
>   
>   struct gfs2_glock {
>   	struct hlist_bl_node gl_list;
> -	struct gfs2_sbd *gl_sbd;
>   	unsigned long gl_flags;		/* GLF_... */
>   	struct lm_lockname gl_name;
>   
> @@ -835,7 +836,7 @@ static inline void gfs2_glstats_inc(struct gfs2_glock *gl, int which)
>   
>   static inline void gfs2_sbstats_inc(const struct gfs2_glock *gl, int which)
>   {
> -	const struct gfs2_sbd *sdp = gl->gl_sbd;
> +	const struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	preempt_disable();
>   	this_cpu_ptr(sdp->sd_lkstats)->lkstats[gl->gl_name.ln_type].stats[which]++;
>   	preempt_enable();
> diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
> index 641383a..c962cfc 100644
> --- a/fs/gfs2/lock_dlm.c
> +++ b/fs/gfs2/lock_dlm.c
> @@ -80,7 +80,7 @@ static inline void gfs2_update_reply_times(struct gfs2_glock *gl)
>   
>   	preempt_disable();
>   	rtt = ktime_to_ns(ktime_sub(ktime_get_real(), gl->gl_dstamp));
> -	lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats);
> +	lks = this_cpu_ptr(gl->gl_name.ln_sbd->sd_lkstats);
>   	gfs2_update_stats(&gl->gl_stats, index, rtt);		/* Local */
>   	gfs2_update_stats(&lks->lkstats[gltype], index, rtt);	/* Global */
>   	preempt_enable();
> @@ -108,7 +108,7 @@ static inline void gfs2_update_request_times(struct gfs2_glock *gl)
>   	dstamp = gl->gl_dstamp;
>   	gl->gl_dstamp = ktime_get_real();
>   	irt = ktime_to_ns(ktime_sub(gl->gl_dstamp, dstamp));
> -	lks = this_cpu_ptr(gl->gl_sbd->sd_lkstats);
> +	lks = this_cpu_ptr(gl->gl_name.ln_sbd->sd_lkstats);
>   	gfs2_update_stats(&gl->gl_stats, GFS2_LKS_SIRT, irt);		/* Local */
>   	gfs2_update_stats(&lks->lkstats[gltype], GFS2_LKS_SIRT, irt);	/* Global */
>   	preempt_enable();
> @@ -253,7 +253,7 @@ static void gfs2_reverse_hex(char *c, u64 value)
>   static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
>   		     unsigned int flags)
>   {
> -	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
> +	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
>   	int req;
>   	u32 lkf;
>   	char strname[GDLM_STRNAME_BYTES] = "";
> @@ -281,7 +281,7 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
>   
>   static void gdlm_put_lock(struct gfs2_glock *gl)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
>   	int lvb_needs_unlock = 0;
>   	int error;
> @@ -319,7 +319,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
>   
>   static void gdlm_cancel(struct gfs2_glock *gl)
>   {
> -	struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
> +	struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
>   	dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
>   }
>   
> diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
> index 2c1ae86..7833394 100644
> --- a/fs/gfs2/lops.c
> +++ b/fs/gfs2/lops.c
> @@ -70,7 +70,7 @@ static bool buffer_is_rgrp(const struct gfs2_bufdata *bd)
>   static void maybe_release_space(struct gfs2_bufdata *bd)
>   {
>   	struct gfs2_glock *gl = bd->bd_gl;
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct gfs2_rgrpd *rgd = gl->gl_object;
>   	unsigned int index = bd->bd_bh->b_blocknr - gl->gl_name.ln_number;
>   	struct gfs2_bitmap *bi = rgd->rd_bits + index;
> @@ -585,7 +585,7 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
>   static void gfs2_meta_sync(struct gfs2_glock *gl)
>   {
>   	struct address_space *mapping = gfs2_glock2aspace(gl);
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	int error;
>   
>   	if (mapping == NULL)
> @@ -595,7 +595,7 @@ static void gfs2_meta_sync(struct gfs2_glock *gl)
>   	error = filemap_fdatawait(mapping);
>   
>   	if (error)
> -		gfs2_io_error(gl->gl_sbd);
> +		gfs2_io_error(gl->gl_name.ln_sbd);
>   }
>   
>   static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
> diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
> index b984a6e..0e1d4be 100644
> --- a/fs/gfs2/meta_io.c
> +++ b/fs/gfs2/meta_io.c
> @@ -114,7 +114,7 @@ const struct address_space_operations gfs2_rgrp_aops = {
>   struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
>   {
>   	struct address_space *mapping = gfs2_glock2aspace(gl);
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct page *page;
>   	struct buffer_head *bh;
>   	unsigned int shift;
> @@ -200,7 +200,7 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
>   int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
>   		   struct buffer_head **bhp)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct buffer_head *bh;
>   
>   	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
> @@ -362,7 +362,7 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
>   
>   struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
>   {
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct buffer_head *first_bh, *bh;
>   	u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >>
>   			  sdp->sd_sb.sb_bsize_shift;
> diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
> index ac5d802..8ca1615 100644
> --- a/fs/gfs2/meta_io.h
> +++ b/fs/gfs2/meta_io.h
> @@ -44,7 +44,7 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
>   {
>   	struct inode *inode = mapping->host;
>   	if (mapping->a_ops == &gfs2_meta_aops)
> -		return (((struct gfs2_glock *)mapping) - 1)->gl_sbd;
> +		return (((struct gfs2_glock *)mapping) - 1)->gl_name.ln_sbd;
>   	else if (mapping->a_ops == &gfs2_rgrp_aops)
>   		return container_of(mapping, struct gfs2_sbd, sd_aspace);
>   	else
> diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
> index 9b61f92..3a31226 100644
> --- a/fs/gfs2/quota.c
> +++ b/fs/gfs2/quota.c
> @@ -119,7 +119,7 @@ static void gfs2_qd_dispose(struct list_head *list)
>   
>   	while (!list_empty(list)) {
>   		qd = list_entry(list->next, struct gfs2_quota_data, qd_lru);
> -		sdp = qd->qd_gl->gl_sbd;
> +		sdp = qd->qd_gl->gl_name.ln_sbd;
>   
>   		list_del(&qd->qd_lru);
>   
> @@ -302,7 +302,7 @@ static int qd_get(struct gfs2_sbd *sdp, struct kqid qid,
>   
>   static void qd_hold(struct gfs2_quota_data *qd)
>   {
> -	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
> +	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
>   	gfs2_assert(sdp, !__lockref_is_dead(&qd->qd_lockref));
>   	lockref_get(&qd->qd_lockref);
>   }
> @@ -367,7 +367,7 @@ static void slot_put(struct gfs2_quota_data *qd)
>   
>   static int bh_get(struct gfs2_quota_data *qd)
>   {
> -	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
> +	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
>   	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
>   	unsigned int block, offset;
>   	struct buffer_head *bh;
> @@ -414,7 +414,7 @@ fail:
>   
>   static void bh_put(struct gfs2_quota_data *qd)
>   {
> -	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
> +	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
>   
>   	mutex_lock(&sdp->sd_quota_mutex);
>   	gfs2_assert(sdp, qd->qd_bh_count);
> @@ -486,7 +486,7 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp)
>   
>   static void qd_unlock(struct gfs2_quota_data *qd)
>   {
> -	gfs2_assert_warn(qd->qd_gl->gl_sbd,
> +	gfs2_assert_warn(qd->qd_gl->gl_name.ln_sbd,
>   			 test_bit(QDF_LOCKED, &qd->qd_flags));
>   	clear_bit(QDF_LOCKED, &qd->qd_flags);
>   	bh_put(qd);
> @@ -614,7 +614,7 @@ static int sort_qd(const void *a, const void *b)
>   
>   static void do_qc(struct gfs2_quota_data *qd, s64 change)
>   {
> -	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
> +	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
>   	struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
>   	struct gfs2_quota_change *qc = qd->qd_bh_qc;
>   	s64 x;
> @@ -831,7 +831,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
>   
>   static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
>   {
> -	struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_sbd;
> +	struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_name.ln_sbd;
>   	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
>   	struct gfs2_alloc_parms ap = { .aflags = 0, };
>   	unsigned int data_blocks, ind_blocks;
> @@ -922,7 +922,7 @@ out:
>   		gfs2_glock_dq_uninit(&ghs[qx]);
>   	mutex_unlock(&ip->i_inode.i_mutex);
>   	kfree(ghs);
> -	gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl, NORMAL_FLUSH);
> +	gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl, NORMAL_FLUSH);
>   	return error;
>   }
>   
> @@ -954,7 +954,7 @@ static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
>   static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
>   		    struct gfs2_holder *q_gh)
>   {
> -	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
> +	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
>   	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
>   	struct gfs2_holder i_gh;
>   	int error;
> @@ -1037,7 +1037,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
>   
>   static int need_sync(struct gfs2_quota_data *qd)
>   {
> -	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
> +	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
>   	struct gfs2_tune *gt = &sdp->sd_tune;
>   	s64 value;
>   	unsigned int num, den;
> @@ -1125,7 +1125,7 @@ out:
>   
>   static int print_message(struct gfs2_quota_data *qd, char *type)
>   {
> -	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
> +	struct gfs2_sbd *sdp = qd->qd_gl->gl_name.ln_sbd;
>   
>   	fs_info(sdp, "quota %s for %s %u\n",
>   		type,
> diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
> index c6c6232..c92ae7fd 100644
> --- a/fs/gfs2/rgrp.c
> +++ b/fs/gfs2/rgrp.c
> @@ -1860,7 +1860,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
>   static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops)
>   {
>   	const struct gfs2_glock *gl = rgd->rd_gl;
> -	const struct gfs2_sbd *sdp = gl->gl_sbd;
> +	const struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct gfs2_lkstats *st;
>   	s64 r_dcount, l_dcount;
>   	s64 l_srttb, a_srttb = 0;
> diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
> index 20c007d..fff47d0 100644
> --- a/fs/gfs2/trace_gfs2.h
> +++ b/fs/gfs2/trace_gfs2.h
> @@ -104,7 +104,7 @@ TRACE_EVENT(gfs2_glock_state_change,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->glnum		= gl->gl_name.ln_number;
>   		__entry->gltype		= gl->gl_name.ln_type;
>   		__entry->cur_state	= glock_trace_state(gl->gl_state);
> @@ -140,7 +140,7 @@ TRACE_EVENT(gfs2_glock_put,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->gltype		= gl->gl_name.ln_type;
>   		__entry->glnum		= gl->gl_name.ln_number;
>   		__entry->cur_state	= glock_trace_state(gl->gl_state);
> @@ -174,7 +174,7 @@ TRACE_EVENT(gfs2_demote_rq,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev		= gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev		= gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->gltype		= gl->gl_name.ln_type;
>   		__entry->glnum		= gl->gl_name.ln_number;
>   		__entry->cur_state	= glock_trace_state(gl->gl_state);
> @@ -209,7 +209,7 @@ TRACE_EVENT(gfs2_promote,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev	= gh->gh_gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev	= gh->gh_gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->glnum	= gh->gh_gl->gl_name.ln_number;
>   		__entry->gltype	= gh->gh_gl->gl_name.ln_type;
>   		__entry->first	= first;
> @@ -239,7 +239,7 @@ TRACE_EVENT(gfs2_glock_queue,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev	= gh->gh_gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev	= gh->gh_gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->glnum	= gh->gh_gl->gl_name.ln_number;
>   		__entry->gltype	= gh->gh_gl->gl_name.ln_type;
>   		__entry->queue	= queue;
> @@ -278,7 +278,7 @@ TRACE_EVENT(gfs2_glock_lock_time,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev            = gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev            = gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->glnum          = gl->gl_name.ln_number;
>   		__entry->gltype         = gl->gl_name.ln_type;
>   		__entry->status		= gl->gl_lksb.sb_status;
> @@ -333,7 +333,7 @@ TRACE_EVENT(gfs2_pin,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev		= bd->bd_gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev		= bd->bd_gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->pin		= pin;
>   		__entry->len		= bd->bd_bh->b_size;
>   		__entry->block		= bd->bd_bh->b_blocknr;
> @@ -449,7 +449,7 @@ TRACE_EVENT(gfs2_bmap,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev            = ip->i_gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev            = ip->i_gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->lblock		= lblock;
>   		__entry->pblock		= buffer_mapped(bh) ?  bh->b_blocknr : 0;
>   		__entry->inum		= ip->i_no_addr;
> @@ -489,7 +489,7 @@ TRACE_EVENT(gfs2_block_alloc,
>   	),
>   
>   	TP_fast_assign(
> -		__entry->dev		= rgd->rd_gl->gl_sbd->sd_vfs->s_dev;
> +		__entry->dev		= rgd->rd_gl->gl_name.ln_sbd->sd_vfs->s_dev;
>   		__entry->start		= block;
>   		__entry->inum		= ip->i_no_addr;
>   		__entry->len		= len;
> diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
> index 88bff24..b95d0d6 100644
> --- a/fs/gfs2/trans.c
> +++ b/fs/gfs2/trans.c
> @@ -158,7 +158,7 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
>   void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
>   {
>   	struct gfs2_trans *tr = current->journal_info;
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct address_space *mapping = bh->b_page->mapping;
>   	struct gfs2_inode *ip = GFS2_I(mapping->host);
>   	struct gfs2_bufdata *bd;
> @@ -224,7 +224,7 @@ static void meta_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
>   void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
>   {
>   
> -	struct gfs2_sbd *sdp = gl->gl_sbd;
> +	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>   	struct gfs2_bufdata *bd;
>   
>   	lock_buffer(bh);



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 1/2][TRY #2] GFS2: Move glock superblock pointer to field gl_name
  2015-07-13 19:19       ` Steven Whitehouse
@ 2015-08-22 22:00         ` Andreas Gruenbacher
  2015-08-23 10:53           ` Steven Whitehouse
  2015-08-26 14:12           ` Bob Peterson
  0 siblings, 2 replies; 14+ messages in thread
From: Andreas Gruenbacher @ 2015-08-22 22:00 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Bob,

how hard would it be to move the rhashtable into struct gfs2_sbd instead?

Thanks,
Andreas



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 1/2][TRY #2] GFS2: Move glock superblock pointer to field gl_name
  2015-08-22 22:00         ` Andreas Gruenbacher
@ 2015-08-23 10:53           ` Steven Whitehouse
  2015-08-26 14:12           ` Bob Peterson
  1 sibling, 0 replies; 14+ messages in thread
From: Steven Whitehouse @ 2015-08-23 10:53 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,

On 22/08/15 23:00, Andreas Gruenbacher wrote:
> Bob,
>
> how hard would it be to move the rhashtable into struct gfs2_sbd instead?
>
> Thanks,
> Andreas

What would be the advantage?

Steve.



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks Bob Peterson
  2015-07-13 11:19   ` Steven Whitehouse
@ 2015-08-24 13:16   ` Andreas Gruenbacher
  2015-08-24 13:31   ` Andreas Gruenbacher
  2015-08-24 13:46   ` Andreas Gruenbacher
  3 siblings, 0 replies; 14+ messages in thread
From: Andreas Gruenbacher @ 2015-08-24 13:16 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Bob,

2015-07-09 20:25 GMT+02:00 Bob Peterson <rpeterso@redhat.com>:
> This patch changes the glock hash table from a normal hash table to
> a resizable hash table, which scales better. This also simplifies
> a lot of code.
> ---
>  fs/gfs2/glock.c  | 282 +++++++++++++++++++++----------------------------------
>  fs/gfs2/incore.h |   4 +-
>  2 files changed, 111 insertions(+), 175 deletions(-)
>
> diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
> index 25e0389..813de00 100644
> --- a/fs/gfs2/glock.c
> +++ b/fs/gfs2/glock.c
> @@ -34,6 +34,7 @@
>  #include <linux/percpu.h>
>  #include <linux/list_sort.h>
>  #include <linux/lockref.h>
> +#include <linux/rhashtable.h>
>
>  #include "gfs2.h"
>  #include "incore.h"
> @@ -51,8 +52,12 @@
>
>  struct gfs2_glock_iter {
>         int hash;                       /* hash bucket index           */
> -       unsigned nhash;                 /* Index within current bucket */
>         struct gfs2_sbd *sdp;           /* incore superblock           */
> +};
> +
> +struct gfs2_glock_rht_iter {
> +       struct gfs2_sbd *sdp;           /* incore superblock           */
> +       struct rhashtable_iter hti;     /* rhashtable iterator         */
>         struct gfs2_glock *gl;          /* current glock struct        */
>         loff_t last_pos;                /* last position               */
>  };
> @@ -70,44 +75,20 @@ static DEFINE_SPINLOCK(lru_lock);
>
>  #define GFS2_GL_HASH_SHIFT      15
>  #define GFS2_GL_HASH_SIZE       (1 << GFS2_GL_HASH_SHIFT)
> -#define GFS2_GL_HASH_MASK       (GFS2_GL_HASH_SIZE - 1)
> -
> -static struct hlist_bl_head gl_hash_table[GFS2_GL_HASH_SIZE];
> -static struct dentry *gfs2_root;
> -
> -/**
> - * gl_hash() - Turn glock number into hash bucket number
> - * @lock: The glock number
> - *
> - * Returns: The number of the corresponding hash bucket
> - */
> -
> -static unsigned int gl_hash(const struct gfs2_sbd *sdp,
> -                           const struct lm_lockname *name)
> -{
> -       unsigned int h;
> -
> -       h = jhash(&name->ln_number, sizeof(u64), 0);
> -       h = jhash(&name->ln_type, sizeof(unsigned int), h);
> -       h = jhash(&sdp, sizeof(struct gfs2_sbd *), h);
> -       h &= GFS2_GL_HASH_MASK;
> -
> -       return h;
> -}
>
> -static inline void spin_lock_bucket(unsigned int hash)
> -{
> -       hlist_bl_lock(&gl_hash_table[hash]);
> -}
> +struct rhashtable_params ht_parms = {
> +       .nelem_hint = GFS2_GL_HASH_SIZE * 3 / 4,
> +       .key_len = sizeof(struct lm_lockname),
> +       .key_offset = offsetof(struct gfs2_glock, gl_name),
> +       .head_offset = offsetof(struct gfs2_glock, gl_node),
> +       .hashfn = jhash,
> +};
>
> -static inline void spin_unlock_bucket(unsigned int hash)
> -{
> -       hlist_bl_unlock(&gl_hash_table[hash]);
> -}
> +static struct rhashtable gl_hash_table;
>
> -static void gfs2_glock_dealloc(struct rcu_head *rcu)
> +void gfs2_glock_free(struct gfs2_glock *gl)
>  {
> -       struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
> +       struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
>
>         if (gl->gl_ops->go_flags & GLOF_ASPACE) {
>                 kmem_cache_free(gfs2_glock_aspace_cachep, gl);
> @@ -115,13 +96,6 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
>                 kfree(gl->gl_lksb.sb_lvbptr);
>                 kmem_cache_free(gfs2_glock_cachep, gl);
>         }
> -}
> -
> -void gfs2_glock_free(struct gfs2_glock *gl)
> -{
> -       struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
> -
> -       call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
>         if (atomic_dec_and_test(&sdp->sd_glock_disposal))
>                 wake_up(&sdp->sd_glock_wait);
>  }
> @@ -202,9 +176,8 @@ void gfs2_glock_put(struct gfs2_glock *gl)
>
>         gfs2_glock_remove_from_lru(gl);
>         spin_unlock(&gl->gl_lockref.lock);
> -       spin_lock_bucket(gl->gl_hash);
> -       hlist_bl_del_rcu(&gl->gl_list);
> -       spin_unlock_bucket(gl->gl_hash);
> +       if (gl->gl_node.next != NULL)
> +               rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms);
>         GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
>         GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
>         trace_gfs2_glock_put(gl);
> @@ -212,30 +185,6 @@ void gfs2_glock_put(struct gfs2_glock *gl)
>  }
>
>  /**
> - * search_bucket() - Find struct gfs2_glock by lock number
> - * @bucket: the bucket to search
> - * @name: The lock name
> - *
> - * Returns: NULL, or the struct gfs2_glock with the requested number
> - */
> -
> -static struct gfs2_glock *search_bucket(unsigned int hash,
> -                                       const struct lm_lockname *name)
> -{
> -       struct gfs2_glock *gl;
> -       struct hlist_bl_node *h;
> -
> -       hlist_bl_for_each_entry_rcu(gl, h, &gl_hash_table[hash], gl_list) {
> -               if (!lm_name_equal(&gl->gl_name, name))
> -                       continue;
> -               if (lockref_get_not_dead(&gl->gl_lockref))
> -                       return gl;
> -       }
> -
> -       return NULL;
> -}
> -
> -/**
>   * may_grant - check if its ok to grant a new lock
>   * @gl: The glock
>   * @gh: The lock request which we wish to grant
> @@ -704,14 +653,14 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>         struct lm_lockname name = { .ln_number = number,
>                                     .ln_type = glops->go_type,
>                                     .ln_sbd = sdp };
> -       struct gfs2_glock *gl, *tmp;
> -       unsigned int hash = gl_hash(sdp, &name);
> +       struct gfs2_glock *gl, *tmp = NULL;
>         struct address_space *mapping;
>         struct kmem_cache *cachep;
> +       int ret, tries = 0;
>
> -       rcu_read_lock();
> -       gl = search_bucket(hash, &name);
> -       rcu_read_unlock();
> +       gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
> +       if (gl && !lockref_get_not_dead(&gl->gl_lockref))
> +               gl = NULL;
>
>         *glp = gl;
>         if (gl)
> @@ -738,13 +687,13 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>         }
>
>         atomic_inc(&sdp->sd_glock_disposal);
> +       gl->gl_node.next = NULL;
>         gl->gl_flags = 0;
>         gl->gl_name = name;
>         gl->gl_lockref.count = 1;
>         gl->gl_state = LM_ST_UNLOCKED;
>         gl->gl_target = LM_ST_UNLOCKED;
>         gl->gl_demote_state = LM_ST_EXCLUSIVE;
> -       gl->gl_hash = hash;
>         gl->gl_ops = glops;
>         gl->gl_dstamp = ktime_set(0, 0);
>         preempt_disable();
> @@ -769,22 +718,34 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
>                 mapping->writeback_index = 0;
>         }
>
> -       spin_lock_bucket(hash);
> -       tmp = search_bucket(hash, &name);
> -       if (tmp) {
> -               spin_unlock_bucket(hash);
> -               kfree(gl->gl_lksb.sb_lvbptr);
> -               kmem_cache_free(cachep, gl);
> -               atomic_dec(&sdp->sd_glock_disposal);
> -               gl = tmp;
> -       } else {
> -               hlist_bl_add_head_rcu(&gl->gl_list, &gl_hash_table[hash]);
> -               spin_unlock_bucket(hash);
> +again:
> +       ret = rhashtable_lookup_insert_fast(&gl_hash_table, &gl->gl_node,
> +                                           ht_parms);
> +       if (ret == 0) {
> +               *glp = gl;
> +               return 0;
>         }
>
> -       *glp = gl;
> +       if (ret == -EEXIST) {
> +               ret = 0;
> +               tmp = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
> +               if (tmp == NULL || !lockref_get_not_dead(&tmp->gl_lockref)) {
> +                       if (++tries < 100) {
> +                               cond_resched();
> +                               goto again;
> +                       }
> +                       tmp = NULL;
> +                       ret = -ENOMEM;
> +               }
> +       } else {
> +               WARN_ON_ONCE(ret);
> +       }
> +       kfree(gl->gl_lksb.sb_lvbptr);
> +       kmem_cache_free(cachep, gl);
> +       atomic_dec(&sdp->sd_glock_disposal);
> +       *glp = tmp;
>
> -       return 0;
> +       return ret;
>  }
>
>  /**
> @@ -1460,31 +1421,24 @@ static struct shrinker glock_shrinker = {
>   *
>   */
>
> -static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
> -                         unsigned int hash)
> +static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
>  {
>         struct gfs2_glock *gl;
> -       struct hlist_bl_head *head = &gl_hash_table[hash];
> -       struct hlist_bl_node *pos;
> +       struct rhash_head *pos, *next;
> +       const struct bucket_table *tbl;
> +       int i;
>
> -       rcu_read_lock();
> -       hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
> -               if ((gl->gl_name.ln_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
> -                       examiner(gl);
> +       tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
> +       for (i = 0; i < tbl->size; i++) {
> +               rht_for_each_entry_safe(gl, pos, next, tbl, i, gl_node) {
> +                       if ((gl->gl_name.ln_sbd == sdp) &&
> +                           lockref_get_not_dead(&gl->gl_lockref))
> +                               examiner(gl);
> +               }
>         }
> -       rcu_read_unlock();
>         cond_resched();
>  }
>
> -static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
> -{
> -       unsigned x;
> -
> -       for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
> -               examine_bucket(examiner, sdp, x);
> -}
> -
> -
>  /**
>   * thaw_glock - thaw out a glock which has an unprocessed reply waiting
>   * @gl: The glock to thaw
> @@ -1802,20 +1756,24 @@ static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
>
>  int __init gfs2_glock_init(void)
>  {
> -       unsigned i;
> -       for(i = 0; i < GFS2_GL_HASH_SIZE; i++) {
> -               INIT_HLIST_BL_HEAD(&gl_hash_table[i]);
> -       }
> +       int ret;
> +
> +       ret = rhashtable_init(&gl_hash_table, &ht_parms);
> +       if (ret < 0)
> +               return ret;
>
>         glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
>                                           WQ_HIGHPRI | WQ_FREEZABLE, 0);
> -       if (!glock_workqueue)
> +       if (!glock_workqueue) {
> +               rhashtable_destroy(&gl_hash_table);
>                 return -ENOMEM;
> +       }
>         gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
>                                                 WQ_MEM_RECLAIM | WQ_FREEZABLE,
>                                                 0);
>         if (!gfs2_delete_workqueue) {
>                 destroy_workqueue(glock_workqueue);
> +               rhashtable_destroy(&gl_hash_table);
>                 return -ENOMEM;
>         }
>
> @@ -1827,72 +1785,36 @@ int __init gfs2_glock_init(void)
>  void gfs2_glock_exit(void)
>  {
>         unregister_shrinker(&glock_shrinker);
> +       rhashtable_destroy(&gl_hash_table);
>         destroy_workqueue(glock_workqueue);
>         destroy_workqueue(gfs2_delete_workqueue);
>  }
>
> -static inline struct gfs2_glock *glock_hash_chain(unsigned hash)
> +static void gfs2_glock_iter_next(struct gfs2_glock_rht_iter *gi)
>  {
> -       return hlist_bl_entry(hlist_bl_first_rcu(&gl_hash_table[hash]),
> -                             struct gfs2_glock, gl_list);
> -}
> -
> -static inline struct gfs2_glock *glock_hash_next(struct gfs2_glock *gl)
> -{
> -       return hlist_bl_entry(rcu_dereference(gl->gl_list.next),
> -                             struct gfs2_glock, gl_list);
> -}
> -
> -static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
> -{
> -       struct gfs2_glock *gl;
> -
>         do {
> -               gl = gi->gl;
> -               if (gl) {
> -                       gi->gl = glock_hash_next(gl);
> -                       gi->nhash++;
> -               } else {
> -                       if (gi->hash >= GFS2_GL_HASH_SIZE) {
> -                               rcu_read_unlock();
> -                               return 1;
> -                       }
> -                       gi->gl = glock_hash_chain(gi->hash);
> -                       gi->nhash = 0;
> -               }
> -               while (gi->gl == NULL) {
> -                       gi->hash++;
> -                       if (gi->hash >= GFS2_GL_HASH_SIZE) {
> -                               rcu_read_unlock();
> -                               return 1;
> -                       }
> -                       gi->gl = glock_hash_chain(gi->hash);
> -                       gi->nhash = 0;
> -               }
> +               gi->gl = rhashtable_walk_next(&gi->hti);
>         /* Skip entries for other sb and dead entries */
> -       } while (gi->sdp != gi->gl->gl_name.ln_sbd ||
> -                __lockref_is_dead(&gi->gl->gl_lockref));
> -
> -       return 0;
> +       } while ((gi->gl) && ((gi->sdp != gi->gl->gl_name.ln_sbd) ||
> +                             __lockref_is_dead(&gi->gl->gl_lockref)));
>  }
>
>  static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
>  {
> -       struct gfs2_glock_iter *gi = seq->private;
> +       struct gfs2_glock_rht_iter *gi = seq->private;
>         loff_t n = *pos;
> +       int ret;
>
>         if (gi->last_pos <= *pos)
> -               n = gi->nhash + (*pos - gi->last_pos);
> -       else
> -               gi->hash = 0;
> +               n = (*pos - gi->last_pos);
>
> -       gi->nhash = 0;
> -       rcu_read_lock();
> +       ret = rhashtable_walk_start(&gi->hti);
> +       if (ret)
> +               return NULL;
>
>         do {
> -               if (gfs2_glock_iter_next(gi))
> -                       return NULL;
> -       } while (n--);
> +               gfs2_glock_iter_next(gi);
> +       } while (gi->gl && n--);
>
>         gi->last_pos = *pos;
>         return gi->gl;
> @@ -1901,23 +1823,20 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
>  static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
>                                  loff_t *pos)
>  {
> -       struct gfs2_glock_iter *gi = seq->private;
> +       struct gfs2_glock_rht_iter *gi = seq->private;
>
>         (*pos)++;
>         gi->last_pos = *pos;
> -       if (gfs2_glock_iter_next(gi))
> -               return NULL;
> -
> +       gfs2_glock_iter_next(gi);
>         return gi->gl;
>  }
>
>  static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
>  {
> -       struct gfs2_glock_iter *gi = seq->private;
> +       struct gfs2_glock_rht_iter *gi = seq->private;
>
> -       if (gi->gl)
> -               rcu_read_unlock();
>         gi->gl = NULL;
> +       rhashtable_walk_stop(&gi->hti);
>  }
>
>  static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
> @@ -1981,29 +1900,46 @@ static const struct seq_operations gfs2_sbstats_seq_ops = {
>  static int gfs2_glocks_open(struct inode *inode, struct file *file)
>  {
>         int ret = seq_open_private(file, &gfs2_glock_seq_ops,
> -                                  sizeof(struct gfs2_glock_iter));
> +                                  sizeof(struct gfs2_glock_rht_iter));
>         if (ret == 0) {
>                 struct seq_file *seq = file->private_data;
> -               struct gfs2_glock_iter *gi = seq->private;
> +               struct gfs2_glock_rht_iter *gi = seq->private;
> +
>                 gi->sdp = inode->i_private;
> +               gi->last_pos = 0;
>                 seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
>                 if (seq->buf)
>                         seq->size = GFS2_SEQ_GOODSIZE;
> +               gi->gl = NULL;
> +               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
>         }
>         return ret;
>  }
>
> +static int gfs2_glocks_release(struct inode *inode, struct file *file)
> +{
> +       struct seq_file *seq = file->private_data;
> +       struct gfs2_glock_rht_iter *gi = seq->private;
> +
> +       gi->gl = NULL;
> +       rhashtable_walk_exit(&gi->hti);
> +       return seq_release_private(inode, file);
> +}
> +
>  static int gfs2_glstats_open(struct inode *inode, struct file *file)
>  {
>         int ret = seq_open_private(file, &gfs2_glstats_seq_ops,
> -                                  sizeof(struct gfs2_glock_iter));
> +                                  sizeof(struct gfs2_glock_rht_iter));
>         if (ret == 0) {
>                 struct seq_file *seq = file->private_data;
> -               struct gfs2_glock_iter *gi = seq->private;
> +               struct gfs2_glock_rht_iter *gi = seq->private;
>                 gi->sdp = inode->i_private;
> +               gi->last_pos = 0;
>                 seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
>                 if (seq->buf)
>                         seq->size = GFS2_SEQ_GOODSIZE;
> +               gi->gl = NULL;
> +               ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
>         }
>         return ret;
>  }
> @@ -2025,7 +1961,7 @@ static const struct file_operations gfs2_glocks_fops = {
>         .open    = gfs2_glocks_open,
>         .read    = seq_read,
>         .llseek  = seq_lseek,
> -       .release = seq_release_private,
> +       .release = gfs2_glocks_release,
>  };
>
>  static const struct file_operations gfs2_glstats_fops = {
> @@ -2033,7 +1969,7 @@ static const struct file_operations gfs2_glstats_fops = {
>         .open    = gfs2_glstats_open,
>         .read    = seq_read,
>         .llseek  = seq_lseek,
> -       .release = seq_release_private,
> +       .release = gfs2_glocks_release,
>  };
>
>  static const struct file_operations gfs2_sbstats_fops = {
> diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
> index 4de7853..0d63715 100644
> --- a/fs/gfs2/incore.h
> +++ b/fs/gfs2/incore.h
> @@ -22,6 +22,7 @@
>  #include <linux/ktime.h>
>  #include <linux/percpu.h>
>  #include <linux/lockref.h>
> +#include <linux/rhashtable.h>
>
>  #define DIO_WAIT       0x00000010
>  #define DIO_METADATA   0x00000020
> @@ -342,7 +343,6 @@ struct gfs2_glock {
>                      gl_req:2,          /* State in last dlm request */
>                      gl_reply:8;        /* Last reply from the dlm */
>
> -       unsigned int gl_hash;
>         unsigned long gl_demote_time; /* time of first demote request */
>         long gl_hold_time;
>         struct list_head gl_holders;
> @@ -368,7 +368,7 @@ struct gfs2_glock {
>                         loff_t end;
>                 } gl_vm;
>         };
> -       struct rcu_head gl_rcu;
> +       struct rhash_head gl_node;
>  };
>
>  #define GFS2_MIN_LVB_SIZE 32   /* Min size of LVB that gfs2 supports */
> --
> 2.1.0
>



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks Bob Peterson
  2015-07-13 11:19   ` Steven Whitehouse
  2015-08-24 13:16   ` Andreas Gruenbacher
@ 2015-08-24 13:31   ` Andreas Gruenbacher
  2015-08-24 13:46   ` Andreas Gruenbacher
  3 siblings, 0 replies; 14+ messages in thread
From: Andreas Gruenbacher @ 2015-08-24 13:31 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Bob,

[sorry for the empty previous reply ...]

2015-07-09 20:25 GMT+02:00 Bob Peterson <rpeterso@redhat.com>:
> @@ -1460,31 +1421,24 @@ static struct shrinker glock_shrinker = {
>   *
>   */
>
> -static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
> -                         unsigned int hash)
> +static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
>  {
>         struct gfs2_glock *gl;
> -       struct hlist_bl_head *head = &gl_hash_table[hash];
> -       struct hlist_bl_node *pos;
> +       struct rhash_head *pos, *next;
> +       const struct bucket_table *tbl;
> +       int i;
>
> -       rcu_read_lock();
> -       hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
> -               if ((gl->gl_name.ln_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
> -                       examiner(gl);
> +       tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
> +       for (i = 0; i < tbl->size; i++) {
> +               rht_for_each_entry_safe(gl, pos, next, tbl, i, gl_node) {
> +                       if ((gl->gl_name.ln_sbd == sdp) &&
> +                           lockref_get_not_dead(&gl->gl_lockref))
> +                               examiner(gl);
> +               }
>         }
> -       rcu_read_unlock();
>         cond_resched();
>  }
>
> -static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
> -{
> -       unsigned x;
> -
> -       for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
> -               examine_bucket(examiner, sdp, x);
> -}
> -
> -
>  /**
>   * thaw_glock - thaw out a glock which has an unprocessed reply waiting
>   * @gl: The glock to thaw

I don't think we can drop the rcu read lock in glock_hash_walk(): That
"lock" prevents a concurrent hash table resize from freeing the bucket
table under us.

Thanks,
Andreas



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks
  2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks Bob Peterson
                     ` (2 preceding siblings ...)
  2015-08-24 13:31   ` Andreas Gruenbacher
@ 2015-08-24 13:46   ` Andreas Gruenbacher
  2015-08-27 13:34     ` Bob Peterson
  3 siblings, 1 reply; 14+ messages in thread
From: Andreas Gruenbacher @ 2015-08-24 13:46 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Bob,

2015-07-09 20:25 GMT+02:00 Bob Peterson <rpeterso@redhat.com>:
> @@ -202,9 +176,8 @@ void gfs2_glock_put(struct gfs2_glock *gl)
>
>         gfs2_glock_remove_from_lru(gl);
>         spin_unlock(&gl->gl_lockref.lock);
> -       spin_lock_bucket(gl->gl_hash);
> -       hlist_bl_del_rcu(&gl->gl_list);
> -       spin_unlock_bucket(gl->gl_hash);
> +       if (gl->gl_node.next != NULL)
> +               rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms);
>         GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
>         GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
>         trace_gfs2_glock_put(gl);

what does the added if do?

Thanks,
Andreas



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 1/2][TRY #2] GFS2: Move glock superblock pointer to field gl_name
  2015-08-22 22:00         ` Andreas Gruenbacher
  2015-08-23 10:53           ` Steven Whitehouse
@ 2015-08-26 14:12           ` Bob Peterson
  1 sibling, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2015-08-26 14:12 UTC (permalink / raw)
  To: cluster-devel.redhat.com

----- Original Message -----
> Bob,
> 
> how hard would it be to move the rhashtable into struct gfs2_sbd instead?
> 
> Thanks,
> Andreas

Hi Andreas,

I've suggested moving the glock hash table into the superblock a couple times
in the past, when it was still a normal hash table, but I've always been shot
down. The advantage was improved scalability and not having to filter out
the glocks you don't want from the ones you don't when you go to do things
like dumping glocks. There's one central point for all glocks everywhere.
With rhashtable, scalability isn't much of an issue anymore. The disadvantage
is having multiple hash tables to manage when you are trying to clear things
out when you're unloading the module, for example. I've always felt the
advantages outweighed the disadvantages, but others did not agree.

Regards,

Bob Peterson
Red Hat File Systems



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks
  2015-08-24 13:46   ` Andreas Gruenbacher
@ 2015-08-27 13:34     ` Bob Peterson
  0 siblings, 0 replies; 14+ messages in thread
From: Bob Peterson @ 2015-08-27 13:34 UTC (permalink / raw)
  To: cluster-devel.redhat.com

----- Original Message -----
> Bob,
> 
> 2015-07-09 20:25 GMT+02:00 Bob Peterson <rpeterso@redhat.com>:
> > @@ -202,9 +176,8 @@ void gfs2_glock_put(struct gfs2_glock *gl)
> >
> >         gfs2_glock_remove_from_lru(gl);
> >         spin_unlock(&gl->gl_lockref.lock);
> > -       spin_lock_bucket(gl->gl_hash);
> > -       hlist_bl_del_rcu(&gl->gl_list);
> > -       spin_unlock_bucket(gl->gl_hash);
> > +       if (gl->gl_node.next != NULL)
> > +               rhashtable_remove_fast(&gl_hash_table, &gl->gl_node,
> > ht_parms);
> >         GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
> >         GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
> >         trace_gfs2_glock_put(gl);
> 
> what does the added if do?
 
I guess nothing. I'll remove it with another patch.

Bob Peterson
Red Hat File Systems



^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-08-27 13:34 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-09 18:25 [Cluster-devel] [GFS2 PATCH 0/2] Increase GFS2 glock scalability Bob Peterson
2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 1/2] GFS2: Move glock superblock pointer to field gl_name Bob Peterson
2015-07-13 11:19   ` Steven Whitehouse
2015-07-13 13:39     ` [Cluster-devel] [GFS2 PATCH 1/2][TRY #2] " Bob Peterson
2015-07-13 19:19       ` Steven Whitehouse
2015-08-22 22:00         ` Andreas Gruenbacher
2015-08-23 10:53           ` Steven Whitehouse
2015-08-26 14:12           ` Bob Peterson
2015-07-09 18:25 ` [Cluster-devel] [GFS2 PATCH 2/2] GFS2: Use resizable hash table for glocks Bob Peterson
2015-07-13 11:19   ` Steven Whitehouse
2015-08-24 13:16   ` Andreas Gruenbacher
2015-08-24 13:31   ` Andreas Gruenbacher
2015-08-24 13:46   ` Andreas Gruenbacher
2015-08-27 13:34     ` Bob Peterson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.