*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License v.2.
+ * of the GNU General Public License version 2.
*/
#include <linux/sched.h>
* Returns: The number of the corresponding hash bucket
*/
-static unsigned int gl_hash(struct lm_lockname *name)
+static unsigned int gl_hash(const struct lm_lockname *name)
{
unsigned int h;
int gfs2_glock_put(struct gfs2_glock *gl)
{
- struct gfs2_sbd *sdp = gl->gl_sbd;
struct gfs2_gl_hash_bucket *bucket = gl->gl_bucket;
int rv = 0;
- mutex_lock(&sdp->sd_invalidate_inodes_mutex);
-
write_lock(&bucket->hb_lock);
if (kref_put(&gl->gl_ref, kill_glock)) {
list_del_init(&gl->gl_list);
goto out;
}
write_unlock(&bucket->hb_lock);
- out:
- mutex_unlock(&sdp->sd_invalidate_inodes_mutex);
+out:
return rv;
}
*/
static struct gfs2_glock *search_bucket(struct gfs2_gl_hash_bucket *bucket,
- struct lm_lockname *name)
+ const struct gfs2_sbd *sdp,
+ const struct lm_lockname *name)
{
struct gfs2_glock *gl;
continue;
if (!lm_name_equal(&gl->gl_name, name))
continue;
+ if (gl->gl_sbd != sdp)
+ continue;
kref_get(&gl->gl_ref);
*/
static struct gfs2_glock *gfs2_glock_find(struct gfs2_sbd *sdp,
- struct lm_lockname *name)
+ const struct lm_lockname *name)
{
struct gfs2_gl_hash_bucket *bucket = &sdp->sd_gl_hash[gl_hash(name)];
struct gfs2_glock *gl;
read_lock(&bucket->hb_lock);
- gl = search_bucket(bucket, name);
+ gl = search_bucket(bucket, sdp, name);
read_unlock(&bucket->hb_lock);
return gl;
*/
int gfs2_glock_get(struct gfs2_sbd *sdp, uint64_t number,
- struct gfs2_glock_operations *glops, int create,
+ const struct gfs2_glock_operations *glops, int create,
struct gfs2_glock **glp)
{
struct lm_lockname name;
bucket = &sdp->sd_gl_hash[gl_hash(&name)];
read_lock(&bucket->hb_lock);
- gl = search_bucket(bucket, &name);
+ gl = search_bucket(bucket, sdp, &name);
read_unlock(&bucket->hb_lock);
if (gl || !create) {
if (!gl)
return -ENOMEM;
- memset(gl, 0, sizeof(struct gfs2_glock));
-
- INIT_LIST_HEAD(&gl->gl_list);
+ gl->gl_flags = 0;
gl->gl_name = name;
kref_init(&gl->gl_ref);
-
- spin_lock_init(&gl->gl_spin);
-
gl->gl_state = LM_ST_UNLOCKED;
gl->gl_owner = NULL;
gl->gl_ip = 0;
- INIT_LIST_HEAD(&gl->gl_holders);
- INIT_LIST_HEAD(&gl->gl_waiters1);
- INIT_LIST_HEAD(&gl->gl_waiters2);
- INIT_LIST_HEAD(&gl->gl_waiters3);
-
gl->gl_ops = glops;
-
+ gl->gl_req_gh = NULL;
+ gl->gl_req_bh = NULL;
+ gl->gl_vn = 0;
+ gl->gl_stamp = jiffies;
+ gl->gl_object = NULL;
gl->gl_bucket = bucket;
- INIT_LIST_HEAD(&gl->gl_reclaim);
-
gl->gl_sbd = sdp;
-
+ gl->gl_aspace = NULL;
lops_init_le(&gl->gl_le, &gfs2_glock_lops);
- INIT_LIST_HEAD(&gl->gl_ail_list);
/* If this glock protects actual on-disk data or metadata blocks,
create a VFS inode to manage the pages/buffers holding them. */
if (glops == &gfs2_inode_glops ||
- glops == &gfs2_rgrp_glops ||
- glops == &gfs2_meta_glops) {
+ glops == &gfs2_rgrp_glops) {
gl->gl_aspace = gfs2_aspace_get(sdp);
if (!gl->gl_aspace) {
error = -ENOMEM;
goto fail_aspace;
write_lock(&bucket->hb_lock);
- tmp = search_bucket(bucket, &name);
+ tmp = search_bucket(bucket, sdp, &name);
if (tmp) {
write_unlock(&bucket->hb_lock);
glock_free(gl);
return 0;
- fail_aspace:
+fail_aspace:
if (gl->gl_aspace)
gfs2_aspace_put(gl->gl_aspace);
-
- fail:
+fail:
kmem_cache_free(gfs2_glock_cachep, gl);
-
return error;
}
{
struct gfs2_glock *gl = gh->gh_gl;
struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ 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)) {
gfs2_reclaim_glock(sdp);
}
- glops->go_xmote_th(gl, gh->gh_state,
- gh->gh_flags);
-
+ glops->go_xmote_th(gl, gh->gh_state, gh->gh_flags);
spin_lock(&gl->gl_spin);
}
return 1;
static int rq_demote(struct gfs2_holder *gh)
{
struct gfs2_glock *gl = gh->gh_gl;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
if (!list_empty(&gl->gl_holders))
return 1;
list_add_tail(&gh.gh_list, &gl->gl_waiters2);
run_queue(gl);
spin_unlock(&gl->gl_spin);
+ wait_for_completion(&gh.gh_wait);
gfs2_holder_uninit(&gh);
}
static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
struct gfs2_holder *gh = gl->gl_req_gh;
int prev_state = gl->gl_state;
int op_done = 1;
void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ 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);
gfs2_glock_hold(gl);
gl->gl_req_bh = xmote_bh;
- lck_ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, state,
- lck_flags);
+ lck_ret = gfs2_lm_lock(sdp, gl->gl_lock, gl->gl_state, state, lck_flags);
if (gfs2_assert_withdraw(sdp, !(lck_ret & LM_OUT_ERROR)))
return;
static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
struct gfs2_holder *gh = gl->gl_req_gh;
clear_bit(GLF_PREFETCH, &gl->gl_flags);
void gfs2_glock_drop_th(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
unsigned int ret;
gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
if (gl->gl_state == LM_ST_EXCLUSIVE) {
if (glops->go_sync)
- glops->go_sync(gl,
- DIO_METADATA | DIO_DATA | DIO_RELEASE);
+ glops->go_sync(gl, DIO_METADATA | DIO_DATA | DIO_RELEASE);
}
gfs2_glock_hold(gl);
{
struct gfs2_glock *gl = gh->gh_gl;
struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
if (test_bit(HIF_ABORTED, &gh->gh_iflags))
return -EIO;
existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner);
if (existing) {
print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip);
+ printk(KERN_INFO "pid : %d\n", existing->gh_owner->pid);
+ printk(KERN_INFO "lock type : %d lock state : %d\n",
+ existing->gh_gl->gl_name.ln_type, existing->gh_gl->gl_state);
print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip);
+ printk(KERN_INFO "pid : %d\n", gh->gh_owner->pid);
+ printk(KERN_INFO "lock type : %d lock state : %d\n",
+ gl->gl_name.ln_type, gl->gl_state);
BUG();
}
void gfs2_glock_dq(struct gfs2_holder *gh)
{
struct gfs2_glock *gl = gh->gh_gl;
- struct gfs2_glock_operations *glops = gl->gl_ops;
-
- if (gh->gh_flags & GL_SYNC)
- set_bit(GLF_SYNC, &gl->gl_flags);
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
if (gh->gh_flags & GL_NOCACHE)
handle_callback(gl, LM_ST_UNLOCKED);
if (glops->go_unlock)
glops->go_unlock(gh);
- if (test_bit(GLF_SYNC, &gl->gl_flags)) {
- if (glops->go_sync)
- glops->go_sync(gl, DIO_METADATA | DIO_DATA);
- }
-
gl->gl_stamp = jiffies;
spin_lock(&gl->gl_spin);
static void gfs2_glock_prefetch(struct gfs2_glock *gl, unsigned int state,
int flags)
{
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
spin_lock(&gl->gl_spin);
struct greedy *gr = data;
struct gfs2_holder *gh = &gr->gr_gh;
struct gfs2_glock *gl = gh->gh_gl;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
clear_bit(GLF_SKIP_WAITERS2, &gl->gl_flags);
*/
int gfs2_glock_nq_num(struct gfs2_sbd *sdp, uint64_t number,
- struct gfs2_glock_operations *glops, unsigned int state,
- int flags, struct gfs2_holder *gh)
+ const struct gfs2_glock_operations *glops,
+ unsigned int state, int flags, struct gfs2_holder *gh)
{
struct gfs2_glock *gl;
int error;
*/
void gfs2_glock_prefetch_num(struct gfs2_sbd *sdp, uint64_t number,
- struct gfs2_glock_operations *glops,
+ const struct gfs2_glock_operations *glops,
unsigned int state, int flags)
{
struct gfs2_glock *gl;
static int demote_ok(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_glock_operations *glops = gl->gl_ops;
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
int demote = 1;
if (test_bit(GLF_STICKY, &gl->gl_flags))
static void scan_glock(struct gfs2_glock *gl)
{
+ if (gl->gl_ops == &gfs2_inode_glops)
+ goto out;
+
if (gfs2_glmutex_trylock(gl)) {
- if (gl->gl_ops == &gfs2_inode_glops) {
- struct gfs2_inode *ip = gl->gl_object;
- if (ip == NULL) {
- struct gfs2_sbd *sdp = gl->gl_sbd;
- gfs2_assert_withdraw(sdp, gl->gl_state == LM_ST_UNLOCKED);
- goto out_schedule;
- }
- }
if (queue_empty(gl, &gl->gl_holders) &&
gl->gl_state != LM_ST_UNLOCKED &&
demote_ok(gl))
goto out_schedule;
-
gfs2_glmutex_unlock(gl);
}
-
+out:
gfs2_glock_put(gl);
-
return;
out_schedule:
t = jiffies;
}
- /* invalidate_inodes() requires that the sb inodes list
- not change, but an async completion callback for an
- unlock can occur which does glock_put() which
- can call iput() which will change the sb inodes list.
- invalidate_inodes_mutex prevents glock_put()'s during
- an invalidate_inodes() */
-
- mutex_lock(&sdp->sd_invalidate_inodes_mutex);
invalidate_inodes(sdp->sd_vfs);
- mutex_unlock(&sdp->sd_invalidate_inodes_mutex);
msleep(10);
}
}
spin_lock(&gl->gl_spin);
- printk(KERN_INFO "Glock (%u, %llu)\n", gl->gl_name.ln_type,
+ printk(KERN_INFO "Glock 0x%p (%u, %llu)\n",
+ gl,
+ gl->gl_name.ln_type,
(unsigned long long)gl->gl_name.ln_number);
printk(KERN_INFO " gl_flags =");
for (x = 0; x < 32; x++)
printk(KERN_INFO " reclaim = %s\n",
(list_empty(&gl->gl_reclaim)) ? "no" : "yes");
if (gl->gl_aspace)
- printk(KERN_INFO " aspace = %lu\n",
- gl->gl_aspace->i_mapping->nrpages);
+ printk(KERN_INFO " aspace = 0x%p nrpages = %lu\n",
+ gl->gl_aspace,
+ gl->gl_aspace->i_mapping->nrpages);
else
printk(KERN_INFO " aspace = no\n");
printk(KERN_INFO " ail = %d\n", atomic_read(&gl->gl_ail_count));