提交 85d1da67 编写于 作者: S Steven Whitehouse

[GFS2] Move glock hash table out of superblock

There are several reasons why we want to do this:
 - Firstly its large and thus we'll scale better with multiple
   GFS2 fs mounted at the same time
 - Secondly its easier to scale its size as required (thats a plan
   for later patches)
 - Thirdly, we can use kzalloc rather than vmalloc when allocating
   the superblock (its now only 4888 bytes)
 - Fourth its all part of my plan to eventually be able to use RCU
   with the glock hash.
Signed-off-by: NSteven Whitehouse <swhiteho@redhat.com>
上级 b8547856
...@@ -49,6 +49,8 @@ typedef void (*glock_examiner) (struct gfs2_glock * gl); ...@@ -49,6 +49,8 @@ typedef void (*glock_examiner) (struct gfs2_glock * gl);
static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); static int gfs2_dump_lockstate(struct gfs2_sbd *sdp);
static int dump_glock(struct gfs2_glock *gl); static int dump_glock(struct gfs2_glock *gl);
static struct gfs2_gl_hash_bucket gl_hash_table[GFS2_GL_HASH_SIZE];
/** /**
* relaxed_state_ok - is a requested lock compatible with the current lock mode? * relaxed_state_ok - is a requested lock compatible with the current lock mode?
* @actual: the current state of the lock * @actual: the current state of the lock
...@@ -231,10 +233,10 @@ static struct gfs2_glock *search_bucket(struct gfs2_gl_hash_bucket *bucket, ...@@ -231,10 +233,10 @@ static struct gfs2_glock *search_bucket(struct gfs2_gl_hash_bucket *bucket,
* Returns: NULL, or the struct gfs2_glock with the requested number * Returns: NULL, or the struct gfs2_glock with the requested number
*/ */
static struct gfs2_glock *gfs2_glock_find(struct gfs2_sbd *sdp, static struct gfs2_glock *gfs2_glock_find(const struct gfs2_sbd *sdp,
const struct lm_lockname *name) const struct lm_lockname *name)
{ {
struct gfs2_gl_hash_bucket *bucket = &sdp->sd_gl_hash[gl_hash(sdp, name)]; struct gfs2_gl_hash_bucket *bucket = &gl_hash_table[gl_hash(sdp, name)];
struct gfs2_glock *gl; struct gfs2_glock *gl;
read_lock(&bucket->hb_lock); read_lock(&bucket->hb_lock);
...@@ -268,7 +270,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, ...@@ -268,7 +270,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
name.ln_number = number; name.ln_number = number;
name.ln_type = glops->go_type; name.ln_type = glops->go_type;
bucket = &sdp->sd_gl_hash[gl_hash(sdp, &name)]; bucket = &gl_hash_table[gl_hash(sdp, &name)];
read_lock(&bucket->hb_lock); read_lock(&bucket->hb_lock);
gl = search_bucket(bucket, sdp, &name); gl = search_bucket(bucket, sdp, &name);
...@@ -648,9 +650,9 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl) ...@@ -648,9 +650,9 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl)
set_bit(HIF_MUTEX, &gh.gh_iflags); set_bit(HIF_MUTEX, &gh.gh_iflags);
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
list_add_tail(&gh.gh_list, &gl->gl_waiters1); list_add_tail(&gh.gh_list, &gl->gl_waiters1);
else { } else {
gl->gl_owner = current; gl->gl_owner = current;
gl->gl_ip = (unsigned long)__builtin_return_address(0); gl->gl_ip = (unsigned long)__builtin_return_address(0);
complete(&gh.gh_wait); complete(&gh.gh_wait);
...@@ -673,9 +675,9 @@ static int gfs2_glmutex_trylock(struct gfs2_glock *gl) ...@@ -673,9 +675,9 @@ static int gfs2_glmutex_trylock(struct gfs2_glock *gl)
int acquired = 1; int acquired = 1;
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
acquired = 0; acquired = 0;
else { } else {
gl->gl_owner = current; gl->gl_owner = current;
gl->gl_ip = (unsigned long)__builtin_return_address(0); gl->gl_ip = (unsigned long)__builtin_return_address(0);
} }
...@@ -830,9 +832,9 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) ...@@ -830,9 +832,9 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
list_del_init(&gh->gh_list); list_del_init(&gh->gh_list);
if (gl->gl_state == gh->gh_state || if (gl->gl_state == gh->gh_state ||
gl->gl_state == LM_ST_UNLOCKED) gl->gl_state == LM_ST_UNLOCKED) {
gh->gh_error = 0; gh->gh_error = 0;
else { } else {
if (gfs2_assert_warn(sdp, gh->gh_flags & if (gfs2_assert_warn(sdp, gh->gh_flags &
(LM_FLAG_TRY | LM_FLAG_TRY_1CB)) == -1) (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) == -1)
fs_warn(sdp, "ret = 0x%.8X\n", ret); fs_warn(sdp, "ret = 0x%.8X\n", ret);
...@@ -1090,8 +1092,7 @@ static int glock_wait_internal(struct gfs2_holder *gh) ...@@ -1090,8 +1092,7 @@ static int glock_wait_internal(struct gfs2_holder *gh)
return gh->gh_error; return gh->gh_error;
gfs2_assert_withdraw(sdp, test_bit(HIF_HOLDER, &gh->gh_iflags)); gfs2_assert_withdraw(sdp, test_bit(HIF_HOLDER, &gh->gh_iflags));
gfs2_assert_withdraw(sdp, relaxed_state_ok(gl->gl_state, gfs2_assert_withdraw(sdp, relaxed_state_ok(gl->gl_state, gh->gh_state,
gh->gh_state,
gh->gh_flags)); gh->gh_flags));
if (test_bit(HIF_FIRST, &gh->gh_iflags)) { if (test_bit(HIF_FIRST, &gh->gh_iflags)) {
...@@ -1901,6 +1902,8 @@ static int examine_bucket(glock_examiner examiner, struct gfs2_sbd *sdp, ...@@ -1901,6 +1902,8 @@ static int examine_bucket(glock_examiner examiner, struct gfs2_sbd *sdp,
if (test_bit(GLF_PLUG, &gl->gl_flags)) if (test_bit(GLF_PLUG, &gl->gl_flags))
continue; continue;
if (gl->gl_sbd != sdp)
continue;
/* examiner() must glock_put() */ /* examiner() must glock_put() */
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
...@@ -1953,7 +1956,7 @@ void gfs2_scand_internal(struct gfs2_sbd *sdp) ...@@ -1953,7 +1956,7 @@ void gfs2_scand_internal(struct gfs2_sbd *sdp)
unsigned int x; unsigned int x;
for (x = 0; x < GFS2_GL_HASH_SIZE; x++) { for (x = 0; x < GFS2_GL_HASH_SIZE; x++) {
examine_bucket(scan_glock, sdp, &sdp->sd_gl_hash[x]); examine_bucket(scan_glock, sdp, &gl_hash_table[x]);
cond_resched(); cond_resched();
} }
} }
...@@ -2012,7 +2015,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait) ...@@ -2012,7 +2015,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait)
cont = 0; cont = 0;
for (x = 0; x < GFS2_GL_HASH_SIZE; x++) for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
if (examine_bucket(clear_glock, sdp, &sdp->sd_gl_hash[x])) if (examine_bucket(clear_glock, sdp, &gl_hash_table[x]))
cont = 1; cont = 1;
if (!wait || !cont) if (!wait || !cont)
...@@ -2114,14 +2117,13 @@ static int dump_glock(struct gfs2_glock *gl) ...@@ -2114,14 +2117,13 @@ static int dump_glock(struct gfs2_glock *gl)
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
printk(KERN_INFO "Glock 0x%p (%u, %llu)\n", printk(KERN_INFO "Glock 0x%p (%u, %llu)\n", gl, gl->gl_name.ln_type,
gl,
gl->gl_name.ln_type,
(unsigned long long)gl->gl_name.ln_number); (unsigned long long)gl->gl_name.ln_number);
printk(KERN_INFO " gl_flags ="); printk(KERN_INFO " gl_flags =");
for (x = 0; x < 32; x++) for (x = 0; x < 32; x++) {
if (test_bit(x, &gl->gl_flags)) if (test_bit(x, &gl->gl_flags))
printk(" %u", x); printk(" %u", x);
}
printk(" \n"); printk(" \n");
printk(KERN_INFO " gl_ref = %d\n", atomic_read(&gl->gl_ref.refcount)); printk(KERN_INFO " gl_ref = %d\n", atomic_read(&gl->gl_ref.refcount));
printk(KERN_INFO " gl_state = %u\n", gl->gl_state); printk(KERN_INFO " gl_state = %u\n", gl->gl_state);
...@@ -2136,8 +2138,7 @@ static int dump_glock(struct gfs2_glock *gl) ...@@ -2136,8 +2138,7 @@ static int dump_glock(struct gfs2_glock *gl)
printk(KERN_INFO " reclaim = %s\n", printk(KERN_INFO " reclaim = %s\n",
(list_empty(&gl->gl_reclaim)) ? "no" : "yes"); (list_empty(&gl->gl_reclaim)) ? "no" : "yes");
if (gl->gl_aspace) if (gl->gl_aspace)
printk(KERN_INFO " aspace = 0x%p nrpages = %lu\n", printk(KERN_INFO " aspace = 0x%p nrpages = %lu\n", gl->gl_aspace,
gl->gl_aspace,
gl->gl_aspace->i_mapping->nrpages); gl->gl_aspace->i_mapping->nrpages);
else else
printk(KERN_INFO " aspace = no\n"); printk(KERN_INFO " aspace = no\n");
...@@ -2203,13 +2204,15 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp) ...@@ -2203,13 +2204,15 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp)
int error = 0; int error = 0;
for (x = 0; x < GFS2_GL_HASH_SIZE; x++) { for (x = 0; x < GFS2_GL_HASH_SIZE; x++) {
bucket = &sdp->sd_gl_hash[x]; bucket = &gl_hash_table[x];
read_lock(&bucket->hb_lock); read_lock(&bucket->hb_lock);
list_for_each_entry(gl, &bucket->hb_list, gl_list) { list_for_each_entry(gl, &bucket->hb_list, gl_list) {
if (test_bit(GLF_PLUG, &gl->gl_flags)) if (test_bit(GLF_PLUG, &gl->gl_flags))
continue; continue;
if (gl->gl_sbd != sdp)
continue;
error = dump_glock(gl); error = dump_glock(gl);
if (error) if (error)
...@@ -2226,3 +2229,14 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp) ...@@ -2226,3 +2229,14 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp)
return error; return error;
} }
int __init gfs2_glock_init(void)
{
unsigned i;
for(i = 0; i < GFS2_GL_HASH_SIZE; i++) {
struct gfs2_gl_hash_bucket *hb = &gl_hash_table[i];
rwlock_init(&hb->hb_lock);
INIT_LIST_HEAD(&hb->hb_list);
}
return 0;
}
...@@ -150,4 +150,6 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp); ...@@ -150,4 +150,6 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
void gfs2_scand_internal(struct gfs2_sbd *sdp); void gfs2_scand_internal(struct gfs2_sbd *sdp);
void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait); void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait);
int __init gfs2_glock_init(void);
#endif /* __GLOCK_DOT_H__ */ #endif /* __GLOCK_DOT_H__ */
...@@ -30,7 +30,6 @@ struct gfs2_quota_data; ...@@ -30,7 +30,6 @@ struct gfs2_quota_data;
struct gfs2_trans; struct gfs2_trans;
struct gfs2_ail; struct gfs2_ail;
struct gfs2_jdesc; struct gfs2_jdesc;
struct gfs2_gl_hash_bucket;
struct gfs2_sbd; struct gfs2_sbd;
typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret); typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret);
...@@ -107,6 +106,11 @@ struct gfs2_bufdata { ...@@ -107,6 +106,11 @@ struct gfs2_bufdata {
struct list_head bd_ail_gl_list; struct list_head bd_ail_gl_list;
}; };
struct gfs2_gl_hash_bucket {
rwlock_t hb_lock;
struct list_head hb_list;
};
struct gfs2_glock_operations { struct gfs2_glock_operations {
void (*go_xmote_th) (struct gfs2_glock * gl, unsigned int state, void (*go_xmote_th) (struct gfs2_glock * gl, unsigned int state,
int flags); int flags);
...@@ -442,11 +446,6 @@ struct gfs2_tune { ...@@ -442,11 +446,6 @@ struct gfs2_tune {
unsigned int gt_statfs_slow; unsigned int gt_statfs_slow;
}; };
struct gfs2_gl_hash_bucket {
rwlock_t hb_lock;
struct list_head hb_list;
};
enum { enum {
SDF_JOURNAL_CHECKED = 0, SDF_JOURNAL_CHECKED = 0,
SDF_JOURNAL_LIVE = 1, SDF_JOURNAL_LIVE = 1,
...@@ -489,7 +488,6 @@ struct gfs2_sbd { ...@@ -489,7 +488,6 @@ struct gfs2_sbd {
/* Lock Stuff */ /* Lock Stuff */
struct lm_lockstruct sd_lockstruct; struct lm_lockstruct sd_lockstruct;
struct gfs2_gl_hash_bucket sd_gl_hash[GFS2_GL_HASH_SIZE];
struct list_head sd_reclaim_list; struct list_head sd_reclaim_list;
spinlock_t sd_reclaim_lock; spinlock_t sd_reclaim_lock;
wait_queue_head_t sd_reclaim_wq; wait_queue_head_t sd_reclaim_wq;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "ops_fstype.h" #include "ops_fstype.h"
#include "sys.h" #include "sys.h"
#include "util.h" #include "util.h"
#include "glock.h"
static void gfs2_init_inode_once(void *foo, kmem_cache_t *cachep, unsigned long flags) static void gfs2_init_inode_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
{ {
...@@ -69,8 +70,11 @@ static int __init init_gfs2_fs(void) ...@@ -69,8 +70,11 @@ static int __init init_gfs2_fs(void)
if (error) if (error)
return error; return error;
error = -ENOMEM; error = gfs2_glock_init();
if (error)
goto fail;
error = -ENOMEM;
gfs2_glock_cachep = kmem_cache_create("gfs2_glock", gfs2_glock_cachep = kmem_cache_create("gfs2_glock",
sizeof(struct gfs2_glock), sizeof(struct gfs2_glock),
0, 0, 0, 0,
......
...@@ -45,23 +45,16 @@ extern struct dentry_operations gfs2_dops; ...@@ -45,23 +45,16 @@ extern struct dentry_operations gfs2_dops;
static struct gfs2_sbd *init_sbd(struct super_block *sb) static struct gfs2_sbd *init_sbd(struct super_block *sb)
{ {
struct gfs2_sbd *sdp; struct gfs2_sbd *sdp;
unsigned int x;
sdp = vmalloc(sizeof(struct gfs2_sbd)); sdp = kzalloc(sizeof(struct gfs2_sbd), GFP_KERNEL);
if (!sdp) if (!sdp)
return NULL; return NULL;
memset(sdp, 0, sizeof(struct gfs2_sbd));
sb->s_fs_info = sdp; sb->s_fs_info = sdp;
sdp->sd_vfs = sb; sdp->sd_vfs = sb;
gfs2_tune_init(&sdp->sd_tune); gfs2_tune_init(&sdp->sd_tune);
for (x = 0; x < GFS2_GL_HASH_SIZE; x++) {
rwlock_init(&sdp->sd_gl_hash[x].hb_lock);
INIT_LIST_HEAD(&sdp->sd_gl_hash[x].hb_list);
}
INIT_LIST_HEAD(&sdp->sd_reclaim_list); INIT_LIST_HEAD(&sdp->sd_reclaim_list);
spin_lock_init(&sdp->sd_reclaim_lock); spin_lock_init(&sdp->sd_reclaim_lock);
init_waitqueue_head(&sdp->sd_reclaim_wq); init_waitqueue_head(&sdp->sd_reclaim_wq);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册