Skip to content

Commit

Permalink
[GFS2] Move rwlocks in glock.c into their own array
Browse files Browse the repository at this point in the history
This splits the rwlocks guarding the hash chains of the glock hash
table into their own array. This will reduce memory usage in some
cases due to better alignment, although the real reason for doing it
is to allow the two tables to be different sizes in future (i.e.
the locks will be sized proportionally with the max number of CPUs
and the hash chains sized proportinally with the size of physical memory)

In order to allow this, the gl_bucket member of struct gfs2_glock has
now become gl_hash, so we record the hash rather than a pointer to the
bucket itself.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
  • Loading branch information
Steven Whitehouse committed Sep 8, 2006
1 parent 9b47c11 commit 37b2fa6
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 51 deletions.
87 changes: 42 additions & 45 deletions fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,17 @@ struct greedy {
struct work_struct gr_work;
};

struct gfs2_gl_hash_bucket {
struct list_head hb_list;
};

typedef void (*glock_examiner) (struct gfs2_glock * gl);

static int gfs2_dump_lockstate(struct gfs2_sbd *sdp);
static int dump_glock(struct gfs2_glock *gl);

static struct gfs2_gl_hash_bucket gl_hash_table[GFS2_GL_HASH_SIZE];
static rwlock_t gl_hash_locks[GFS2_GL_HASH_SIZE];

/**
* relaxed_state_ok - is a requested lock compatible with the current lock mode?
Expand Down Expand Up @@ -154,19 +159,18 @@ static void kill_glock(struct kref *kref)

int gfs2_glock_put(struct gfs2_glock *gl)
{
struct gfs2_gl_hash_bucket *bucket = gl->gl_bucket;
int rv = 0;

write_lock(&bucket->hb_lock);
write_lock(&gl_hash_locks[gl->gl_hash]);
if (kref_put(&gl->gl_ref, kill_glock)) {
list_del_init(&gl->gl_list);
write_unlock(&bucket->hb_lock);
list_del_init(&gl_hash_table[gl->gl_hash].hb_list);
write_unlock(&gl_hash_locks[gl->gl_hash]);
BUG_ON(spin_is_locked(&gl->gl_spin));
glock_free(gl);
rv = 1;
goto out;
}
write_unlock(&bucket->hb_lock);
write_unlock(&gl_hash_locks[gl->gl_hash]);
out:
return rv;
}
Expand Down Expand Up @@ -203,13 +207,13 @@ static inline int queue_empty(struct gfs2_glock *gl, struct list_head *head)
* Returns: NULL, or the struct gfs2_glock with the requested number
*/

