GFS2: merge window

Here is a list of patches we've accumulated for GFS2 for the current upstream
 merge window. This time we've only got six patches, many of which are very small:
 
 - Three cleanups from Andreas Gruenbacher, including a nice cleanup of
   the sequence file code for the sbstats debugfs file.
 - A patch from Ben Hutchings that changes statistics variables from signed
   to unsigned.
 - Two patches from me that increase GFS2's glock scalability by switching
   from a conventional hash table to rhashtable.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJV8XuJAAoJENeLYdPf93o73+UH/j+c5Iug/FaTGHTtHiTZjjcR
 GRYOHL1UqwM5xb3YwAi63JSgt0jvf+Oo4hf9LZ8wLEm69yCTo4kc8zMNnqDd5Evc
 Zx4jJT5XUBtpjPhCAQyJuE6TCjAqm/fsnZmDqUWiwByDkaUnW7cKB20KrIERbYiL
 qBV5F42XSpXnNSWeMs8Sg2vYiCS9omI/ZenoIsL4YQAtKdPlX1Ce4Apv8EO2c09i
 HzNseOQierZE6ghCKRELusqqGzgK3GyqWjOWa8ZGLsD9dRyPLK7FNO7HBIBwV2Wb
 G6KKnVCDSCRM1zXMc5+YplvzEsHN1dT+rqroxRrYlVHJ3hcHBqNis0X4pjxwHEo=
 =idxz
 -----END PGP SIGNATURE-----

Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2

Pull GFS2 updates from Bob Peterson:
 "Here is a list of patches we've accumulated for GFS2 for the current
  upstream merge window.  This time we've only got six patches, many of
  which are very small:

   - three cleanups from Andreas Gruenbacher, including a nice cleanup
     of the sequence file code for the sbstats debugfs file.

   - a patch from Ben Hutchings that changes statistics variables from
     signed to unsigned.

   - two patches from me that increase GFS2's glock scalability by
     switching from a conventional hash table to rhashtable"

* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: A minor "sbstats" cleanup
  gfs2: Fix a typo in a comment
  gfs2: Make statistics unsigned, suitable for use with do_div()
  GFS2: Use resizable hash table for glocks
  GFS2: Move glock superblock pointer to field gl_name
  gfs2: Simplify the seq file code for "sbstats"
This commit is contained in:
Linus Torvalds 2015-09-11 12:23:51 -07:00
commit 01cab5549c
11 changed files with 212 additions and 285 deletions

View File

