]> err.no Git - linux-2.6/blobdiff - fs/gfs2/glock.c
Merge branch 'linus' into x86/kconfig
[linux-2.6] / fs / gfs2 / glock.c
index a8387e0b50684f5993184ab10cc4cb92439e6206..d636b3e80f5d26dda0a0f799011da225c5ef24ba 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -35,7 +35,6 @@
 #include "glock.h"
 #include "glops.h"
 #include "inode.h"
-#include "lm.h"
 #include "lops.h"
 #include "meta_io.h"
 #include "quota.h"
@@ -183,7 +182,8 @@ static void glock_free(struct gfs2_glock *gl)
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct inode *aspace = gl->gl_aspace;
 
-       gfs2_lm_put_lock(sdp, gl->gl_lock);
+       if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+               sdp->sd_lockstruct.ls_ops->lm_put_lock(gl->gl_lock);
 
        if (aspace)
                gfs2_aspace_put(aspace);
@@ -293,6 +293,16 @@ static void glock_work_func(struct work_struct *work)
        gfs2_glock_put(gl);
 }
 
+static int gfs2_lm_get_lock(struct gfs2_sbd *sdp, struct lm_lockname *name,
+                    void **lockp)
+{
+       int error = -EIO;
+       if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+               error = sdp->sd_lockstruct.ls_ops->lm_get_lock(
+                               sdp->sd_lockstruct.ls_lockspace, name, lockp);
+       return error;
+}
+
 /**
  * gfs2_glock_get() - Get a glock, or create one if one doesn't exist
  * @sdp: The GFS2 superblock
@@ -338,7 +348,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
        gl->gl_ip = 0;
        gl->gl_ops = glops;
        gl->gl_req_gh = NULL;
-       gl->gl_vn = 0;
        gl->gl_stamp = jiffies;
        gl->gl_tchange = jiffies;
        gl->gl_object = NULL;
@@ -755,7 +764,6 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
 static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
 {
        struct gfs2_sbd *sdp = gl->gl_sbd;
-       const struct gfs2_glock_operations *glops = gl->gl_ops;
        struct gfs2_holder *gh = gl->gl_req_gh;
 
        gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
@@ -764,26 +772,20 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
 
        state_change(gl, LM_ST_UNLOCKED);
 
-       if (glops->go_inval)
-               glops->go_inval(gl, DIO_METADATA);
-
-       if (gh) {
+       if (test_and_clear_bit(GLF_CONV_DEADLK, &gl->gl_flags)) {
                spin_lock(&gl->gl_spin);
-               list_del_init(&gh->gh_list);
                gh->gh_error = 0;
                spin_unlock(&gl->gl_spin);
+               gfs2_glock_xmote_th(gl, gl->gl_req_gh);
+               gfs2_glock_put(gl);
+               return;
        }
 
        spin_lock(&gl->gl_spin);
        gfs2_demote_wake(gl);
-       gl->gl_req_gh = NULL;
        clear_bit(GLF_LOCK, &gl->gl_flags);
        spin_unlock(&gl->gl_spin);
-
        gfs2_glock_put(gl);
-
-       if (gh)
-               gfs2_holder_wake(gh);
 }
 
 /**
@@ -798,10 +800,9 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
        struct gfs2_sbd *sdp = gl->gl_sbd;
        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;
 
-       if ((ret & LM_OUT_ST_MASK) == LM_ST_UNLOCKED) {
+       if (!gh && (ret & LM_OUT_ST_MASK) == LM_ST_UNLOCKED) {
                drop_bh(gl, ret);
                return;
        }
@@ -812,16 +813,6 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
 
        state_change(gl, ret & LM_OUT_ST_MASK);
 
-       if (prev_state != LM_ST_UNLOCKED && !(ret & LM_OUT_CACHEABLE)) {
-               if (glops->go_inval)
-                       glops->go_inval(gl, DIO_METADATA);
-       } else if (gl->gl_state == LM_ST_DEFERRED) {
-               /* We might not want to do this here.
-                  Look at moving to the inode glops. */
-               if (glops->go_inval)
-                       glops->go_inval(gl, 0);
-       }
-
        /*  Deal with each possible exit condition  */
 
        if (!gh) {
@@ -841,6 +832,14 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
                }
        } else {
                spin_lock(&gl->gl_spin);
+               if (ret & LM_OUT_CONV_DEADLK) {
+                       gh->gh_error = 0;
+                       set_bit(GLF_CONV_DEADLK, &gl->gl_flags);
+                       spin_unlock(&gl->gl_spin);
+                       gfs2_glock_drop_th(gl);
+                       gfs2_glock_put(gl);
+                       return;
+               }
                list_del_init(&gh->gh_list);
                gh->gh_error = -EIO;
                if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 
@@ -882,6 +881,17 @@ out:
                gfs2_holder_wake(gh);
 }
 
+static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
+                                unsigned int cur_state, unsigned int req_state,
+                                unsigned int flags)
+{
+       int ret = 0;
+       if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+               ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock, cur_state,
+                                                        req_state, flags);
+       return ret;
+}
+
 /**
  * gfs2_glock_xmote_th - Call into the lock module to acquire or change a glock
  * @gl: The glock in question
@@ -903,6 +913,8 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
 
        if (glops->go_xmote_th)
                glops->go_xmote_th(gl);
+       if (state == LM_ST_DEFERRED && glops->go_inval)
+               glops->go_inval(gl, DIO_METADATA);
 
        gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
        gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
@@ -922,6 +934,15 @@ static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh)
                xmote_bh(gl, lck_ret);
 }
 
+static unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock,
+                                  unsigned int cur_state)
+{
+       int ret = 0;
+       if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+               ret =  sdp->sd_lockstruct.ls_ops->lm_unlock(lock, cur_state);
+       return ret;
+}
+
 /**
  * gfs2_glock_drop_th - call into the lock module to unlock a lock
  * @gl: the glock
@@ -936,6 +957,8 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
 
        if (glops->go_xmote_th)
                glops->go_xmote_th(gl);
+       if (glops->go_inval)
+               glops->go_inval(gl, DIO_METADATA);
 
        gfs2_assert_warn(sdp, test_bit(GLF_LOCK, &gl->gl_flags));
        gfs2_assert_warn(sdp, list_empty(&gl->gl_holders));
@@ -964,6 +987,7 @@ static void gfs2_glock_drop_th(struct gfs2_glock *gl)
 static void do_cancels(struct gfs2_holder *gh)
 {
        struct gfs2_glock *gl = gh->gh_gl;
+       struct gfs2_sbd *sdp = gl->gl_sbd;
 
        spin_lock(&gl->gl_spin);
 
@@ -972,7 +996,8 @@ static void do_cancels(struct gfs2_holder *gh)
               !list_empty(&gh->gh_list)) {
                if (!(gl->gl_req_gh && (gl->gl_req_gh->gh_flags & GL_NOCANCEL))) {
                        spin_unlock(&gl->gl_spin);
-                       gfs2_lm_cancel(gl->gl_sbd, gl->gl_lock);
+                       if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+                               sdp->sd_lockstruct.ls_ops->lm_cancel(gl->gl_lock);
                        msleep(100);
                        spin_lock(&gl->gl_spin);
                } else {
@@ -1426,6 +1451,14 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
                gfs2_glock_dq_uninit(&ghs[x]);
 }
 
+static int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp)
+{
+       int error = -EIO;
+       if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+               error = sdp->sd_lockstruct.ls_ops->lm_hold_lvb(lock, lvbp);
+       return error;
+}
+
 /**
  * gfs2_lvb_hold - attach a LVB from a glock
  * @gl: The glock in question
@@ -1461,12 +1494,15 @@ int gfs2_lvb_hold(struct gfs2_glock *gl)
 
 void gfs2_lvb_unhold(struct gfs2_glock *gl)
 {
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+
        gfs2_glock_hold(gl);
        gfs2_glmutex_lock(gl);
 
        gfs2_assert(gl->gl_sbd, atomic_read(&gl->gl_lvb_count) > 0);
        if (atomic_dec_and_test(&gl->gl_lvb_count)) {
-               gfs2_lm_unhold_lvb(gl->gl_sbd, gl->gl_lock, gl->gl_lvb);
+               if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+                       sdp->sd_lockstruct.ls_ops->lm_unhold_lvb(gl->gl_lock, gl->gl_lvb);
                gl->gl_lvb = NULL;
                gfs2_glock_put(gl);
        }