static struct gfs2_glock *search_bucket(struct gfs2_gl_hash_bucket *bucket,
static struct gfs2_glock *search_bucket(unsigned int hash,
const struct gfs2_sbd *sdp,
const struct lm_lockname *name)
{
struct gfs2_glock *gl;

list_for_each_entry(gl, &bucket->hb_list, gl_list) {
list_for_each_entry(gl, &gl_hash_table[hash].hb_list, gl_list) {
if (test_bit(GLF_PLUG, &gl->gl_flags))
continue;
if (!lm_name_equal(&gl->gl_name, name))
Expand All @@ -236,12 +240,12 @@ static struct gfs2_glock *search_bucket(struct gfs2_gl_hash_bucket *bucket,
static struct gfs2_glock *gfs2_glock_find(const struct gfs2_sbd *sdp,
const struct lm_lockname *name)
{
struct gfs2_gl_hash_bucket *bucket = &gl_hash_table[gl_hash(sdp, name)];
unsigned int hash = gl_hash(sdp, name);
struct gfs2_glock *gl;

read_lock(&bucket->hb_lock);
gl = search_bucket(bucket, sdp, name);
read_unlock(&bucket->hb_lock);
read_lock(&gl_hash_locks[hash]);
gl = search_bucket(hash, sdp, name);
read_unlock(&gl_hash_locks[hash]);

return gl;
}
Expand All @@ -263,18 +267,14 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
const struct gfs2_glock_operations *glops, int create,
struct gfs2_glock **glp)
{
struct lm_lockname name;
struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type };
struct gfs2_glock *gl, *tmp;
struct gfs2_gl_hash_bucket *bucket;
unsigned int hash = gl_hash(sdp, &name);
int error;

name.ln_number = number;
name.ln_type = glops->go_type;
bucket = &gl_hash_table[gl_hash(sdp, &name)];

read_lock(&bucket->hb_lock);
gl = search_bucket(bucket, sdp, &name);
read_unlock(&bucket->hb_lock);
read_lock(&gl_hash_locks[hash]);
gl = search_bucket(hash, sdp, &name);
read_unlock(&gl_hash_locks[hash]);

if (gl || !create) {
*glp = gl;
Expand All @@ -289,6 +289,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
gl->gl_name = name;
kref_init(&gl->gl_ref);
gl->gl_state = LM_ST_UNLOCKED;
gl->gl_hash = hash;
gl->gl_owner = NULL;
gl->gl_ip = 0;
gl->gl_ops = glops;
Expand All @@ -297,7 +298,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
gl->gl_vn = 0;
gl->gl_stamp = jiffies;
gl->gl_object = NULL;
gl->gl_bucket = bucket;
gl->gl_sbd = sdp;
gl->gl_aspace = NULL;
lops_init_le(&gl->gl_le, &gfs2_glock_lops);
Expand All @@ -316,15 +316,15 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
if (error)
goto fail_aspace;

write_lock(&bucket->hb_lock);
tmp = search_bucket(bucket, sdp, &name);
write_lock(&gl_hash_locks[hash]);
tmp = search_bucket(hash, sdp, &name);
if (tmp) {
write_unlock(&bucket->hb_lock);
write_unlock(&gl_hash_locks[hash]);
glock_free(gl);
gl = tmp;
} else {
list_add_tail(&gl->gl_list, &bucket->hb_list);
write_unlock(&bucket->hb_lock);
list_add_tail(&gl->gl_list, &gl_hash_table[hash].hb_list);
write_unlock(&gl_hash_locks[hash]);
}

*glp = gl;
Expand Down Expand Up @@ -1868,7 +1868,7 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp)
*/

static int examine_bucket(glock_examiner examiner, struct gfs2_sbd *sdp,
struct gfs2_gl_hash_bucket *bucket)
unsigned int hash)
{
struct glock_plug plug;
struct list_head *tmp;
Expand All @@ -1879,20 +1879,20 @@ static int examine_bucket(glock_examiner examiner, struct gfs2_sbd *sdp,
memset(&plug.gl_flags, 0, sizeof(unsigned long));
set_bit(GLF_PLUG, &plug.gl_flags);

write_lock(&bucket->hb_lock);
list_add(&plug.gl_list, &bucket->hb_list);
write_unlock(&bucket->hb_lock);
write_lock(&gl_hash_locks[hash]);
list_add(&plug.gl_list, &gl_hash_table[hash].hb_list);
write_unlock(&gl_hash_locks[hash]);

for (;;) {
write_lock(&bucket->hb_lock);
write_lock(&gl_hash_locks[hash]);

for (;;) {
tmp = plug.gl_list.next;

if (tmp == &bucket->hb_list) {
if (tmp == &gl_hash_table[hash].hb_list) {
list_del(&plug.gl_list);
entries = !list_empty(&bucket->hb_list);
write_unlock(&bucket->hb_lock);
entries = !list_empty(&gl_hash_table[hash].hb_list);
write_unlock(&gl_hash_locks[hash]);
return entries;
}
gl = list_entry(tmp, struct gfs2_glock, gl_list);
Expand All @@ -1911,7 +1911,7 @@ static int examine_bucket(glock_examiner examiner, struct gfs2_sbd *sdp,
break;
}

write_unlock(&bucket->hb_lock);
write_unlock(&gl_hash_locks[hash]);

examiner(gl);
}
Expand Down Expand Up @@ -1956,7 +1956,7 @@ void gfs2_scand_internal(struct gfs2_sbd *sdp)
unsigned int x;

for (x = 0; x < GFS2_GL_HASH_SIZE; x++) {
examine_bucket(scan_glock, sdp, &gl_hash_table[x]);
examine_bucket(scan_glock, sdp, x);
cond_resched();
}
}
Expand Down Expand Up @@ -2015,7 +2015,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait)
cont = 0;

for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
if (examine_bucket(clear_glock, sdp, &gl_hash_table[x]))
if (examine_bucket(clear_glock, sdp, x))
cont = 1;

if (!wait || !cont)
Expand Down Expand Up @@ -2198,17 +2198,15 @@ static int dump_glock(struct gfs2_glock *gl)

static int gfs2_dump_lockstate(struct gfs2_sbd *sdp)
{
struct gfs2_gl_hash_bucket *bucket;
struct gfs2_glock *gl;
unsigned int x;
int error = 0;

for (x = 0; x < GFS2_GL_HASH_SIZE; x++) {
bucket = &gl_hash_table[x];

read_lock(&bucket->hb_lock);
read_lock(&gl_hash_locks[x]);

list_for_each_entry(gl, &bucket->hb_list, gl_list) {
list_for_each_entry(gl, &gl_hash_table[x].hb_list, gl_list) {
if (test_bit(GLF_PLUG, &gl->gl_flags))
continue;
if (gl->gl_sbd != sdp)
Expand All @@ -2219,7 +2217,7 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp)
break;
}

read_unlock(&bucket->hb_lock);
read_unlock(&gl_hash_locks[x]);

if (error)
break;
Expand All @@ -2233,9 +2231,8 @@ 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);
rwlock_init(&gl_hash_locks[i]);
INIT_LIST_HEAD(&gl_hash_table[i].hb_list);
}
return 0;
}
Expand Down
7 changes: 1 addition & 6 deletions fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,6 @@ struct gfs2_bufdata {
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 {
void (*go_xmote_th) (struct gfs2_glock * gl, unsigned int state,
int flags);
Expand Down Expand Up @@ -175,6 +170,7 @@ struct gfs2_glock {
spinlock_t gl_spin;

unsigned int gl_state;
unsigned int gl_hash;
struct task_struct *gl_owner;
unsigned long gl_ip;
struct list_head gl_holders;
Expand All @@ -195,7 +191,6 @@ struct gfs2_glock {
unsigned long gl_stamp;
void *gl_object;

struct gfs2_gl_hash_bucket *gl_bucket;
struct list_head gl_reclaim;

struct gfs2_sbd *gl_sbd;
Expand Down

0 comments on commit 37b2fa6

Please sign in to comment.