Skip to content

Commit

Permalink
[GFS2] Clean up the glock core
Browse files Browse the repository at this point in the history
This patch implements a number of cleanups to the core of the
GFS2 glock code. As a result a lot of code is removed. It looks
like a really big change, but actually a large part of this patch
is either removing or moving existing code.

There are some new bits too though, such as the new run_queue()
function which is considerably streamlined. Highlights of this
patch include:

 o Fixes a cluster coherency bug during SH -> EX lock conversions
 o Removes the "glmutex" code in favour of a single bit lock
 o Removes the ->go_xmote_bh() for inodes since it was duplicating
   ->go_lock()
 o We now only use the ->lm_lock() function for both locks and
   unlocks (i.e. unlock is a lock with target mode LM_ST_UNLOCKED)
 o The fast path is considerably shortly, giving performance gains
   especially with lock_nolock
 o The glock_workqueue is now used for all the callbacks from the DLM
   which allows us to simplify the lock_dlm module (see following patch)
 o The way is now open to make further changes such as eliminating the two
   threads (gfs2_glockd and gfs2_scand) in favour of a more efficient
   scheme.

This patch has undergone extensive testing with various test suites
so it should be pretty stable by now.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Cc: Bob Peterson <rpeterso@redhat.com>
  • Loading branch information
swhiteho committed Jun 27, 2008
1 parent 543cf4c commit 6802e34
Show file tree
Hide file tree
Showing 13 changed files with 758 additions and 1,071 deletions.
1,655 changes: 666 additions & 989 deletions fs/gfs2/glock.c

Large diffs are not rendered by default.

9 changes: 4 additions & 5 deletions fs/gfs2/glock.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,8 @@
#define GL_SKIP 0x00000100
#define GL_ATIME 0x00000200
#define GL_NOCACHE 0x00000400
#define GL_FLOCK 0x00000800
#define GL_NOCANCEL 0x00001000

#define GLR_TRYFAILED 13
#define GLR_CANCELED 14

static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
{
Expand All @@ -41,6 +38,8 @@ static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *
spin_lock(&gl->gl_spin);
pid = task_pid(current);
list_for_each_entry(gh, &gl->gl_holders, gh_list) {
if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
break;
if (gh->gh_owner_pid == pid)
goto out;
}
Expand Down Expand Up @@ -70,7 +69,7 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl)
{
int ret;
spin_lock(&gl->gl_spin);
ret = test_bit(GLF_DEMOTE, &gl->gl_flags) || !list_empty(&gl->gl_waiters3);
ret = test_bit(GLF_DEMOTE, &gl->gl_flags);
spin_unlock(&gl->gl_spin);
return ret;
}
Expand Down Expand Up @@ -98,6 +97,7 @@ int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);

/**
* gfs2_glock_nq_init - intialize a holder and enqueue it on a glock
Expand Down Expand Up @@ -130,7 +130,6 @@ int gfs2_lvb_hold(struct gfs2_glock *gl);
void gfs2_lvb_unhold(struct gfs2_glock *gl);

void gfs2_glock_cb(void *cb_data, unsigned int type, void *data);

void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl);
void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait);
Expand Down
70 changes: 44 additions & 26 deletions fs/gfs2/glops.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/buffer_head.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>
#include <linux/bio.h>

#include "gfs2.h"
#include "incore.h"
Expand Down Expand Up @@ -171,26 +172,6 @@ static void inode_go_sync(struct gfs2_glock *gl)
}
}

/**
* inode_go_xmote_bh - After promoting/demoting a glock
* @gl: the glock
*
*/

static void inode_go_xmote_bh(struct gfs2_glock *gl)
{
struct gfs2_holder *gh = gl->gl_req_gh;
struct buffer_head *bh;
int error;

if (gl->gl_state != LM_ST_UNLOCKED &&
(!gh || !(gh->gh_flags & GL_SKIP))) {
error = gfs2_meta_read(gl, gl->gl_name.ln_number, 0, &bh);
if (!error)
brelse(bh);
}
}

/**
* inode_go_inval - prepare a inode glock to be released
* @gl: the glock
Expand Down Expand Up @@ -266,6 +247,26 @@ static int inode_go_lock(struct gfs2_holder *gh)
return error;
}

/**
* inode_go_dump - print information about an inode
* @seq: The iterator
* @ip: the inode
*
* Returns: 0 on success, -ENOBUFS when we run out of space
*/

static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
{
const struct gfs2_inode *ip = gl->gl_object;
if (ip == NULL)
return 0;
gfs2_print_dbg(seq, " I: n:%llu/%llu t:%u f:0x%08lx\n",
(unsigned long long)ip->i_no_formal_ino,
(unsigned long long)ip->i_no_addr,
IF2DT(ip->i_inode.i_mode), ip->i_flags);
return 0;
}

/**
* rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock
* @gl: the glock
Expand Down Expand Up @@ -305,6 +306,22 @@ static void rgrp_go_unlock(struct gfs2_holder *gh)
gfs2_rgrp_bh_put(gh->gh_gl->gl_object);
}

/**
* rgrp_go_dump - print out an rgrp
* @seq: The iterator
* @gl: The glock in question
*
*/

