aboutsummaryrefslogtreecommitdiff
path: root/fs/gfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/Kconfig47
-rw-r--r--fs/gfs2/bmap.c10
-rw-r--r--fs/gfs2/dir.c25
-rw-r--r--fs/gfs2/dir.h21
-rw-r--r--fs/gfs2/eattr.c8
-rw-r--r--fs/gfs2/glock.c316
-rw-r--r--fs/gfs2/glock.h11
-rw-r--r--fs/gfs2/glops.c136
-rw-r--r--fs/gfs2/incore.h18
-rw-r--r--fs/gfs2/inode.c61
-rw-r--r--fs/gfs2/lm.c8
-rw-r--r--fs/gfs2/locking/dlm/lock_dlm.h2
-rw-r--r--fs/gfs2/locking/dlm/main.c6
-rw-r--r--fs/gfs2/locking/dlm/mount.c6
-rw-r--r--fs/gfs2/locking/dlm/plock.c2
-rw-r--r--fs/gfs2/locking/dlm/sysfs.c13
-rw-r--r--fs/gfs2/lops.c14
-rw-r--r--fs/gfs2/meta_io.c3
-rw-r--r--fs/gfs2/ops_address.c134
-rw-r--r--fs/gfs2/ops_dentry.c16
-rw-r--r--fs/gfs2/ops_export.c15
-rw-r--r--fs/gfs2/ops_file.c52
-rw-r--r--fs/gfs2/ops_inode.c63
-rw-r--r--fs/gfs2/ops_inode.h8
-rw-r--r--fs/gfs2/ops_super.c13
-rw-r--r--fs/gfs2/ops_super.h2
-rw-r--r--fs/gfs2/ops_vm.c24
-rw-r--r--fs/gfs2/super.c16
-rw-r--r--fs/gfs2/sys.c10
29 files changed, 391 insertions, 669 deletions
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index 6a2ffa2db14..de8e64c03f7 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -4,44 +4,43 @@ config GFS2_FS
select FS_POSIX_ACL
select CRC32
help
- A cluster filesystem.
+ A cluster filesystem.
- Allows a cluster of computers to simultaneously use a block device
- that is shared between them (with FC, iSCSI, NBD, etc...). GFS reads
- and writes to the block device like a local filesystem, but also uses
- a lock module to allow the computers coordinate their I/O so
- filesystem consistency is maintained. One of the nifty features of
- GFS is perfect consistency -- changes made to the filesystem on one
- machine show up immediately on all other machines in the cluster.
+ Allows a cluster of computers to simultaneously use a block device
+ that is shared between them (with FC, iSCSI, NBD, etc...). GFS reads
+ and writes to the block device like a local filesystem, but also uses
+ a lock module to allow the computers coordinate their I/O so
+ filesystem consistency is maintained. One of the nifty features of
+ GFS is perfect consistency -- changes made to the filesystem on one
+ machine show up immediately on all other machines in the cluster.
- To use the GFS2 filesystem, you will need to enable one or more of
- the below locking modules. Documentation and utilities for GFS2 can
- be found here: http://sources.redhat.com/cluster
+ To use the GFS2 filesystem, you will need to enable one or more of
+ the below locking modules. Documentation and utilities for GFS2 can
+ be found here: http://sources.redhat.com/cluster
config GFS2_FS_LOCKING_NOLOCK
tristate "GFS2 \"nolock\" locking module"
depends on GFS2_FS
help
- Single node locking module for GFS2.
+ Single node locking module for GFS2.
- Use this module if you want to use GFS2 on a single node without
- its clustering features. You can still take advantage of the
- large file support, and upgrade to running a full cluster later on
- if required.
+ Use this module if you want to use GFS2 on a single node without
+ its clustering features. You can still take advantage of the
+ large file support, and upgrade to running a full cluster later on
+ if required.
- If you will only be using GFS2 in cluster mode, you do not need this
- module.
+ If you will only be using GFS2 in cluster mode, you do not need this
+ module.
config GFS2_FS_LOCKING_DLM
tristate "GFS2 DLM locking module"
- depends on GFS2_FS && NET && INET && (IPV6 || IPV6=n)
+ depends on GFS2_FS && SYSFS && NET && INET && (IPV6 || IPV6=n)
select IP_SCTP if DLM_SCTP
select CONFIGFS_FS
select DLM
help
- Multiple node locking module for GFS2
-
- Most users of GFS2 will require this module. It provides the locking
- interface between GFS2 and the DLM, which is required to use GFS2
- in a cluster environment.
+ Multiple node locking module for GFS2
+ Most users of GFS2 will require this module. It provides the locking
+ interface between GFS2 and the DLM, which is required to use GFS2
+ in a cluster environment.
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 8240c1ff94f..113f6c9110c 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -773,7 +773,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
gfs2_free_data(ip, bstart, blen);
}
- ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_dinode_out(ip, dibh->b_data);
@@ -848,7 +848,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
}
ip->i_di.di_size = size;
- ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
error = gfs2_meta_inode_buffer(ip, &dibh);
if (error)
@@ -963,7 +963,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
if (gfs2_is_stuffed(ip)) {
ip->i_di.di_size = size;
- ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
@@ -975,7 +975,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
if (!error) {
ip->i_di.di_size = size;
- ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1048,7 +1048,7 @@ static int trunc_end(struct gfs2_inode *ip)
ip->i_num.no_addr;
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
}
- ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 0fdcb7713cd..c93ca8f361b 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -131,7 +131,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
if (ip->i_di.di_size < offset + size)
ip->i_di.di_size = offset + size;
- ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -229,7 +229,7 @@ out:
if (ip->i_di.di_size < offset + copied)
ip->i_di.di_size = offset + copied;
- ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1198,12 +1198,11 @@ static int compare_dents(const void *a, const void *b)
*/
static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
- void *opaque, gfs2_filldir_t filldir,
+ void *opaque, filldir_t filldir,
const struct gfs2_dirent **darr, u32 entries,
int *copied)
{
const struct gfs2_dirent *dent, *dent_next;
- struct gfs2_inum_host inum;
u64 off, off_next;
unsigned int x, y;
int run = 0;
@@ -1240,11 +1239,9 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
*offset = off;
}
- gfs2_inum_in(&inum, (char *)&dent->de_inum);
-
error = filldir(opaque, (const char *)(dent + 1),
be16_to_cpu(dent->de_name_len),
- off, &inum,
+ off, be64_to_cpu(dent->de_inum.no_addr),
be16_to_cpu(dent->de_type));
if (error)
return 1;
@@ -1262,8 +1259,8 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
}
static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
- gfs2_filldir_t filldir, int *copied,
- unsigned *depth, u64 leaf_no)
+ filldir_t filldir, int *copied, unsigned *depth,
+ u64 leaf_no)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
@@ -1343,7 +1340,7 @@ out:
*/
static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
- gfs2_filldir_t filldir)
+ filldir_t filldir)
{
struct gfs2_inode *dip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
@@ -1402,7 +1399,7 @@ out:
}
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
- gfs2_filldir_t filldir)
+ filldir_t filldir)
{
struct gfs2_inode *dip = GFS2_I(inode);
struct dirent_gather g;
@@ -1568,7 +1565,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
break;
gfs2_trans_add_bh(ip->i_gl, bh, 1);
ip->i_di.di_entries++;
- ip->i_inode.i_mtime.tv_sec = ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
error = 0;
@@ -1654,7 +1651,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
gfs2_consist_inode(dip);
gfs2_trans_add_bh(dip->i_gl, bh, 1);
dip->i_di.di_entries--;
- dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds();
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
mark_inode_dirty(&dip->i_inode);
@@ -1702,7 +1699,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
gfs2_trans_add_bh(dip->i_gl, bh, 1);
}
- dip->i_inode.i_mtime.tv_sec = dip->i_inode.i_ctime.tv_sec = get_seconds();
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
return 0;
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index b21b33668a5..48fe89046bb 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -16,30 +16,13 @@ struct inode;
struct gfs2_inode;
struct gfs2_inum;
-/**
- * gfs2_filldir_t - Report a directory entry to the caller of gfs2_dir_read()
- * @opaque: opaque data used by the function
- * @name: the name of the directory entry
- * @length: the length of the name
- * @offset: the entry's offset in the directory
- * @inum: the inode number the entry points to
- * @type: the type of inode the entry points to
- *
- * Returns: 0 on success, 1 if buffer full
- */
-
-typedef int (*gfs2_filldir_t) (void *opaque,
- const char *name, unsigned int length,
- u64 offset,
- struct gfs2_inum_host *inum, unsigned int type);
-
int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
struct gfs2_inum_host *inum, unsigned int *type);
int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
const struct gfs2_inum_host *inum, unsigned int type);
int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
-int gfs2_dir_read(struct inode *inode, u64 * offset, void *opaque,
- gfs2_filldir_t filldir);
+int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
+ filldir_t filldir);
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
struct gfs2_inum_host *new_inum, unsigned int new_type);
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index ebebbdcd705..0c83c7f4dda 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -301,7 +301,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -718,7 +718,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
(er->er_mode & S_IFMT));
ip->i_inode.i_mode = er->er_mode;
}
- ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -853,7 +853,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
(ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));
ip->i_inode.i_mode = er->er_mode;
}
- ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -1134,7 +1134,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime.tv_sec = get_seconds();
+ ip->i_inode.i_ctime = CURRENT_TIME_SEC;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 438146904b5..6618c119025 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -19,6 +19,8 @@
#include <linux/gfs2_ondisk.h>
#include <linux/list.h>
#include <linux/lm_interface.h>
+#include <linux/wait.h>
+#include <linux/rwsem.h>
#include <asm/uaccess.h>
#include "gfs2.h"
@@ -33,11 +35,6 @@
#include "super.h"
#include "util.h"
-struct greedy {
- struct gfs2_holder gr_gh;
- struct delayed_work gr_work;
-};
-
struct gfs2_gl_hash_bucket {
struct hlist_head hb_list;
};
@@ -47,6 +44,9 @@ 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 int dump_inode(struct gfs2_inode *ip);
+static void gfs2_glock_xmote_th(struct gfs2_holder *gh);
+static void gfs2_glock_drop_th(struct gfs2_glock *gl);
+static DECLARE_RWSEM(gfs2_umount_flush_sem);
#define GFS2_GL_HASH_SHIFT 15
#define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT)
@@ -213,30 +213,6 @@ out:
}
/**
- * queue_empty - check to see if a glock's queue is empty
- * @gl: the glock
- * @head: the head of the queue to check
- *
- * This function protects the list in the event that a process already
- * has a holder on the list and is adding a second holder for itself.
- * The glmutex lock is what generally prevents processes from working
- * on the same glock at once, but the special case of adding a second
- * holder for yourself ("recursive" locking) doesn't involve locking
- * glmutex, making the spin lock necessary.
- *
- * Returns: 1 if the queue is empty
- */
-
-static inline int queue_empty(struct gfs2_glock *gl, struct list_head *head)
-{
- int empty;
- spin_lock(&gl->gl_spin);
- empty = list_empty(head);
- spin_unlock(&gl->gl_spin);
- return empty;
-}
-
-/**
* search_bucket() - Find struct gfs2_glock by lock number
* @bucket: the bucket to search
* @name: The lock name
@@ -395,11 +371,6 @@ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
gh->gh_flags = flags;
gh->gh_error = 0;
gh->gh_iflags = 0;
- init_completion(&gh->gh_wait);
-
- if (gh->gh_state == LM_ST_EXCLUSIVE)
- gh->gh_flags |= GL_LOCAL_EXCL;
-
gfs2_glock_hold(gl);
}
@@ -417,9 +388,6 @@ void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder *
{
gh->gh_state = state;
gh->gh_flags = flags;
- if (gh->gh_state == LM_ST_EXCLUSIVE)
- gh->gh_flags |= GL_LOCAL_EXCL;
-
gh->gh_iflags &= 1 << HIF_ALLOCED;
gh->gh_ip = (unsigned long)__builtin_return_address(0);
}
@@ -479,6 +447,29 @@ static void gfs2_holder_put(struct gfs2_holder *gh)
kfree(gh);
}
+static void gfs2_holder_dispose_or_wake(struct gfs2_holder *gh)
+{
+ if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) {
+ gfs2_holder_put(gh);
+ return;
+ }
+ clear_bit(HIF_WAIT, &gh->gh_iflags);
+ smp_mb();
+ wake_up_bit(&gh->gh_iflags, HIF_WAIT);
+}
+
+static int holder_wait(void *word)
+{
+ schedule();
+ return 0;
+}
+
+static void wait_on_holder(struct gfs2_holder *gh)
+{
+ might_sleep();
+ wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE);
+}
+
/**
* rq_mutex - process a mutex request in the queue
* @gh: the glock holder
@@ -493,7 +484,9 @@ static int rq_mutex(struct gfs2_holder *gh)
list_del_init(&gh->gh_list);
/* gh->gh_error never examined. */
set_bit(GLF_LOCK, &gl->gl_flags);
- complete(&gh->gh_wait);
+ clear_bit(HIF_WAIT, &gh->gh_iflags);
+ smp_mb();
+ wake_up_bit(&gh->gh_iflags, HIF_WAIT);
return 1;
}
@@ -511,7 +504,6 @@ static int rq_promote(struct gfs2_holder *gh)
{
struct gfs2_glock *gl = gh->gh_gl;
struct gfs2_sbd *sdp = gl->gl_sbd;
- const struct gfs2_glock_operations *glops = gl->gl_ops;
if (!relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) {
if (list_empty(&gl->gl_holders)) {
@@ -526,7 +518,7 @@ static int rq_promote(struct gfs2_holder *gh)
gfs2_reclaim_glock(sdp);
}
- glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags);
+ gfs2_glock_xmote_th(gh);
spin_lock(&gl->gl_spin);
}
return 1;
@@ -537,11 +529,11 @@ static int rq_promote(struct gfs2_holder *gh)
set_bit(GLF_LOCK, &gl->gl_flags);
} else {
struct gfs2_holder *next_gh;
- if (gh->gh_flags & GL_LOCAL_EXCL)
+ if (gh->gh_state == LM_ST_EXCLUSIVE)
return 1;
next_gh = list_entry(gl->gl_holders.next, struct gfs2_holder,
gh_list);
- if (next_gh->gh_flags & GL_LOCAL_EXCL)
+ if (next_gh->gh_state == LM_ST_EXCLUSIVE)
return 1;
}
@@ -549,7 +541,7 @@ static int rq_promote(struct gfs2_holder *gh)
gh->gh_error = 0;
set_bit(HIF_HOLDER, &gh->gh_iflags);
- complete(&gh->gh_wait);
+ gfs2_holder_dispose_or_wake(gh);
return 0;
}
@@ -564,7 +556,6 @@ static int rq_promote(struct gfs2_holder *gh)
static int rq_demote(struct gfs2_holder *gh)
{
struct gfs2_glock *gl = gh->gh_gl;
- const struct gfs2_glock_operations *glops = gl->gl_ops;
if (!list_empty(&gl->gl_holders))
return 1;
@@ -573,10 +564,7 @@ static int rq_demote(struct gfs2_holder *gh)
list_del_init(&gh->gh_list);
gh->gh_error = 0;
spin_unlock(&gl->gl_spin);
- if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
- gfs2_holder_put(gh);
- else
- complete(&gh->gh_wait);
+ gfs2_holder_dispose_or_wake(gh);
spin_lock(&gl->gl_spin);
} else {
gl->gl_req_gh = gh;
@@ -585,9 +573,9 @@ static int rq_demote(struct gfs2_holder *gh)
if (gh->gh_state == LM_ST_UNLOCKED ||
gl->gl_state != LM_ST_EXCLUSIVE)
- glops->go_drop_th(gl);
+ gfs2_glock_drop_th(gl);
else
- glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags);
+ gfs2_glock_xmote_th(gh);
spin_lock(&gl->gl_spin);
}
@@ -596,30 +584,6 @@ static int rq_demote(struct gfs2_holder *gh)
}
/**
- * rq_greedy - process a queued request to drop greedy status
- * @gh: the glock holder
- *
- * Returns: 1 if the queue is blocked
- */
-
-static int rq_greedy(struct gfs2_holder *gh)
-{
- struct gfs2_glock *gl = gh->gh_gl;
-
- list_del_init(&gh->gh_list);
- /* gh->gh_error never examined. */
- clear_bit(GLF_GREEDY, &gl->gl_flags);
- spin_unlock(&gl->gl_spin);
-
- gfs2_holder_uninit(gh);
- kfree(container_of(gh, struct greedy, gr_gh));
-
- spin_lock(&gl->gl_spin);
-
- return 0;
-}
-
-/**
* run_queue - process holder structures on a glock
* @gl: the glock
*
@@ -649,8 +613,6 @@ static void run_queue(struct gfs2_glock *gl)
if (test_bit(HIF_DEMOTE, &gh->gh_iflags))
blocked = rq_demote(gh);
- else if (test_bit(HIF_GREEDY, &gh->gh_iflags))
- blocked = rq_greedy(gh);
else
gfs2_assert_warn(gl->gl_sbd, 0);
@@ -684,6 +646,8 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl)
gfs2_holder_init(gl, 0, 0, &gh);
set_bit(HIF_MUTEX, &gh.gh_iflags);
+ if (test_and_set_bit(HIF_WAIT, &gh.gh_iflags))
+ BUG();
spin_lock(&gl->gl_spin);
if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
@@ -691,11 +655,13 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl)
} else {
gl->gl_owner = current;
gl->gl_ip = (unsigned long)__builtin_return_address(0);
- complete(&gh.gh_wait);
+ clear_bit(HIF_WAIT, &gh.gh_iflags);
+ smp_mb();
+ wake_up_bit(&gh.gh_iflags, HIF_WAIT);
}
spin_unlock(&gl->gl_spin);
- wait_for_completion(&gh.gh_wait);
+ wait_on_holder(&gh);
gfs2_holder_uninit(&gh);
}
@@ -774,6 +740,7 @@ restart:
return;
set_bit(HIF_DEMOTE, &new_gh->gh_iflags);
set_bit(HIF_DEALLOC, &new_gh->gh_iflags);
+ set_bit(HIF_WAIT, &new_gh->gh_iflags);
goto restart;
}
@@ -825,7 +792,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
int op_done = 1;
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
- gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
+ gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
gfs2_assert_warn(sdp, !(ret & LM_OUT_ASYNC));
state_change(gl, ret & LM_OUT_ST_MASK);
@@ -908,12 +875,8 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
gfs2_glock_put(gl);
- if (gh) {
- if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
- gfs2_holder_put(gh);
- else
- complete(&gh->gh_wait);
- }
+ if (gh)
+ gfs2_holder_dispose_or_wake(gh);
}
/**
@@ -924,23 +887,26 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
*
*/
-void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags)
+void gfs2_glock_xmote_th(struct gfs2_holder *gh)
{
+ struct gfs2_glock *gl = gh->gh_gl;
struct gfs2_sbd *sdp = gl->gl_sbd;
+ int flags = gh->gh_flags;
+ unsigned state = gh->gh_state;
const struct gfs2_glock_operations *glops = gl->gl_ops;
int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB |
LM_FLAG_NOEXP | LM_FLAG_ANY |
LM_FLAG_PRIORITY);
unsigned int lck_ret;
+ if (glops->go_xmote_th)
+ glops->go_xmote_th(gl);
+
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
- gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
+ gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
gfs2_assert_warn(sdp, state != LM_ST_UNLOCKED);
gfs2_assert_warn(sdp, state != gl->gl_state);
- if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync)
- glops->go_sync(gl);
-
gfs2_glock_hold(gl);
gl->gl_req_bh = xmote_bh;
@@ -971,10 +937,8 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
const struct gfs2_glock_operations *glops = gl->gl_ops;
struct gfs2_holder *gh = gl->gl_req_gh;
- clear_bit(GLF_PREFETCH, &gl->gl_flags);
-
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
- gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
+ gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
gfs2_assert_warn(sdp, !ret);
state_change(gl, LM_ST_UNLOCKED);
@@ -1001,12 +965,8 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
gfs2_glock_put(gl);
- if (gh) {
- if (test_bit(HIF_DEALLOC, &gh->gh_iflags))
- gfs2_holder_put(gh);
- else
- complete(&gh->gh_wait);
- }
+ if (gh)
+ gfs2_holder_dispose_or_wake(gh);
}
/**
@@ -1015,19 +975,19 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
*
*/
-void gfs2_glock_drop_th(struct gfs2_glock *gl)
+static void gfs2_glock_drop_th(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
const struct gfs2_glock_operations *glops = gl->gl_ops;
unsigned int ret;
+ if (glops->go_drop_th)
+ glops->go_drop_th(gl);
+
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
- gfs2_assert_warn(sdp, queue_empty(gl, &gl->gl_holders));
+ gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
gfs2_assert_warn(sdp, gl->gl_state != LM_ST_UNLOCKED);
- if (gl->gl_state == LM_ST_EXCLUSIVE && glops->go_sync)
- glops->go_sync(gl);
-
gfs2_glock_hold(gl);
gl->gl_req_bh = drop_bh;
@@ -1107,8 +1067,7 @@ static int glock_wait_internal(struct gfs2_holder *gh)
if (gh->gh_flags & LM_FLAG_PRIORITY)
do_cancels(gh);
- wait_for_completion(&gh->gh_wait);
-
+ wait_on_holder(gh);
if (gh->gh_error)
return gh->gh_error;
@@ -1164,6 +1123,8 @@ static void add_to_queue(struct gfs2_holder *gh)
struct gfs2_holder *existing;
BUG_ON(!gh->gh_owner);
+ if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags))
+ BUG();
existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner);
if (existing) {
@@ -1227,8 +1188,6 @@ restart:
}
}
- clear_bit(GLF_PREFETCH, &gl->gl_flags);
-
return error;
}
@@ -1321,98 +1280,6 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
}
/**
- * gfs2_glock_prefetch - Try to prefetch a glock
- * @gl: the glock
- * @state: the state to prefetch in
- * @flags: flags passed to go_xmote_th()
- *
- */
-
-static void gfs2_glock_prefetch(struct gfs2_glock *gl, unsigned int state,
- int flags)
-{
- const struct gfs2_glock_operations *glops = gl->gl_ops;
-
- spin_lock(&gl->gl_spin);
-
- if (test_bit(GLF_LOCK, &gl->gl_flags) || !list_empty(&gl->gl_holders) ||
- !list_empty(&gl->gl_waiters1) || !list_empty(&gl->gl_waiters2) ||
- !list_empty(&gl->gl_waiters3) ||
- relaxed_state_ok(gl->gl_state, state, flags)) {
- spin_unlock(&gl->gl_spin);
- return;
- }
-
- set_bit(GLF_PREFETCH, &gl->gl_flags);
- set_bit(GLF_LOCK, &gl->gl_flags);
- spin_unlock(&gl->gl_spin);
-
- glops->go_xmote_th(gl, state, flags);
-}
-
-static void greedy_work(struct work_struct *work)
-{
- struct greedy *gr = container_of(work, struct greedy, gr_work.work);
- struct gfs2_holder *gh = &gr->gr_gh;
- struct gfs2_glock *gl = gh->gh_gl;
- const struct gfs2_glock_operations *glops = gl->gl_ops;
-
- clear_bit(GLF_SKIP_WAITERS2, &gl->gl_flags);
-
- if (glops->go_greedy)
- glops->go_greedy(gl);
-
- spin_lock(&gl->gl_spin);
-
- if (list_empty(&gl->gl_waiters2)) {
- clear_bit(GLF_GREEDY, &gl->gl_flags);
- spin_unlock(&gl->gl_spin);
- gfs2_holder_uninit(gh);
- kfree(gr);
- } else {
- gfs2_glock_hold(gl);
- list_add_tail(&gh->gh_list, &gl->gl_waiters2);
- run_queue(gl);
- spin_unlock(&gl->gl_spin);
- gfs2_glock_put(gl);
- }
-}
-
-/**
- * gfs2_glock_be_greedy -
- * @gl:
- * @time:
- *
- * Returns: 0 if go_greedy will be called, 1 otherwise
- */
-
-int gfs2_glock_be_greedy(struct gfs2_glock *gl, unsigned int time)
-{
- struct greedy *gr;
- struct gfs2_holder *gh;
-
- if (!time || gl->gl_sbd->sd_args.ar_localcaching ||
- test_and_set_bit(GLF_GREEDY, &gl->gl_flags))
- return 1;
-
- gr = kmalloc(sizeof(struct greedy), GFP_KERNEL);
- if (!gr) {
- clear_bit(GLF_GREEDY, &gl->gl_flags);
- return 1;
- }
- gh = &gr->gr_gh;
-
- gfs2_holder_init(gl, 0, 0, gh);
- set_bit(HIF_GREEDY, &gh->gh_iflags);
- INIT_DELAYED_WORK(&gr->gr_work, greedy_work);
-
- set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags);
- schedule_delayed_work(&gr->gr_work, time);
-
- return 0;
-}
-
-/**
* gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it
* @gh: the holder structure
*
@@ -1470,10 +1337,7 @@ static int glock_compare(const void *arg_a, const void *arg_b)
return 1;
if (a->ln_number < b->ln_number)
return -1;
- if (gh_a->gh_state == LM_ST_SHARED && gh_b->gh_state == LM_ST_EXCLUSIVE)
- return 1;
- if (!(gh_a->gh_flags & GL_LOCAL_EXCL) && (gh_b->gh_flags & GL_LOCAL_EXCL))
- return 1;
+ BUG_ON(gh_a->gh_gl->gl_ops->go_type == gh_b->gh_gl->gl_ops->go_type);
return 0;
}
@@ -1618,34 +1482,6 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
}
/**
- * gfs2_glock_prefetch_num - prefetch a glock based on lock number
- * @sdp: the filesystem
- * @number: the lock number
- * @glops: the glock operations for the type of glock
- * @state: the state to acquire the glock in
- * @flags: modifier flags for the aquisition
- *
- * Returns: errno
- */
-
-void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, u64 number,
- const struct gfs2_glock_operations *glops,
- unsigned int state, int flags)
-{
- struct gfs2_glock *gl;
- int error;
-
- if (atomic_read(&sdp->sd_reclaim_count) <
- gfs2_tune_get(sdp, gt_reclaim_limit)) {
- error = gfs2_glock_get(sdp, number, glops, CREATE, &gl);
- if (!error) {
- gfs2_glock_prefetch(gl, state, flags);
- gfs2_glock_put(gl);
- }
- }
-}
-
-/**
* gfs2_lvb_hold - attach a LVB from a glock
* @gl: The glock in question
*
@@ -1703,8 +1539,6 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name,
if (!gl)
return;
- if (gl->gl_ops->go_callback)
- gl->gl_ops->go_callback(gl, state);
handle_callback(gl, state);
spin_lock(&gl->gl_spin);
@@ -1746,12 +1580,14 @@ void gfs2_glock_cb(void *cb_data, unsigned int type, void *data)
struct lm_async_cb *async = data;
struct gfs2_glock *gl;
+ down_read(&gfs2_umount_flush_sem);
gl = gfs2_glock_find(sdp, &async->lc_name);
if (gfs2_assert_warn(sdp, gl))
return;
if (!gfs2_assert_warn(sdp, gl->gl_req_bh))
gl->gl_req_bh(gl, async->lc_ret