@ -34,6 +34,7 @@
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/list_sort.h> #include <linux/list_sort.h>
#include <linux/lockref.h> #include <linux/lockref.h>
#include <linux/rhashtable.h>
#include "gfs2.h" #include "gfs2.h"
#include "incore.h" #include "incore.h"
@ -50,9 +51,8 @@
#include "trace_gfs2.h" #include "trace_gfs2.h"
struct gfs2_glock_iter { struct gfs2_glock_iter {
int hash; /* hash bucket index */
unsigned nhash; /* Index within current bucket */
struct gfs2_sbd *sdp; /* incore superblock */ struct gfs2_sbd *sdp; /* incore superblock */
struct rhashtable_iter hti; /* rhashtable iterator */
struct gfs2_glock *gl; /* current glock struct */ struct gfs2_glock *gl; /* current glock struct */
loff_t last_pos; /* last position */ loff_t last_pos; /* last position */
}; };
@ -70,44 +70,19 @@ static DEFINE_SPINLOCK(lru_lock);
#define GFS2_GL_HASH_SHIFT 15 #define GFS2_GL_HASH_SHIFT 15
#define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) #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 rhashtable_params ht_parms = {
static struct dentry *gfs2_root; .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),
};
/** static struct rhashtable gl_hash_table;
* 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, void gfs2_glock_free(struct gfs2_glock *gl)
const struct lm_lockname *name)
{ {
unsigned int h; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
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]);
}
static inline void spin_unlock_bucket(unsigned int hash)
{
hlist_bl_unlock(&gl_hash_table[hash]);
}
static void gfs2_glock_dealloc(struct rcu_head *rcu)
{
struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
if (gl->gl_ops->go_flags & GLOF_ASPACE) { if (gl->gl_ops->go_flags & GLOF_ASPACE) {
kmem_cache_free(gfs2_glock_aspace_cachep, gl); kmem_cache_free(gfs2_glock_aspace_cachep, gl);
@ -115,13 +90,6 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
kfree(gl->gl_lksb.sb_lvbptr); kfree(gl->gl_lksb.sb_lvbptr);
kmem_cache_free(gfs2_glock_cachep, gl); kmem_cache_free(gfs2_glock_cachep, gl);
} }
}
void gfs2_glock_free(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
if (atomic_dec_and_test(&sdp->sd_glock_disposal)) if (atomic_dec_and_test(&sdp->sd_glock_disposal))
wake_up(&sdp->sd_glock_wait); wake_up(&sdp->sd_glock_wait);
} }
@ -192,7 +160,7 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
void gfs2_glock_put(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); struct address_space *mapping = gfs2_glock2aspace(gl);
if (lockref_put_or_lock(&gl->gl_lockref)) if (lockref_put_or_lock(&gl->gl_lockref))
@ -202,42 +170,13 @@ void gfs2_glock_put(struct gfs2_glock *gl)
gfs2_glock_remove_from_lru(gl); gfs2_glock_remove_from_lru(gl);
spin_unlock(&gl->gl_lockref.lock); spin_unlock(&gl->gl_lockref.lock);
spin_lock_bucket(gl->gl_hash); rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms);
hlist_bl_del_rcu(&gl->gl_list);
spin_unlock_bucket(gl->gl_hash);
GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders)); GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
GLOCK_BUG_ON(gl, mapping && mapping->nrpages); GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
trace_gfs2_glock_put(gl); trace_gfs2_glock_put(gl);
sdp->sd_lockstruct.ls_ops->lm_put_lock(gl); sdp->sd_lockstruct.ls_ops->lm_put_lock(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 gfs2_sbd *sdp,
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 (gl->gl_sbd != sdp)
continue;
if (lockref_get_not_dead(&gl->gl_lockref))
return gl;
}
return NULL;
}
/** /**
* may_grant - check if its ok to grant a new lock * may_grant - check if its ok to grant a new lock
* @gl: The glock * @gl: The glock
@ -506,7 +445,7 @@ __releases(&gl->gl_spin)
__acquires(&gl->gl_spin) __acquires(&gl->gl_spin)
{ {
const struct gfs2_glock_operations *glops = gl->gl_ops; 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; unsigned int lck_flags = gh ? gh->gh_flags : 0;
int ret; int ret;
@ -628,7 +567,7 @@ out_unlock:
static void delete_work_func(struct work_struct *work) static void delete_work_func(struct work_struct *work)
{ {
struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete); 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 gfs2_inode *ip;
struct inode *inode; struct inode *inode;
u64 no_addr = gl->gl_name.ln_number; u64 no_addr = gl->gl_name.ln_number;
@ -704,15 +643,17 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
struct gfs2_glock **glp) struct gfs2_glock **glp)
{ {
struct super_block *s = sdp->sd_vfs; 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,
struct gfs2_glock *gl, *tmp; .ln_type = glops->go_type,
unsigned int hash = gl_hash(sdp, &name); .ln_sbd = sdp };
struct gfs2_glock *gl, *tmp = NULL;
struct address_space *mapping; struct address_space *mapping;
struct kmem_cache *cachep; struct kmem_cache *cachep;
int ret, tries = 0;
rcu_read_lock(); gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
gl = search_bucket(hash, sdp, &name); if (gl && !lockref_get_not_dead(&gl->gl_lockref))
rcu_read_unlock(); gl = NULL;
*glp = gl; *glp = gl;
if (gl) if (gl)
@ -739,14 +680,13 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
} }
atomic_inc(&sdp->sd_glock_disposal); atomic_inc(&sdp->sd_glock_disposal);
gl->gl_sbd = sdp; gl->gl_node.next = NULL;
gl->gl_flags = 0; gl->gl_flags = 0;
gl->gl_name = name; gl->gl_name = name;
gl->gl_lockref.count = 1; gl->gl_lockref.count = 1;
gl->gl_state = LM_ST_UNLOCKED; gl->gl_state = LM_ST_UNLOCKED;
gl->gl_target = LM_ST_UNLOCKED; gl->gl_target = LM_ST_UNLOCKED;
gl->gl_demote_state = LM_ST_EXCLUSIVE; gl->gl_demote_state = LM_ST_EXCLUSIVE;
gl->gl_hash = hash;
gl->gl_ops = glops; gl->gl_ops = glops;
gl->gl_dstamp = ktime_set(0, 0); gl->gl_dstamp = ktime_set(0, 0);
preempt_disable(); preempt_disable();
@ -771,22 +711,34 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
mapping->writeback_index = 0; mapping->writeback_index = 0;
} }
spin_lock_bucket(hash); again:
tmp = search_bucket(hash, sdp, &name); ret = rhashtable_lookup_insert_fast(&gl_hash_table, &gl->gl_node,
if (tmp) { ht_parms);
spin_unlock_bucket(hash); if (ret == 0) {
kfree(gl->gl_lksb.sb_lvbptr); *glp = gl;
kmem_cache_free(cachep, gl); return 0;
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);
} }
*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;
} }
/** /**
@ -928,7 +880,7 @@ __releases(&gl->gl_spin)
__acquires(&gl->gl_spin) __acquires(&gl->gl_spin)
{ {
struct gfs2_glock *gl = gh->gh_gl; 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 list_head *insert_pt = NULL;
struct gfs2_holder *gh2; struct gfs2_holder *gh2;
int try_futile = 0; int try_futile = 0;
@ -1006,7 +958,7 @@ trap_recursive:
int gfs2_glock_nq(struct gfs2_holder *gh) int gfs2_glock_nq(struct gfs2_holder *gh)
{ {
struct gfs2_glock *gl = gh->gh_gl; 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; int error = 0;
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
@ -1313,7 +1265,7 @@ static int gfs2_should_freeze(const struct gfs2_glock *gl)
void gfs2_glock_complete(struct gfs2_glock *gl, int ret) 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); spin_lock(&gl->gl_spin);
gl->gl_reply = ret; gl->gl_reply = ret;
@ -1462,31 +1414,26 @@ static struct shrinker glock_shrinker = {
* *
*/ */
static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp, static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
unsigned int hash)
{ {
struct gfs2_glock *gl; struct gfs2_glock *gl;
struct hlist_bl_head *head = &gl_hash_table[hash]; struct rhash_head *pos, *next;
struct hlist_bl_node *pos; const struct bucket_table *tbl;
int i;
rcu_read_lock(); rcu_read_lock();
hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) { tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
if ((gl->gl_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref)) for (i = 0; i < tbl->size; i++) {
examiner(gl); 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(); rcu_read_unlock();
cond_resched(); 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 * thaw_glock - thaw out a glock which has an unprocessed reply waiting
* @gl: The glock to thaw * @gl: The glock to thaw
@ -1569,7 +1516,7 @@ void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
int ret; int ret;
ret = gfs2_truncatei_resume(ip); 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); spin_lock(&gl->gl_spin);
clear_bit(GLF_LOCK, &gl->gl_flags); clear_bit(GLF_LOCK, &gl->gl_flags);
@ -1733,17 +1680,17 @@ static int gfs2_glstats_seq_show(struct seq_file *seq, void *iter_ptr)
{ {
struct gfs2_glock *gl = iter_ptr; struct gfs2_glock *gl = iter_ptr;
seq_printf(seq, "G: n:%u/%llx rtt:%lld/%lld rttb:%lld/%lld irt:%lld/%lld dcnt: %lld qcnt: %lld\n", seq_printf(seq, "G: n:%u/%llx rtt:%llu/%llu rttb:%llu/%llu irt:%llu/%llu dcnt: %llu qcnt: %llu\n",
gl->gl_name.ln_type, gl->gl_name.ln_type,
(unsigned long long)gl->gl_name.ln_number, (unsigned long long)gl->gl_name.ln_number,
(long long)gl->gl_stats.stats[GFS2_LKS_SRTT], (unsigned long long)gl->gl_stats.stats[GFS2_LKS_SRTT],
(long long)gl->gl_stats.stats[GFS2_LKS_SRTTVAR], (unsigned long long)gl->gl_stats.stats[GFS2_LKS_SRTTVAR],
(long long)gl->gl_stats.stats[GFS2_LKS_SRTTB], (unsigned long long)gl->gl_stats.stats[GFS2_LKS_SRTTB],
(long long)gl->gl_stats.stats[GFS2_LKS_SRTTVARB], (unsigned long long)gl->gl_stats.stats[GFS2_LKS_SRTTVARB],
(long long)gl->gl_stats.stats[GFS2_LKS_SIRT], (unsigned long long)gl->gl_stats.stats[GFS2_LKS_SIRT],
(long long)gl->gl_stats.stats[GFS2_LKS_SIRTVAR], (unsigned long long)gl->gl_stats.stats[GFS2_LKS_SIRTVAR],
(long long)gl->gl_stats.stats[GFS2_LKS_DCOUNT], (unsigned long long)gl->gl_stats.stats[GFS2_LKS_DCOUNT],
(long long)gl->gl_stats.stats[GFS2_LKS_QCOUNT]); (unsigned long long)gl->gl_stats.stats[GFS2_LKS_QCOUNT]);
return 0; return 0;
} }
@ -1776,11 +1723,10 @@ static const char *gfs2_stype[] = {
static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr) static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
{ {
struct gfs2_glock_iter *gi = seq->private; struct gfs2_sbd *sdp = seq->private;
struct gfs2_sbd *sdp = gi->sdp; loff_t pos = *(loff_t *)iter_ptr;
unsigned index = gi->hash >> 3; unsigned index = pos >> 3;
unsigned subindex = gi->hash & 0x07; unsigned subindex = pos & 0x07;
s64 value;
int i; int i;
if (index == 0 && subindex != 0) if (index == 0 && subindex != 0)
@ -1791,12 +1737,12 @@ static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
const struct gfs2_pcpu_lkstats *lkstats = per_cpu_ptr(sdp->sd_lkstats, i); const struct gfs2_pcpu_lkstats *lkstats = per_cpu_ptr(sdp->sd_lkstats, i);
if (index == 0) {
value = i; if (index == 0)
} else { seq_printf(seq, " %15u", i);
value = lkstats->lkstats[index - 1].stats[subindex]; else
} seq_printf(seq, " %15llu", (unsigned long long)lkstats->
seq_printf(seq, " %15lld", (long long)value); lkstats[index - 1].stats[subindex]);
} }
seq_putc(seq, '\n'); seq_putc(seq, '\n');
return 0; return 0;
@ -1804,20 +1750,24 @@ static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
int __init gfs2_glock_init(void) int __init gfs2_glock_init(void)
{ {
unsigned i; int ret;
for(i = 0; i < GFS2_GL_HASH_SIZE; i++) {
INIT_HLIST_BL_HEAD(&gl_hash_table[i]); ret = rhashtable_init(&gl_hash_table, &ht_parms);
} if (ret < 0)
return ret;
glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM | glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
WQ_HIGHPRI | WQ_FREEZABLE, 0); WQ_HIGHPRI | WQ_FREEZABLE, 0);
if (!glock_workqueue) if (!glock_workqueue) {
rhashtable_destroy(&gl_hash_table);
return -ENOMEM; return -ENOMEM;
}
gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
WQ_MEM_RECLAIM | WQ_FREEZABLE, WQ_MEM_RECLAIM | WQ_FREEZABLE,
0); 0);
if (!gfs2_delete_workqueue) { if (!gfs2_delete_workqueue) {
destroy_workqueue(glock_workqueue); destroy_workqueue(glock_workqueue);
rhashtable_destroy(&gl_hash_table);
return -ENOMEM; return -ENOMEM;
} }
@ -1829,72 +1779,41 @@ int __init gfs2_glock_init(void)
void gfs2_glock_exit(void) void gfs2_glock_exit(void)
{ {
unregister_shrinker(&glock_shrinker); unregister_shrinker(&glock_shrinker);
rhashtable_destroy(&gl_hash_table);
destroy_workqueue(glock_workqueue); destroy_workqueue(glock_workqueue);
destroy_workqueue(gfs2_delete_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_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 { do {
gl = gi->gl; gi->gl = rhashtable_walk_next(&gi->hti);
if (gl) { if (IS_ERR(gi->gl)) {
gi->gl = glock_hash_next(gl); if (PTR_ERR(gi->gl) == -EAGAIN)
gi->nhash++; continue;
} else { gi->gl = NULL;
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;
} }
/* Skip entries for other sb and dead entries */ /* Skip entries for other sb and dead entries */
} while (gi->sdp != gi->gl->gl_sbd || } while ((gi->gl) && ((gi->sdp != gi->gl->gl_name.ln_sbd) ||
__lockref_is_dead(&gi->gl->gl_lockref)); __lockref_is_dead(&gi->gl->gl_lockref)));
return 0;
} }
static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
{ {
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
loff_t n = *pos; loff_t n = *pos;
int ret;
if (gi->last_pos <= *pos) if (gi->last_pos <= *pos)
n = gi->nhash + (*pos - gi->last_pos); n = (*pos - gi->last_pos);
else
gi->hash = 0;
gi->nhash = 0; ret = rhashtable_walk_start(&gi->hti);
rcu_read_lock(); if (ret)
return NULL;
do { do {
if (gfs2_glock_iter_next(gi)) gfs2_glock_iter_next(gi);
return NULL; } while (gi->gl && n--);
} while (n--);
gi->last_pos = *pos; gi->last_pos = *pos;
return gi->gl; return gi->gl;
@ -1907,9 +1826,7 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
(*pos)++; (*pos)++;
gi->last_pos = *pos; gi->last_pos = *pos;
if (gfs2_glock_iter_next(gi)) gfs2_glock_iter_next(gi);
return NULL;
return gi->gl; return gi->gl;
} }
@ -1917,9 +1834,8 @@ static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
{ {
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
if (gi->gl)
rcu_read_unlock();
gi->gl = NULL; gi->gl = NULL;
rhashtable_walk_stop(&gi->hti);
} }
static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr) static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
@ -1930,26 +1846,19 @@ static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
static void *gfs2_sbstats_seq_start(struct seq_file *seq, loff_t *pos) static void *gfs2_sbstats_seq_start(struct seq_file *seq, loff_t *pos)
{ {
struct gfs2_glock_iter *gi = seq->private; preempt_disable();
gi->hash = *pos;
if (*pos >= GFS2_NR_SBSTATS) if (*pos >= GFS2_NR_SBSTATS)
return NULL; return NULL;
preempt_disable(); return pos;
return SEQ_START_TOKEN;
} }
static void *gfs2_sbstats_seq_next(struct seq_file *seq, void *iter_ptr, static void *gfs2_sbstats_seq_next(struct seq_file *seq, void *iter_ptr,
loff_t *pos) loff_t *pos)
{ {
struct gfs2_glock_iter *gi = seq->private;
(*pos)++; (*pos)++;
gi->hash++; if (*pos >= GFS2_NR_SBSTATS)
if (gi->hash >= GFS2_NR_SBSTATS) {
preempt_enable();
return NULL; return NULL;
} return pos;
return SEQ_START_TOKEN;
} }
static void gfs2_sbstats_seq_stop(struct seq_file *seq, void *iter_ptr) static void gfs2_sbstats_seq_stop(struct seq_file *seq, void *iter_ptr)
@ -1987,14 +1896,28 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file)
if (ret == 0) { if (ret == 0) {
struct seq_file *seq = file->private_data; struct seq_file *seq = file->private_data;
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
gi->sdp = inode->i_private; gi->sdp = inode->i_private;
gi->last_pos = 0;
seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN); seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
if (seq->buf) if (seq->buf)
seq->size = GFS2_SEQ_GOODSIZE; seq->size = GFS2_SEQ_GOODSIZE;
gi->gl = NULL;
ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
} }
return ret; return ret;
} }
static int gfs2_glocks_release(struct inode *inode, struct file *file)
{
struct seq_file *seq = file->private_data;
struct gfs2_glock_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) static int gfs2_glstats_open(struct inode *inode, struct file *file)
{ {
int ret = seq_open_private(file, &gfs2_glstats_seq_ops, int ret = seq_open_private(file, &gfs2_glstats_seq_ops,
@ -2003,21 +1926,22 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file)
struct seq_file *seq = file->private_data; struct seq_file *seq = file->private_data;
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
gi->sdp = inode->i_private; gi->sdp = inode->i_private;
gi->last_pos = 0;
seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN); seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
if (seq->buf) if (seq->buf)
seq->size = GFS2_SEQ_GOODSIZE; seq->size = GFS2_SEQ_GOODSIZE;
gi->gl = NULL;
ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
} }
return ret; return ret;
} }
static int gfs2_sbstats_open(struct inode *inode, struct file *file) static int gfs2_sbstats_open(struct inode *inode, struct file *file)
{ {
int ret = seq_open_private(file, &gfs2_sbstats_seq_ops, int ret = seq_open(file, &gfs2_sbstats_seq_ops);
sizeof(struct gfs2_glock_iter));
if (ret == 0) { if (ret == 0) {
struct seq_file *seq = file->private_data; struct seq_file *seq = file->private_data;
struct gfs2_glock_iter *gi = seq->private; seq->private = inode->i_private; /* sdp */
gi->sdp = inode->i_private;
} }
return ret; return ret;
} }
@ -2027,7 +1951,7 @@ static const struct file_operations gfs2_glocks_fops = {
.open = gfs2_glocks_open, .open = gfs2_glocks_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release_private, .release = gfs2_glocks_release,
}; };
static const struct file_operations gfs2_glstats_fops = { static const struct file_operations gfs2_glstats_fops = {
@ -2035,7 +1959,7 @@ static const struct file_operations gfs2_glstats_fops = {
.open = gfs2_glstats_open, .open = gfs2_glstats_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release_private, .release = gfs2_glocks_release,
}; };
static const struct file_operations gfs2_sbstats_fops = { static const struct file_operations gfs2_sbstats_fops = {
@ -2043,7 +1967,7 @@ static const struct file_operations gfs2_sbstats_fops = {
.open = gfs2_sbstats_open, .open = gfs2_sbstats_open,
.read = seq_read, .read = seq_read,
.llseek = seq_lseek, .llseek = seq_lseek,
.release = seq_release_private, .release = seq_release,
}; };
int gfs2_create_debugfs_file(struct gfs2_sbd *sdp) int gfs2_create_debugfs_file(struct gfs2_sbd *sdp)

View File

@ -32,13 +32,15 @@ struct workqueue_struct *gfs2_freeze_wq;
static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) 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, (unsigned long long)bh->b_blocknr, bh->b_state,
bh->b_page->mapping, bh->b_page->flags); 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, gl->gl_name.ln_type, gl->gl_name.ln_number,
gfs2_glock2aspace(gl)); 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, static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
unsigned int nr_revokes) 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 list_head *head = &gl->gl_ail_list;
struct gfs2_bufdata *bd, *tmp; struct gfs2_bufdata *bd, *tmp;
struct buffer_head *bh; 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) 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; struct gfs2_trans tr;
memset(&tr, 0, sizeof(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) 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 revokes = atomic_read(&gl->gl_ail_count);
unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64); unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
int ret; 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) 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 address_space *mapping = &sdp->sd_aspace;
struct gfs2_rgrpd *rgd; struct gfs2_rgrpd *rgd;
int error; 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) 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 address_space *mapping = &sdp->sd_aspace;
struct gfs2_rgrpd *rgd = gl->gl_object; 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); 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); filemap_fdatawrite(metamapping);
if (ip) { if (ip) {
struct address_space *mapping = ip->i_inode.i_mapping; 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; 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) { if (flags & DIO_METADATA) {
struct address_space *mapping = gfs2_glock2aspace(gl); 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)) { if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
gfs2_log_flush(gl->gl_sbd, NULL, NORMAL_FLUSH); gfs2_log_flush(gl->gl_name.ln_sbd, NULL, NORMAL_FLUSH);
gl->gl_sbd->sd_rindex_uptodate = 0; gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
} }
if (ip && S_ISREG(ip->i_inode.i_mode)) if (ip && S_ISREG(ip->i_inode.i_mode))
truncate_inode_pages(ip->i_inode.i_mapping, 0); 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) 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; struct gfs2_holder *gh;
if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object) 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) static int inode_go_lock(struct gfs2_holder *gh)
{ {
struct gfs2_glock *gl = gh->gh_gl; 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; struct gfs2_inode *ip = gl->gl_object;
int error = 0; 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) static void freeze_go_sync(struct gfs2_glock *gl)
{ {
int error = 0; 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 && if (gl->gl_state == LM_ST_SHARED &&
test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { 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) 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_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
struct gfs2_glock *j_gl = ip->i_gl; struct gfs2_glock *j_gl = ip->i_gl;
struct gfs2_log_header_host head; 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) static void iopen_go_callback(struct gfs2_glock *gl, bool remote)
{ {
struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; 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)) if (!remote || (sdp->sd_vfs->s_flags & MS_RDONLY))
return; return;

View File

@ -22,6 +22,7 @@
#include <linux/ktime.h> #include <linux/ktime.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/lockref.h> #include <linux/lockref.h>
#include <linux/rhashtable.h>
#define DIO_WAIT 0x00000010 #define DIO_WAIT 0x00000010
#define DIO_METADATA 0x00000020 #define DIO_METADATA 0x00000020
@ -203,13 +204,15 @@ enum {
}; };
struct lm_lockname { struct lm_lockname {
struct gfs2_sbd *ln_sbd;
u64 ln_number; u64 ln_number;
unsigned int ln_type; unsigned int ln_type;
}; };
#define lm_name_equal(name1, name2) \ #define lm_name_equal(name1, name2) \
(((name1)->ln_number == (name2)->ln_number) && \ (((name1)->ln_number == (name2)->ln_number) && \
((name1)->ln_type == (name2)->ln_type)) ((name1)->ln_type == (name2)->ln_type) && \
((name1)->ln_sbd == (name2)->ln_sbd))
struct gfs2_glock_operations { struct gfs2_glock_operations {
@ -241,7 +244,7 @@ enum {
}; };
struct gfs2_lkstats { struct gfs2_lkstats {
s64 stats[GFS2_NR_LKSTATS]; u64 stats[GFS2_NR_LKSTATS];
}; };
enum { enum {
@ -327,7 +330,6 @@ enum {
struct gfs2_glock { struct gfs2_glock {
struct hlist_bl_node gl_list; struct hlist_bl_node gl_list;
struct gfs2_sbd *gl_sbd;
unsigned long gl_flags; /* GLF_... */ unsigned long gl_flags; /* GLF_... */
struct lm_lockname gl_name; struct lm_lockname gl_name;
@ -341,7 +343,6 @@ struct gfs2_glock {
gl_req:2, /* State in last dlm request */ gl_req:2, /* State in last dlm request */
gl_reply:8; /* Last reply from the dlm */ gl_reply:8; /* Last reply from the dlm */
unsigned int gl_hash;
unsigned long gl_demote_time; /* time of first demote request */ unsigned long gl_demote_time; /* time of first demote request */
long gl_hold_time; long gl_hold_time;
struct list_head gl_holders; struct list_head gl_holders;
@ -367,7 +368,7 @@ struct gfs2_glock {
loff_t end; loff_t end;
} gl_vm; } 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 */ #define GFS2_MIN_LVB_SIZE 32 /* Min size of LVB that gfs2 supports */
@ -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) 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(); preempt_disable();
this_cpu_ptr(sdp->sd_lkstats)->lkstats[gl->gl_name.ln_type].stats[which]++; this_cpu_ptr(sdp->sd_lkstats)->lkstats[gl->gl_name.ln_type].stats[which]++;
preempt_enable(); preempt_enable();

View File

@ -31,7 +31,7 @@ extern struct workqueue_struct *gfs2_control_wq;
* *
* @delta is the difference between the current rtt sample and the * @delta is the difference between the current rtt sample and the
* running average srtt. We add 1/8 of that to the srtt in order to * running average srtt. We add 1/8 of that to the srtt in order to
* update the current srtt estimate. The varience estimate is a bit * update the current srtt estimate. The variance estimate is a bit
* more complicated. We subtract the abs value of the @delta from * more complicated. We subtract the abs value of the @delta from
* the current variance estimate and add 1/4 of that to the running * the current variance estimate and add 1/4 of that to the running
* total. * total.
@ -80,7 +80,7 @@ static inline void gfs2_update_reply_times(struct gfs2_glock *gl)
preempt_disable(); preempt_disable();
rtt = ktime_to_ns(ktime_sub(ktime_get_real(), gl->gl_dstamp)); 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(&gl->gl_stats, index, rtt); /* Local */
gfs2_update_stats(&lks->lkstats[gltype], index, rtt); /* Global */ gfs2_update_stats(&lks->lkstats[gltype], index, rtt); /* Global */
preempt_enable(); preempt_enable();
@ -108,7 +108,7 @@ static inline void gfs2_update_request_times(struct gfs2_glock *gl)
dstamp = gl->gl_dstamp; dstamp = gl->gl_dstamp;
gl->gl_dstamp = ktime_get_real(); gl->gl_dstamp = ktime_get_real();
irt = ktime_to_ns(ktime_sub(gl->gl_dstamp, dstamp)); 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(&gl->gl_stats, GFS2_LKS_SIRT, irt); /* Local */
gfs2_update_stats(&lks->lkstats[gltype], GFS2_LKS_SIRT, irt); /* Global */ gfs2_update_stats(&lks->lkstats[gltype], GFS2_LKS_SIRT, irt); /* Global */
preempt_enable(); 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, static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
unsigned int flags) 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; int req;
u32 lkf; u32 lkf;
char strname[GDLM_STRNAME_BYTES] = ""; 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) 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; struct lm_lockstruct *ls = &sdp->sd_lockstruct;
int lvb_needs_unlock = 0; int lvb_needs_unlock = 0;
int error; int error;
@ -319,7 +319,7 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
static void gdlm_cancel(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); dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
} }

View File

@ -70,7 +70,7 @@ static bool buffer_is_rgrp(const struct gfs2_bufdata *bd)
static void maybe_release_space(struct gfs2_bufdata *bd) static void maybe_release_space(struct gfs2_bufdata *bd)
{ {
struct gfs2_glock *gl = bd->bd_gl; 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; struct gfs2_rgrpd *rgd = gl->gl_object;
unsigned int index = bd->bd_bh->b_blocknr - gl->gl_name.ln_number; unsigned int index = bd->bd_bh->b_blocknr - gl->gl_name.ln_number;
struct gfs2_bitmap *bi = rgd->rd_bits + index; struct gfs2_bitmap *bi = rgd->rd_bits + index;
@ -578,7 +578,7 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
static void gfs2_meta_sync(struct gfs2_glock *gl) static void gfs2_meta_sync(struct gfs2_glock *gl)
{ {
struct address_space *mapping = gfs2_glock2aspace(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; int error;
if (mapping == NULL) if (mapping == NULL)
@ -588,7 +588,7 @@ static void gfs2_meta_sync(struct gfs2_glock *gl)
error = filemap_fdatawait(mapping); error = filemap_fdatawait(mapping);
if (error) 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) static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)

View File

@ -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 buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
{ {
struct address_space *mapping = gfs2_glock2aspace(gl); 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 page *page;
struct buffer_head *bh; struct buffer_head *bh;
unsigned int shift; 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, int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
struct buffer_head **bhp) struct buffer_head **bhp)
{ {
struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct buffer_head *bh; struct buffer_head *bh;
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) { 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 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; struct buffer_head *first_bh, *bh;
u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >> u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >>
sdp->sd_sb.sb_bsize_shift; sdp->sd_sb.sb_bsize_shift;

View File

@ -44,7 +44,7 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
{ {
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
if (mapping->a_ops == &gfs2_meta_aops) 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) else if (mapping->a_ops == &gfs2_rgrp_aops)
return container_of(mapping, struct gfs2_sbd, sd_aspace); return container_of(mapping, struct gfs2_sbd, sd_aspace);
else else

View File

@ -119,7 +119,7 @@ static void gfs2_qd_dispose(struct list_head *list)
while (!list_empty(list)) { while (!list_empty(list)) {
qd = list_entry(list->next, struct gfs2_quota_data, qd_lru); 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); 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) 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)); gfs2_assert(sdp, !__lockref_is_dead(&qd->qd_lockref));
lockref_get(&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) 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); struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
unsigned int block, offset; unsigned int block, offset;
struct buffer_head *bh; struct buffer_head *bh;
@ -414,7 +414,7 @@ fail:
static void bh_put(struct gfs2_quota_data *qd) 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); mutex_lock(&sdp->sd_quota_mutex);
gfs2_assert(sdp, qd->qd_bh_count); 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) 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)); test_bit(QDF_LOCKED, &qd->qd_flags));
clear_bit(QDF_LOCKED, &qd->qd_flags); clear_bit(QDF_LOCKED, &qd->qd_flags);
bh_put(qd); 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) 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_inode *ip = GFS2_I(sdp->sd_qc_inode);
struct gfs2_quota_change *qc = qd->qd_bh_qc; struct gfs2_quota_change *qc = qd->qd_bh_qc;
s64 x; 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) 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_inode *ip = GFS2_I(sdp->sd_quota_inode);
struct gfs2_alloc_parms ap = { .aflags = 0, }; struct gfs2_alloc_parms ap = { .aflags = 0, };
unsigned int data_blocks, ind_blocks; unsigned int data_blocks, ind_blocks;
@ -922,7 +922,7 @@ out:
gfs2_glock_dq_uninit(&ghs[qx]); gfs2_glock_dq_uninit(&ghs[qx]);
mutex_unlock(&ip->i_inode.i_mutex); mutex_unlock(&ip->i_inode.i_mutex);
kfree(ghs); 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; 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, static int do_glock(struct gfs2_quota_data *qd, int force_refresh,
struct gfs2_holder *q_gh) 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_inode *ip = GFS2_I(sdp->sd_quota_inode);
struct gfs2_holder i_gh; struct gfs2_holder i_gh;
int error; 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) 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; struct gfs2_tune *gt = &sdp->sd_tune;
s64 value; s64 value;
unsigned int num, den; unsigned int num, den;
@ -1125,7 +1125,7 @@ out:
static int print_message(struct gfs2_quota_data *qd, char *type) 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", fs_info(sdp, "quota %s for %s %u\n",
type, type,

View File

@ -1860,13 +1860,13 @@ 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) static bool gfs2_rgrp_congested(const struct gfs2_rgrpd *rgd, int loops)
{ {
const struct gfs2_glock *gl = rgd->rd_gl; 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; struct gfs2_lkstats *st;
s64 r_dcount, l_dcount; u64 r_dcount, l_dcount;
s64 l_srttb, a_srttb = 0; u64 l_srttb, a_srttb = 0;
s64 srttb_diff; s64 srttb_diff;
s64 sqr_diff; u64 sqr_diff;
s64 var; u64 var;
int cpu, nonzero = 0; int cpu, nonzero = 0;
preempt_disable(); preempt_disable();

View File

@ -104,7 +104,7 @@ TRACE_EVENT(gfs2_glock_state_change,
), ),
TP_fast_assign( 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->glnum = gl->gl_name.ln_number;
__entry->gltype = gl->gl_name.ln_type; __entry->gltype = gl->gl_name.ln_type;
__entry->cur_state = glock_trace_state(gl->gl_state); __entry->cur_state = glock_trace_state(gl->gl_state);
@ -140,7 +140,7 @@ TRACE_EVENT(gfs2_glock_put,
), ),
TP_fast_assign( 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->gltype = gl->gl_name.ln_type;
__entry->glnum = gl->gl_name.ln_number; __entry->glnum = gl->gl_name.ln_number;
__entry->cur_state = glock_trace_state(gl->gl_state); __entry->cur_state = glock_trace_state(gl->gl_state);
@ -174,7 +174,7 @@ TRACE_EVENT(gfs2_demote_rq,
), ),
TP_fast_assign( 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->gltype = gl->gl_name.ln_type;
__entry->glnum = gl->gl_name.ln_number; __entry->glnum = gl->gl_name.ln_number;
__entry->cur_state = glock_trace_state(gl->gl_state); __entry->cur_state = glock_trace_state(gl->gl_state);
@ -209,7 +209,7 @@ TRACE_EVENT(gfs2_promote,
), ),
TP_fast_assign( 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->glnum = gh->gh_gl->gl_name.ln_number;
__entry->gltype = gh->gh_gl->gl_name.ln_type; __entry->gltype = gh->gh_gl->gl_name.ln_type;
__entry->first = first; __entry->first = first;
@ -239,7 +239,7 @@ TRACE_EVENT(gfs2_glock_queue,
), ),
TP_fast_assign( 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->glnum = gh->gh_gl->gl_name.ln_number;
__entry->gltype = gh->gh_gl->gl_name.ln_type; __entry->gltype = gh->gh_gl->gl_name.ln_type;
__entry->queue = queue; __entry->queue = queue;
@ -267,18 +267,18 @@ TRACE_EVENT(gfs2_glock_lock_time,
__field( int, status ) __field( int, status )
__field( char, flags ) __field( char, flags )
__field( s64, tdiff ) __field( s64, tdiff )
__field( s64, srtt ) __field( u64, srtt )
__field( s64, srttvar ) __field( u64, srttvar )
__field( s64, srttb ) __field( u64, srttb )
__field( s64, srttvarb ) __field( u64, srttvarb )
__field( s64, sirt ) __field( u64, sirt )
__field( s64, sirtvar ) __field( u64, sirtvar )
__field( s64, dcount ) __field( u64, dcount )
__field( s64, qcount ) __field( u64, qcount )
), ),
TP_fast_assign( 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->glnum = gl->gl_name.ln_number;
__entry->gltype = gl->gl_name.ln_type; __entry->gltype = gl->gl_name.ln_type;
__entry->status = gl->gl_lksb.sb_status; __entry->status = gl->gl_lksb.sb_status;
@ -333,7 +333,7 @@ TRACE_EVENT(gfs2_pin,
), ),
TP_fast_assign( 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->pin = pin;
__entry->len = bd->bd_bh->b_size; __entry->len = bd->bd_bh->b_size;
__entry->block = bd->bd_bh->b_blocknr; __entry->block = bd->bd_bh->b_blocknr;
@ -449,7 +449,7 @@ TRACE_EVENT(gfs2_bmap,
), ),
TP_fast_assign( 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->lblock = lblock;
__entry->pblock = buffer_mapped(bh) ? bh->b_blocknr : 0; __entry->pblock = buffer_mapped(bh) ? bh->b_blocknr : 0;
__entry->inum = ip->i_no_addr; __entry->inum = ip->i_no_addr;
@ -489,7 +489,7 @@ TRACE_EVENT(gfs2_block_alloc,
), ),
TP_fast_assign( 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->start = block;
__entry->inum = ip->i_no_addr; __entry->inum = ip->i_no_addr;
__entry->len = len; __entry->len = len;

View File

@ -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) void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
{ {
struct gfs2_trans *tr = current->journal_info; 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 address_space *mapping = bh->b_page->mapping;
struct gfs2_inode *ip = GFS2_I(mapping->host); struct gfs2_inode *ip = GFS2_I(mapping->host);
struct gfs2_bufdata *bd; 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) 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; struct gfs2_bufdata *bd;
lock_buffer(bh); lock_buffer(bh);