Commit 7b08fc620109c2f66575e9ae884f45c37933ea18

Authored by Steven Whitehouse
1 parent afd0942d98

[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>

Showing 1 changed file with 35 additions and 38 deletions Side-by-side Diff

... ... @@ -46,7 +46,6 @@
46 46 int hash; /* hash bucket index */
47 47 struct gfs2_sbd *sdp; /* incore superblock */
48 48 struct gfs2_glock *gl; /* current glock struct */
49   - struct hlist_head *hb_list; /* current hash bucket ptr */
50 49 struct seq_file *seq; /* sequence file for debugfs */
51 50 char string[512]; /* scratch space */
52 51 };
53 52  
54 53  
55 54  
56 55  
... ... @@ -1990,47 +1989,38 @@
1990 1989  
1991 1990 static int gfs2_glock_iter_next(struct glock_iter *gi)
1992 1991 {
  1992 + struct gfs2_glock *gl;
  1993 +
1993 1994 read_lock(gl_lock_addr(gi->hash));
1994   - while (1) {
1995   - if (!gi->hb_list) { /* If we don't have a hash bucket yet */
1996   - gi->hb_list = &gl_hash_table[gi->hash].hb_list;
1997   - if (hlist_empty(gi->hb_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   - }
  1995 + gl = gi->gl;
  1996 + if (gl) {
  1997 + gi->gl = hlist_entry(gl->gl_list.next, struct gfs2_glock,
  1998 + gl_list);
2025 1999 if (gi->gl)
2026   - break;
  2000 + gfs2_glock_hold(gi->gl);
2027 2001 }
2028 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 2017 return 0;
2030 2018 }
2031 2019  
2032 2020 static void gfs2_glock_iter_free(struct glock_iter *gi)
2033 2021 {
  2022 + if (gi->gl)
  2023 + gfs2_glock_put(gi->gl);
2034 2024 kfree(gi);
2035 2025 }
2036 2026  
2037 2027  
... ... @@ -2044,12 +2034,17 @@
2044 2034  
2045 2035 gi->sdp = sdp;
2046 2036 gi->hash = 0;
2047   - gi->gl = NULL;
2048   - gi->hb_list = NULL;
2049 2037 gi->seq = NULL;
2050 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 2048 gfs2_glock_iter_free(gi);
2054 2049 return NULL;
2055 2050 }
... ... @@ -2066,7 +2061,7 @@
2066 2061 if (!gi)
2067 2062 return NULL;
2068 2063  
2069   - while (n--) {
  2064 + while(n--) {
2070 2065 if (gfs2_glock_iter_next(gi)) {
2071 2066 gfs2_glock_iter_free(gi);
2072 2067 return NULL;
... ... @@ -2093,7 +2088,9 @@
2093 2088  
2094 2089 static 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  
2099 2096 static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr)