[GFS2] Update copyright, tidy up incore.h
[linux-block.git] / fs / gfs2 / glock.c
index 7f362d0c3f7aac5233f95d18386a79a71571b5a1..989f4f78f9be7432b0b914eb2d6b16d2463986ba 100644 (file)
@@ -4,7 +4,7 @@
  *
  * 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>
@@ -83,7 +83,7 @@ static inline int relaxed_state_ok(unsigned int actual, unsigned requested,
  * 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;
 
@@ -150,12 +150,9 @@ static void kill_glock(struct kref *kref)
 
 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);
@@ -166,8 +163,7 @@ int gfs2_glock_put(struct gfs2_glock *gl)
                goto out;
        }
        write_unlock(&bucket->hb_lock);
- out:
-       mutex_unlock(&sdp->sd_invalidate_inodes_mutex);
+out:
        return rv;
 }
 
@@ -204,7 +200,8 @@ static inline int queue_empty(struct gfs2_glock *gl, struct list_head *head)
  */
 
 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;
 
@@ -213,6 +210,8 @@ static struct gfs2_glock *search_bucket(struct gfs2_gl_hash_bucket *bucket,
                        continue;
                if (!lm_name_equal(&gl->gl_name, name))
                        continue;
+               if (gl->gl_sbd != sdp)
+                       continue;
 
                kref_get(&gl->gl_ref);
 
@@ -231,13 +230,13 @@ static struct gfs2_glock *search_bucket(struct gfs2_gl_hash_bucket *bucket,
  */
 
 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;
@@ -257,7 +256,7 @@ static struct gfs2_glock *gfs2_glock_find(struct gfs2_sbd *sdp,
  */
 
 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;
@@ -270,7 +269,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, uint64_t number,
        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) {
@@ -282,37 +281,27 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, uint64_t number,
        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;
@@ -325,7 +314,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, uint64_t number,
                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);
@@ -339,13 +328,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, uint64_t number,
 
        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;
 }
 
@@ -485,7 +472,7 @@ static int rq_promote(struct gfs2_holder *gh)
 {
        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)) {
@@ -500,9 +487,7 @@ static int rq_promote(struct gfs2_holder *gh)
                                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;
@@ -540,7 +525,7 @@ static int rq_promote(struct gfs2_holder *gh)
 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;
@@ -772,6 +757,7 @@ void gfs2_glock_inode_squish(struct inode *inode)
        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);
 }
 
@@ -809,7 +795,7 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
 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;
@@ -919,7 +905,7 @@ 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)
 {
        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);
@@ -939,8 +925,7 @@ void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags)
        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;
@@ -964,7 +949,7 @@ void gfs2_glock_xmote_th(struct gfs2_glock *gl, unsigned int state, int flags)
 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);
@@ -1014,7 +999,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
 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));
@@ -1023,8 +1008,7 @@ void gfs2_glock_drop_th(struct gfs2_glock *gl)
 
        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);
@@ -1085,7 +1069,7 @@ static int glock_wait_internal(struct gfs2_holder *gh)
 {
        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;
@@ -1169,7 +1153,13 @@ static void add_to_queue(struct gfs2_holder *gh)
        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();
        }
 
@@ -1292,10 +1282,7 @@ int gfs2_glock_wait(struct gfs2_holder *gh)
 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);
@@ -1311,11 +1298,6 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
                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);
@@ -1337,7 +1319,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
 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);
 
@@ -1363,7 +1345,7 @@ static void greedy_work(void *data)
        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);
 
@@ -1445,8 +1427,8 @@ void gfs2_glock_dq_uninit(struct gfs2_holder *gh)
  */
 
 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;
@@ -1643,7 +1625,7 @@ void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
  */
 
 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;
@@ -1825,7 +1807,7 @@ void gfs2_iopen_go_callback(struct gfs2_glock *io_gl, unsigned int state)
 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))
@@ -1964,25 +1946,18 @@ static int examine_bucket(glock_examiner examiner, struct gfs2_sbd *sdp,
 
 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:
@@ -2076,16 +2051,7 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait)
                        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);
        }
 }
@@ -2173,7 +2139,9 @@ static int dump_glock(struct gfs2_glock *gl)
 
        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++)
@@ -2193,8 +2161,9 @@ static int dump_glock(struct gfs2_glock *gl)
        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));