aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-07-24 08:53:36 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2007-10-10 03:54:49 -0400
commit7b08fc620109c2f66575e9ae884f45c37933ea18 (patch)
tree17fd00263b24dfd88242648a7bbd4de73826daec
parentafd0942d98f74296b74993739e41d2ca7cb9fd5a (diff)
[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 <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/glock.c73
1 files changed, 35 insertions, 38 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index d403fd708075..e4bc8ae561aa 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -46,7 +46,6 @@ struct glock_iter {
46 int hash; /* hash bucket index */ 46 int hash; /* hash bucket index */
47 struct gfs2_sbd *sdp; /* incore superblock */ 47 struct gfs2_sbd *sdp; /* incore superblock */
48 struct gfs2_glock *gl; /* current glock struct */ 48 struct gfs2_glock *gl; /* current glock struct */
49 struct hlist_head *hb_list; /* current hash bucket ptr */
50 struct seq_file *seq; /* sequence file for debugfs */ 49 struct seq_file *seq; /* sequence file for debugfs */
51 char string[512]; /* scratch space */ 50 char string[512]; /* scratch space */
52}; 51};
@@ -1990,47 +1989,38 @@ int __init gfs2_glock_init(void)
1990 1989
1991static int gfs2_glock_iter_next(struct glock_iter *gi) 1990static int gfs2_glock_iter_next(struct glock_iter *gi)
1992{ 1991{
1992 struct gfs2_glock *gl;
1993
1993 read_lock(gl_lock_addr(gi->hash)); 1994 read_lock(gl_lock_addr(gi->hash));
1994 while (1) { 1995 gl = gi->gl;
1995 if (!gi->hb_list) { /* If we don't have a hash bucket yet */ 1996 if (gl) {
1996 gi->hb_list = &gl_hash_table[gi->hash].hb_list; 1997 gi->gl = hlist_entry(gl->gl_list.next, struct gfs2_glock,
1997 if (hlist_empty(gi->hb_list)) { 1998 gl_list);
1998 read_unlock(gl_lock_addr(gi->hash));
1999 gi->hash++;
2000 read_lock(gl_lock_addr(gi->hash));
2001 gi->hb_list = NULL;
2002 if (gi->hash >= GFS2_GL_HASH_SIZE) {
2003 read_unlock(gl_lock_addr(gi->hash));
2004 return 1;
2005 }
2006 else
2007 continue;
2008 }
2009 if (!hlist_empty(gi->hb_list)) {
2010 gi->gl = list_entry(gi->hb_list->first,
2011 struct gfs2_glock,
2012 gl_list);
2013 }
2014 } else {
2015 if (gi->gl->gl_list.next == NULL) {
2016 read_unlock(gl_lock_addr(gi->hash));
2017 gi->hash++;
2018 read_lock(gl_lock_addr(gi->hash));
2019 gi->hb_list = NULL;
2020 continue;
2021 }
2022 gi->gl = list_entry(gi->gl->gl_list.next,
2023 struct gfs2_glock, gl_list);
2024 }
2025 if (gi->gl) 1999 if (gi->gl)
2026 break; 2000 gfs2_glock_hold(gi->gl);
2027 } 2001 }
2028 read_unlock(gl_lock_addr(gi->hash)); 2002 read_unlock(gl_lock_addr(gi->hash));
2003 if (gl)
2004 gfs2_glock_put(gl);
2005
2006 while(gi->gl == NULL) {
2007 gi->hash++;
2008 if (gi->hash >= GFS2_GL_HASH_SIZE)
2009 return 1;
2010 read_lock(gl_lock_addr(gi->hash));
2011 gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
2012 struct gfs2_glock, gl_list);
2013 if (gi->gl)
2014 gfs2_glock_hold(gi->gl);
2015 read_unlock(gl_lock_addr(gi->hash));
2016 }
2029 return 0; 2017 return 0;
2030} 2018}
2031 2019
2032static void gfs2_glock_iter_free(struct glock_iter *gi) 2020static void gfs2_glock_iter_free(struct glock_iter *gi)
2033{ 2021{
2022 if (gi->gl)
2023 gfs2_glock_put(gi->gl);
2034 kfree(gi); 2024 kfree(gi);
2035} 2025}
2036 2026
@@ -2044,12 +2034,17 @@ static struct glock_iter *gfs2_glock_iter_init(struct gfs2_sbd *sdp)
2044 2034
2045 gi->sdp = sdp; 2035 gi->sdp = sdp;
2046 gi->hash = 0; 2036 gi->hash = 0;
2047 gi->gl = NULL;
2048 gi->hb_list = NULL;
2049 gi->seq = NULL; 2037 gi->seq = NULL;
2050 memset(gi->string, 0, sizeof(gi->string)); 2038 memset(gi->string, 0, sizeof(gi->string));
2051 2039
2052 if (gfs2_glock_iter_next(gi)) { 2040 read_lock(gl_lock_addr(gi->hash));
2041 gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
2042 struct gfs2_glock, gl_list);
2043 if (gi->gl)
2044 gfs2_glock_hold(gi->gl);
2045 read_unlock(gl_lock_addr(gi->hash));
2046
2047 if (!gi->gl && gfs2_glock_iter_next(gi)) {
2053 gfs2_glock_iter_free(gi); 2048 gfs2_glock_iter_free(gi);
2054 return NULL; 2049 return NULL;
2055 } 2050 }
@@ -2066,7 +2061,7 @@ static void *gfs2_glock_seq_start(struct seq_file *file, loff_t *pos)
2066 if (!gi) 2061 if (!gi)
2067 return NULL; 2062 return NULL;
2068 2063
2069 while (n--) { 2064 while(n--) {
2070 if (gfs2_glock_iter_next(gi)) { 2065 if (gfs2_glock_iter_next(gi)) {
2071 gfs2_glock_iter_free(gi); 2066 gfs2_glock_iter_free(gi);
2072 return NULL; 2067 return NULL;
@@ -2093,7 +2088,9 @@ static void *gfs2_glock_seq_next(struct seq_file *file, void *iter_ptr,
2093 2088
2094static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr) 2089static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr)
2095{ 2090{
2096 /* nothing for now */ 2091 struct glock_iter *gi = iter_ptr;
2092 if (gi)
2093 gfs2_glock_iter_free(gi);
2097} 2094}
2098 2095
2099static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr) 2096static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr)