Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7b08fc620109c2f66575e9ae884f45c37933ea18
Commit:     7b08fc620109c2f66575e9ae884f45c37933ea18
Parent:     afd0942d98f74296b74993739e41d2ca7cb9fd5a
Author:     Steven Whitehouse <[EMAIL PROTECTED]>
AuthorDate: Tue Jul 24 13:53:36 2007 +0100
Committer:  Steven Whitehouse <[EMAIL PROTECTED]>
CommitDate: Wed Oct 10 08:54:49 2007 +0100

    [GFS2] Fix an oops in glock dumping
    
    This fixes an oops which was occurring during glock dumping due to the
    seq file code not taking a reference to the glock. Also this fixes a
    memory leak which occurred in certain cases, in turn preventing the
    filesystem from unmounting.
    
    Signed-off-by: Steven Whitehouse <[EMAIL PROTECTED]>
---
 fs/gfs2/glock.c |   73 ++++++++++++++++++++++++++----------------------------
 1 files changed, 35 insertions(+), 38 deletions(-)

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index d403fd7..e4bc8ae 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -46,7 +46,6 @@ struct glock_iter {
        int hash;                     /* hash bucket index         */
        struct gfs2_sbd *sdp;         /* incore superblock         */
        struct gfs2_glock *gl;        /* current glock struct      */
-       struct hlist_head *hb_list;   /* current hash bucket ptr   */
        struct seq_file *seq;         /* sequence file for debugfs */
        char string[512];             /* scratch space             */
 };
@@ -1990,47 +1989,38 @@ int __init gfs2_glock_init(void)
 
 static int gfs2_glock_iter_next(struct glock_iter *gi)
 {
+       struct gfs2_glock *gl;
+
        read_lock(gl_lock_addr(gi->hash));
-       while (1) {
-               if (!gi->hb_list) {  /* If we don't have a hash bucket yet */
-                       gi->hb_list = &gl_hash_table[gi->hash].hb_list;
-                       if (hlist_empty(gi->hb_list)) {
-                               read_unlock(gl_lock_addr(gi->hash));
-                               gi->hash++;
-                               read_lock(gl_lock_addr(gi->hash));
-                               gi->hb_list = NULL;
-                               if (gi->hash >= GFS2_GL_HASH_SIZE) {
-                                       read_unlock(gl_lock_addr(gi->hash));
-                                       return 1;
-                               }
-                               else
-                                       continue;
-                       }
-                       if (!hlist_empty(gi->hb_list)) {
-                               gi->gl = list_entry(gi->hb_list->first,
-                                                   struct gfs2_glock,
-                                                   gl_list);
-                       }
-               } else {
-                       if (gi->gl->gl_list.next == NULL) {
-                               read_unlock(gl_lock_addr(gi->hash));
-                               gi->hash++;
-                               read_lock(gl_lock_addr(gi->hash));
-                               gi->hb_list = NULL;
-                               continue;
-                       }
-                       gi->gl = list_entry(gi->gl->gl_list.next,
-                                           struct gfs2_glock, gl_list);
-               }
+       gl = gi->gl;
+       if (gl) {
+               gi->gl = hlist_entry(gl->gl_list.next, struct gfs2_glock,
+                                    gl_list);
                if (gi->gl)
-                       break;
+                       gfs2_glock_hold(gi->gl);
        }
        read_unlock(gl_lock_addr(gi->hash));
+       if (gl)
+               gfs2_glock_put(gl);
+
+       while(gi->gl == NULL) {
+               gi->hash++;
+               if (gi->hash >= GFS2_GL_HASH_SIZE)
+                       return 1;
+               read_lock(gl_lock_addr(gi->hash));
+               gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
+                                    struct gfs2_glock, gl_list);
+               if (gi->gl)
+                       gfs2_glock_hold(gi->gl);
+               read_unlock(gl_lock_addr(gi->hash));
+       }
        return 0;
 }
 
 static void gfs2_glock_iter_free(struct glock_iter *gi)
 {
+       if (gi->gl)
+               gfs2_glock_put(gi->gl);
        kfree(gi);
 }
 
@@ -2044,12 +2034,17 @@ static struct glock_iter *gfs2_glock_iter_init(struct 
gfs2_sbd *sdp)
 
        gi->sdp = sdp;
        gi->hash = 0;
-       gi->gl = NULL;
-       gi->hb_list = NULL;
        gi->seq = NULL;
        memset(gi->string, 0, sizeof(gi->string));
 
-       if (gfs2_glock_iter_next(gi)) {
+       read_lock(gl_lock_addr(gi->hash));
+       gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
+                            struct gfs2_glock, gl_list);
+       if (gi->gl)
+               gfs2_glock_hold(gi->gl);
+       read_unlock(gl_lock_addr(gi->hash));
+
+       if (!gi->gl && gfs2_glock_iter_next(gi)) {
                gfs2_glock_iter_free(gi);
                return NULL;
        }
@@ -2066,7 +2061,7 @@ static void *gfs2_glock_seq_start(struct seq_file *file, 
loff_t *pos)
        if (!gi)
                return NULL;
 
-       while (n--) {
+       while(n--) {
                if (gfs2_glock_iter_next(gi)) {
                        gfs2_glock_iter_free(gi);
                        return NULL;
@@ -2093,7 +2088,9 @@ static void *gfs2_glock_seq_next(struct seq_file *file, 
void *iter_ptr,
 
 static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr)
 {
-       /* nothing for now */
+       struct glock_iter *gi = iter_ptr;
+       if (gi)
+               gfs2_glock_iter_free(gi);
 }
 
 static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to