static int rgrp_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
{
const struct gfs2_rgrpd *rgd = gl->gl_object;
if (rgd == NULL)
return 0;
gfs2_print_dbg(seq, " R: n:%llu\n", (unsigned long long)rgd->rd_addr);
return 0;
}

/**
* trans_go_sync - promote/demote the transaction glock
* @gl: the glock
Expand All @@ -330,16 +347,15 @@ static void trans_go_sync(struct gfs2_glock *gl)
*
*/

static void trans_go_xmote_bh(struct gfs2_glock *gl)
static int trans_go_xmote_bh(struct gfs2_glock *gl, struct gfs2_holder *gh)
{
struct gfs2_sbd *sdp = gl->gl_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;
int error;

if (gl->gl_state != LM_ST_UNLOCKED &&
test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);

error = gfs2_find_jhead(sdp->sd_jdesc, &head);
Expand All @@ -354,6 +370,7 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl)
gfs2_log_pointers_init(sdp, head.lh_blkno);
}
}
return 0;
}

/**
Expand All @@ -375,12 +392,12 @@ const struct gfs2_glock_operations gfs2_meta_glops = {

const struct gfs2_glock_operations gfs2_inode_glops = {
.go_xmote_th = inode_go_sync,
.go_xmote_bh = inode_go_xmote_bh,
.go_inval = inode_go_inval,
.go_demote_ok = inode_go_demote_ok,
.go_lock = inode_go_lock,
.go_dump = inode_go_dump,
.go_type = LM_TYPE_INODE,
.go_min_hold_time = HZ / 10,
.go_min_hold_time = HZ / 5,
};

const struct gfs2_glock_operations gfs2_rgrp_glops = {
Expand All @@ -389,8 +406,9 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
.go_demote_ok = rgrp_go_demote_ok,
.go_lock = rgrp_go_lock,
.go_unlock = rgrp_go_unlock,
.go_dump = rgrp_go_dump,
.go_type = LM_TYPE_RGRP,
.go_min_hold_time = HZ / 10,
.go_min_hold_time = HZ / 5,
};

const struct gfs2_glock_operations gfs2_trans_glops = {
Expand Down
35 changes: 15 additions & 20 deletions fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,20 +128,20 @@ struct gfs2_bufdata {

struct gfs2_glock_operations {
void (*go_xmote_th) (struct gfs2_glock *gl);
void (*go_xmote_bh) (struct gfs2_glock *gl);
int (*go_xmote_bh) (struct gfs2_glock *gl, struct gfs2_holder *gh);
void (*go_inval) (struct gfs2_glock *gl, int flags);
int (*go_demote_ok) (struct gfs2_glock *gl);
int (*go_lock) (struct gfs2_holder *gh);
void (*go_unlock) (struct gfs2_holder *gh);
int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl);
const int go_type;
const unsigned long go_min_hold_time;
};

enum {
/* States */
HIF_HOLDER = 6,
HIF_HOLDER = 6, /* Set for gh that "holds" the glock */
HIF_FIRST = 7,
HIF_ABORTED = 9,
HIF_WAIT = 10,
};

Expand All @@ -154,20 +154,20 @@ struct gfs2_holder {
unsigned gh_flags;

int gh_error;
unsigned long gh_iflags;
unsigned long gh_iflags; /* HIF_... */
unsigned long gh_ip;
};

enum {
GLF_LOCK = 1,
GLF_STICKY = 2,
GLF_DEMOTE = 3,
GLF_PENDING_DEMOTE = 4,
GLF_DIRTY = 5,
GLF_DEMOTE_IN_PROGRESS = 6,
GLF_LFLUSH = 7,
GLF_WAITERS2 = 8,
GLF_CONV_DEADLK = 9,
GLF_LOCK = 1,
GLF_STICKY = 2,
GLF_DEMOTE = 3,
GLF_PENDING_DEMOTE = 4,
GLF_DEMOTE_IN_PROGRESS = 5,
GLF_DIRTY = 6,
GLF_LFLUSH = 7,
GLF_INVALIDATE_IN_PROGRESS = 8,
GLF_REPLY_PENDING = 9,
};

struct gfs2_glock {
Expand All @@ -179,19 +179,14 @@ struct gfs2_glock {
spinlock_t gl_spin;

unsigned int gl_state;
unsigned int gl_target;
unsigned int gl_reply;
unsigned int gl_hash;
unsigned int gl_demote_state; /* state requested by remote node */
unsigned long gl_demote_time; /* time of first demote request */
struct pid *gl_owner_pid;
unsigned long gl_ip;
struct list_head gl_holders;
struct list_head gl_waiters1; /* HIF_MUTEX */
struct list_head gl_waiters3; /* HIF_PROMOTE */

const struct gfs2_glock_operations *gl_ops;

struct gfs2_holder *gl_req_gh;

void *gl_lock;
char *gl_lvb;
atomic_t gl_lvb_count;
Expand Down
3 changes: 3 additions & 0 deletions fs/gfs2/locking/dlm/lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ unsigned int gdlm_lock(void *lock, unsigned int cur_state,
{
struct gdlm_lock *lp = lock;

if (req_state == LM_ST_UNLOCKED)
return gdlm_unlock(lock, cur_state);

clear_bit(LFL_DLM_CANCEL, &lp->flags);
if (flags & LM_FLAG_NOEXP)
set_bit(LFL_NOBLOCK, &lp->flags);
Expand Down
2 changes: 2 additions & 0 deletions fs/gfs2/locking/nolock/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ static void nolock_put_lock(void *lock)
static unsigned int nolock_lock(void *lock, unsigned int cur_state,
unsigned int req_state, unsigned int flags)
{
if (req_state == LM_ST_UNLOCKED)
return 0;
return req_state | LM_OUT_CACHEABLE;
}

Expand Down
2 changes: 0 additions & 2 deletions fs/gfs2/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ static void gfs2_init_glock_once(struct kmem_cache *cachep, void *foo)
INIT_HLIST_NODE(&gl->gl_list);
spin_lock_init(&gl->gl_spin);
INIT_LIST_HEAD(&gl->gl_holders);
INIT_LIST_HEAD(&gl->gl_waiters1);
INIT_LIST_HEAD(&gl->gl_waiters3);
gl->gl_lvb = NULL;
atomic_set(&gl->gl_lvb_count, 0);
INIT_LIST_HEAD(&gl->gl_reclaim);
Expand Down
14 changes: 7 additions & 7 deletions fs/gfs2/meta_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ void gfs2_meta_sync(struct gfs2_glock *gl)
}

/**
* getbuf - Get a buffer with a given address space
* gfs2_getbuf - Get a buffer with a given address space
* @gl: the glock
* @blkno: the block number (filesystem scope)
* @create: 1 if the buffer should be created
*
* Returns: the buffer
*/

static struct buffer_head *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 = gl->gl_aspace->i_mapping;
struct gfs2_sbd *sdp = gl->gl_sbd;
Expand Down Expand Up @@ -205,7 +205,7 @@ static void meta_prep_new(struct buffer_head *bh)
struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
{
struct buffer_head *bh;
bh = getbuf(gl, blkno, CREATE);
bh = gfs2_getbuf(gl, blkno, CREATE);
meta_prep_new(bh);
return bh;
}
Expand All @@ -223,7 +223,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)
{
*bhp = getbuf(gl, blkno, CREATE);
*bhp = gfs2_getbuf(gl, blkno, CREATE);
if (!buffer_uptodate(*bhp)) {
ll_rw_block(READ_META, 1, bhp);
if (flags & DIO_WAIT) {
Expand Down Expand Up @@ -346,7 +346,7 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
struct buffer_head *bh;

while (blen) {
bh = getbuf(ip->i_gl, bstart, NO_CREATE);
bh = gfs2_getbuf(ip->i_gl, bstart, NO_CREATE);
if (bh) {
lock_buffer(bh);
gfs2_log_lock(sdp);
Expand Down Expand Up @@ -421,7 +421,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
if (extlen > max_ra)
extlen = max_ra;

first_bh = getbuf(gl, dblock, CREATE);
first_bh = gfs2_getbuf(gl, dblock, CREATE);

if (buffer_uptodate(first_bh))
goto out;
Expand All @@ -432,7 +432,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
extlen--;

while (extlen) {
bh = getbuf(gl, dblock, CREATE);
bh = gfs2_getbuf(gl, dblock, CREATE);

if (!buffer_uptodate(bh) && !buffer_locked(bh))
ll_rw_block(READA, 1, &bh);
Expand Down
1 change: 1 addition & 0 deletions fs/gfs2/meta_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,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);
int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create);

void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
int meta);
Expand Down
25 changes: 11 additions & 14 deletions fs/gfs2/ops_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,26 +507,23 @@ static int __gfs2_readpage(void *file, struct page *page)
static int gfs2_readpage(struct file *file, struct page *page)
{
struct gfs2_inode *ip = GFS2_I(page->mapping->host);
struct gfs2_holder *gh;
struct gfs2_holder gh;
int error;

gh = gfs2_glock_is_locked_by_me(ip->i_gl);
if (!gh) {
gh = kmalloc(sizeof(struct gfs2_holder), GFP_NOFS);
if (!gh)
return -ENOBUFS;
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, gh);
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME|LM_FLAG_TRY_1CB, &gh);
error = gfs2_glock_nq_atime(&gh);
if (unlikely(error)) {
unlock_page(page);
error = gfs2_glock_nq_atime(gh);
if (likely(error != 0))
goto out;
return AOP_TRUNCATED_PAGE;
goto out;
}
error = __gfs2_readpage(file, page);
gfs2_glock_dq(gh);
gfs2_glock_dq(&gh);
out:
gfs2_holder_uninit(gh);
kfree(gh);
gfs2_holder_uninit(&gh);
if (error == GLR_TRYFAILED) {
yield();
return AOP_TRUNCATED_PAGE;
}
return error;
}

Expand Down
Loading

0 comments on commit 6802e34

Please sign in to comment.