diff options
-rw-r--r-- | fs/gfs2/glock.c | 314 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 4 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 1 | ||||
-rw-r--r-- | fs/gfs2/main.c | 3 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 3 |
5 files changed, 262 insertions, 63 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 12accb08fe02..9f203ef4da61 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/rwsem.h> | 24 | #include <linux/rwsem.h> |
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <linux/seq_file.h> | ||
27 | #include <linux/debugfs.h> | ||
26 | 28 | ||
27 | #include "gfs2.h" | 29 | #include "gfs2.h" |
28 | #include "incore.h" | 30 | #include "incore.h" |
@@ -40,14 +42,22 @@ struct gfs2_gl_hash_bucket { | |||
40 | struct hlist_head hb_list; | 42 | struct hlist_head hb_list; |
41 | }; | 43 | }; |
42 | 44 | ||
45 | struct glock_iter { | ||
46 | int hash; /* hash bucket index */ | ||
47 | struct gfs2_sbd *sdp; /* incore superblock */ | ||
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 */ | ||
51 | char string[512]; /* scratch space */ | ||
52 | }; | ||
53 | |||
43 | typedef void (*glock_examiner) (struct gfs2_glock * gl); | 54 | typedef void (*glock_examiner) (struct gfs2_glock * gl); |
44 | 55 | ||
45 | static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); | 56 | static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); |
46 | static int dump_glock(struct gfs2_glock *gl); | ||
47 | static int dump_inode(struct gfs2_inode *ip); | ||
48 | static void gfs2_glock_xmote_th(struct gfs2_holder *gh); | 57 | static void gfs2_glock_xmote_th(struct gfs2_holder *gh); |
49 | static void gfs2_glock_drop_th(struct gfs2_glock *gl); | 58 | static void gfs2_glock_drop_th(struct gfs2_glock *gl); |
50 | static DECLARE_RWSEM(gfs2_umount_flush_sem); | 59 | static DECLARE_RWSEM(gfs2_umount_flush_sem); |
60 | static struct dentry *gfs2_root; | ||
51 | 61 | ||
52 | #define GFS2_GL_HASH_SHIFT 15 | 62 | #define GFS2_GL_HASH_SHIFT 15 |
53 | #define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) | 63 | #define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) |
@@ -1109,6 +1119,20 @@ find_holder_by_owner(struct list_head *head, struct task_struct *owner) | |||
1109 | return NULL; | 1119 | return NULL; |
1110 | } | 1120 | } |
1111 | 1121 | ||
1122 | static void print_dbg(struct glock_iter *gi, const char *fmt, ...) | ||
1123 | { | ||
1124 | va_list args; | ||
1125 | |||
1126 | va_start(args, fmt); | ||
1127 | if (gi) { | ||
1128 | vsprintf(gi->string, fmt, args); | ||
1129 | seq_printf(gi->seq, gi->string); | ||
1130 | } | ||
1131 | else | ||
1132 | vprintk(fmt, args); | ||
1133 | va_end(args); | ||
1134 | } | ||
1135 | |||
1112 | /** | 1136 | /** |
1113 | * add_to_queue - Add a holder to the wait queue (but look for recursion) | 1137 | * add_to_queue - Add a holder to the wait queue (but look for recursion) |
1114 | * @gh: the holder structure to add | 1138 | * @gh: the holder structure to add |
@@ -1849,31 +1873,32 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait) | |||
1849 | * Returns: 0 on success, -ENOBUFS when we run out of space | 1873 | * Returns: 0 on success, -ENOBUFS when we run out of space |
1850 | */ | 1874 | */ |
1851 | 1875 | ||
1852 | static int dump_holder(char *str, struct gfs2_holder *gh) | 1876 | static int dump_holder(struct glock_iter *gi, char *str, |
1877 | struct gfs2_holder *gh) | ||
1853 | { | 1878 | { |
1854 | unsigned int x; | 1879 | unsigned int x; |
1855 | int error = -ENOBUFS; | ||
1856 | 1880 | ||
1857 | printk(KERN_INFO " %s\n", str); | 1881 | print_dbg(gi, " %s\n", str); |
1858 | printk(KERN_INFO " owner = %ld\n", | 1882 | print_dbg(gi, " owner = %ld\n", |
1859 | (gh->gh_owner) ? (long)gh->gh_owner->pid : -1); | 1883 | (gh->gh_owner) ? (long)gh->gh_owner->pid : -1); |
1860 | printk(KERN_INFO " gh_state = %u\n", gh->gh_state); | 1884 | print_dbg(gi, " gh_state = %u\n", gh->gh_state); |
1861 | printk(KERN_INFO " gh_flags ="); | 1885 | print_dbg(gi, " gh_flags ="); |
1862 | for (x = 0; x < 32; x++) | 1886 | for (x = 0; x < 32; x++) |
1863 | if (gh->gh_flags & (1 << x)) | 1887 | if (gh->gh_flags & (1 << x)) |
1864 | printk(" %u", x); | 1888 | print_dbg(gi, " %u", x); |
1865 | printk(" \n"); | 1889 | print_dbg(gi, " \n"); |
1866 | printk(KERN_INFO " error = %d\n", gh->gh_error); | 1890 | print_dbg(gi, " error = %d\n", gh->gh_error); |
1867 | printk(KERN_INFO " gh_iflags ="); | 1891 | print_dbg(gi, " gh_iflags ="); |
1868 | for (x = 0; x < 32; x++) | 1892 | for (x = 0; x < 32; x++) |
1869 | if (test_bit(x, &gh->gh_iflags)) | 1893 | if (test_bit(x, &gh->gh_iflags)) |
1870 | printk(" %u", x); | 1894 | print_dbg(gi, " %u", x); |
1871 | printk(" \n"); | 1895 | print_dbg(gi, " \n"); |
1872 | print_symbol(KERN_INFO " initialized at: %s\n", gh->gh_ip); | 1896 | if (gi) |
1873 | 1897 | print_dbg(gi, " initialized at: 0x%x\n", gh->gh_ip); | |
1874 | error = 0; | 1898 | else |
1899 | print_symbol(KERN_INFO " initialized at: %s\n", gh->gh_ip); | ||
1875 | 1900 | ||
1876 | return error; | 1901 | return 0; |
1877 | } | 1902 | } |
1878 | 1903 | ||
1879 | /** | 1904 | /** |
@@ -1883,25 +1908,20 @@ static int dump_holder(char *str, struct gfs2_holder *gh) | |||
1883 | * Returns: 0 on success, -ENOBUFS when we run out of space | 1908 | * Returns: 0 on success, -ENOBUFS when we run out of space |
1884 | */ | 1909 | */ |
1885 | 1910 | ||
1886 | static int dump_inode(struct gfs2_inode *ip) | 1911 | static int dump_inode(struct glock_iter *gi, struct gfs2_inode *ip) |
1887 | { | 1912 | { |
1888 | unsigned int x; | 1913 | unsigned int x; |
1889 | int error = -ENOBUFS; | ||
1890 | 1914 | ||
1891 | printk(KERN_INFO " Inode:\n"); | 1915 | print_dbg(gi, " Inode:\n"); |
1892 | printk(KERN_INFO " num = %llu %llu\n", | 1916 | print_dbg(gi, " num = %llu/%llu\n", |
1893 | (unsigned long long)ip->i_num.no_formal_ino, | 1917 | ip->i_num.no_formal_ino, ip->i_num.no_addr); |
1894 | (unsigned long long)ip->i_num.no_addr); | 1918 | print_dbg(gi, " type = %u\n", IF2DT(ip->i_inode.i_mode)); |
1895 | printk(KERN_INFO " type = %u\n", IF2DT(ip->i_inode.i_mode)); | 1919 | print_dbg(gi, " i_flags ="); |
1896 | printk(KERN_INFO " i_flags ="); | ||
1897 | for (x = 0; x < 32; x++) | 1920 | for (x = 0; x < 32; x++) |
1898 | if (test_bit(x, &ip->i_flags)) | 1921 | if (test_bit(x, &ip->i_flags)) |
1899 | printk(" %u", x); | 1922 | print_dbg(gi, " %u", x); |
1900 | printk(" \n"); | 1923 | print_dbg(gi, " \n"); |
1901 | 1924 | return 0; | |
1902 | error = 0; | ||
1903 | |||
1904 | return error; | ||
1905 | } | 1925 | } |
1906 | 1926 | ||
1907 | /** | 1927 | /** |
@@ -1912,7 +1932,7 @@ static int dump_inode(struct gfs2_inode *ip) | |||
1912 | * Returns: 0 on success, -ENOBUFS when we run out of space | 1932 | * Returns: 0 on success, -ENOBUFS when we run out of space |
1913 | */ | 1933 | */ |
1914 | 1934 | ||
1915 | static int dump_glock(struct gfs2_glock *gl) | 1935 | static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl) |
1916 | { | 1936 | { |
1917 | struct gfs2_holder *gh; | 1937 | struct gfs2_holder *gh; |
1918 | unsigned int x; | 1938 | unsigned int x; |
@@ -1920,66 +1940,66 @@ static int dump_glock(struct gfs2_glock *gl) | |||
1920 | 1940 | ||
1921 | spin_lock(&gl->gl_spin); | 1941 | spin_lock(&gl->gl_spin); |
1922 | 1942 | ||
1923 | printk(KERN_INFO "Glock 0x%p (%u, %llu)\n", gl, gl->gl_name.ln_type, | 1943 | print_dbg(gi, "Glock 0x%p (%u, %llu)\n", gl, gl->gl_name.ln_type, |
1924 | (unsigned long long)gl->gl_name.ln_number); | 1944 | (unsigned long long)gl->gl_name.ln_number); |
1925 | printk(KERN_INFO " gl_flags ="); | 1945 | print_dbg(gi, " gl_flags ="); |
1926 | for (x = 0; x < 32; x++) { | 1946 | for (x = 0; x < 32; x++) { |
1927 | if (test_bit(x, &gl->gl_flags)) | 1947 | if (test_bit(x, &gl->gl_flags)) |
1928 | printk(" %u", x); | 1948 | print_dbg(gi, " %u", x); |
1929 | } | 1949 | } |
1930 | printk(" \n"); | 1950 | print_dbg(gi, " \n"); |
1931 | printk(KERN_INFO " gl_ref = %d\n", atomic_read(&gl->gl_ref)); | 1951 | print_dbg(gi, " gl_ref = %d\n", atomic_read(&gl->gl_ref)); |
1932 | printk(KERN_INFO " gl_state = %u\n", gl->gl_state); | 1952 | print_dbg(gi, " gl_state = %u\n", gl->gl_state); |
1933 | printk(KERN_INFO " gl_owner = %s\n", gl->gl_owner->comm); | 1953 | print_dbg(gi, " gl_owner = %s\n", gl->gl_owner->comm); |
1934 | print_symbol(KERN_INFO " gl_ip = %s\n", gl->gl_ip); | 1954 | print_dbg(gi, " gl_ip = %lu\n", gl->gl_ip); |
1935 | printk(KERN_INFO " req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no"); | 1955 | print_dbg(gi, " req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no"); |
1936 | printk(KERN_INFO " req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no"); | 1956 | print_dbg(gi, " req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no"); |
1937 | printk(KERN_INFO " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count)); | 1957 | print_dbg(gi, " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count)); |
1938 | printk(KERN_INFO " object = %s\n", (gl->gl_object) ? "yes" : "no"); | 1958 | print_dbg(gi, " object = %s\n", (gl->gl_object) ? "yes" : "no"); |
1939 | printk(KERN_INFO " le = %s\n", | 1959 | print_dbg(gi, " le = %s\n", |
1940 | (list_empty(&gl->gl_le.le_list)) ? "no" : "yes"); | 1960 | (list_empty(&gl->gl_le.le_list)) ? "no" : "yes"); |
1941 | printk(KERN_INFO " reclaim = %s\n", | 1961 | print_dbg(gi, " reclaim = %s\n", |
1942 | (list_empty(&gl->gl_reclaim)) ? "no" : "yes"); | 1962 | (list_empty(&gl->gl_reclaim)) ? "no" : "yes"); |
1943 | if (gl->gl_aspace) | 1963 | if (gl->gl_aspace) |
1944 | printk(KERN_INFO " aspace = 0x%p nrpages = %lu\n", gl->gl_aspace, | 1964 | print_dbg(gi, " aspace = 0x%p nrpages = %lu\n", gl->gl_aspace, |
1945 | gl->gl_aspace->i_mapping->nrpages); | 1965 | gl->gl_aspace->i_mapping->nrpages); |
1946 | else | 1966 | else |
1947 | printk(KERN_INFO " aspace = no\n"); | 1967 | print_dbg(gi, " aspace = no\n"); |
1948 | printk(KERN_INFO " ail = %d\n", atomic_read(&gl->gl_ail_count)); | 1968 | print_dbg(gi, " ail = %d\n", atomic_read(&gl->gl_ail_count)); |
1949 | if (gl->gl_req_gh) { | 1969 | if (gl->gl_req_gh) { |
1950 | error = dump_holder("Request", gl->gl_req_gh); | 1970 | error = dump_holder(gi, "Request", gl->gl_req_gh); |
1951 | if (error) | 1971 | if (error) |
1952 | goto out; | 1972 | goto out; |
1953 | } | 1973 | } |
1954 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { | 1974 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { |
1955 | error = dump_holder("Holder", gh); | 1975 | error = dump_holder(gi, "Holder", gh); |
1956 | if (error) | 1976 | if (error) |
1957 | goto out; | 1977 | goto out; |
1958 | } | 1978 | } |
1959 | list_for_each_entry(gh, &gl->gl_waiters1, gh_list) { | 1979 | list_for_each_entry(gh, &gl->gl_waiters1, gh_list) { |
1960 | error = dump_holder("Waiter1", gh); | 1980 | error = dump_holder(gi, "Waiter1", gh); |
1961 | if (error) | 1981 | if (error) |
1962 | goto out; | 1982 | goto out; |
1963 | } | 1983 | } |
1964 | list_for_each_entry(gh, &gl->gl_waiters2, gh_list) { | 1984 | list_for_each_entry(gh, &gl->gl_waiters2, gh_list) { |
1965 | error = dump_holder("Waiter2", gh); | 1985 | error = dump_holder(gi, "Waiter2", gh); |
1966 | if (error) | 1986 | if (error) |
1967 | goto out; | 1987 | goto out; |
1968 | } | 1988 | } |
1969 | list_for_each_entry(gh, &gl->gl_waiters3, gh_list) { | 1989 | list_for_each_entry(gh, &gl->gl_waiters3, gh_list) { |
1970 | error = dump_holder("Waiter3", gh); | 1990 | error = dump_holder(gi, "Waiter3", gh); |
1971 | if (error) | 1991 | if (error) |
1972 | goto out; | 1992 | goto out; |
1973 | } | 1993 | } |
1974 | if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) { | 1994 | if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) { |
1975 | if (!test_bit(GLF_LOCK, &gl->gl_flags) && | 1995 | if (!test_bit(GLF_LOCK, &gl->gl_flags) && |
1976 | list_empty(&gl->gl_holders)) { | 1996 | list_empty(&gl->gl_holders)) { |
1977 | error = dump_inode(gl->gl_object); | 1997 | error = dump_inode(gi, gl->gl_object); |
1978 | if (error) | 1998 | if (error) |
1979 | goto out; | 1999 | goto out; |
1980 | } else { | 2000 | } else { |
1981 | error = -ENOBUFS; | 2001 | error = -ENOBUFS; |
1982 | printk(KERN_INFO " Inode: busy\n"); | 2002 | print_dbg(gi, " Inode: busy\n"); |
1983 | } | 2003 | } |
1984 | } | 2004 | } |
1985 | 2005 | ||
@@ -2014,7 +2034,7 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp) | |||
2014 | if (gl->gl_sbd != sdp) | 2034 | if (gl->gl_sbd != sdp) |
2015 | continue; | 2035 | continue; |
2016 | 2036 | ||
2017 | error = dump_glock(gl); | 2037 | error = dump_glock(NULL, gl); |
2018 | if (error) | 2038 | if (error) |
2019 | break; | 2039 | break; |
2020 | } | 2040 | } |
@@ -2043,3 +2063,171 @@ int __init gfs2_glock_init(void) | |||
2043 | return 0; | 2063 | return 0; |
2044 | } | 2064 | } |
2045 | 2065 | ||
2066 | static int gfs2_glock_iter_next(struct glock_iter *gi) | ||
2067 | { | ||
2068 | while (1) { | ||
2069 | if (!gi->hb_list) { /* If we don't have a hash bucket yet */ | ||
2070 | gi->hb_list = &gl_hash_table[gi->hash].hb_list; | ||
2071 | if (hlist_empty(gi->hb_list)) { | ||
2072 | gi->hash++; | ||
2073 | gi->hb_list = NULL; | ||
2074 | if (gi->hash >= GFS2_GL_HASH_SIZE) | ||
2075 | return 1; | ||
2076 | else | ||
2077 | continue; | ||
2078 | } | ||
2079 | if (!hlist_empty(gi->hb_list)) { | ||
2080 | gi->gl = list_entry(gi->hb_list->first, | ||
2081 | struct gfs2_glock, | ||
2082 | gl_list); | ||
2083 | } | ||
2084 | } else { | ||
2085 | if (gi->gl->gl_list.next == NULL) { | ||
2086 | gi->hash++; | ||
2087 | gi->hb_list = NULL; | ||
2088 | continue; | ||
2089 | } | ||
2090 | gi->gl = list_entry(gi->gl->gl_list.next, | ||
2091 | struct gfs2_glock, gl_list); | ||
2092 | } | ||
2093 | if (gi->gl) | ||
2094 | break; | ||
2095 | } | ||
2096 | return 0; | ||
2097 | } | ||
2098 | |||
2099 | static void gfs2_glock_iter_free(struct glock_iter *gi) | ||
2100 | { | ||
2101 | kfree(gi); | ||
2102 | } | ||
2103 | |||
2104 | static struct glock_iter *gfs2_glock_iter_init(struct gfs2_sbd *sdp) | ||
2105 | { | ||
2106 | struct glock_iter *gi; | ||
2107 | |||
2108 | gi = kmalloc(sizeof (*gi), GFP_KERNEL); | ||
2109 | if (!gi) | ||
2110 | return NULL; | ||
2111 | |||
2112 | gi->sdp = sdp; | ||
2113 | gi->hash = 0; | ||
2114 | gi->gl = NULL; | ||
2115 | gi->hb_list = NULL; | ||
2116 | gi->seq = NULL; | ||
2117 | memset(gi->string, 0, sizeof(gi->string)); | ||
2118 | |||
2119 | if (gfs2_glock_iter_next(gi)) { | ||
2120 | gfs2_glock_iter_free(gi); | ||
2121 | return NULL; | ||
2122 | } | ||
2123 | |||
2124 | return gi; | ||
2125 | } | ||
2126 | |||
2127 | static void *gfs2_glock_seq_start(struct seq_file *file, loff_t *pos) | ||
2128 | { | ||
2129 | struct glock_iter *gi; | ||
2130 | loff_t n = *pos; | ||
2131 | |||
2132 | gi = gfs2_glock_iter_init(file->private); | ||
2133 | if (!gi) | ||
2134 | return NULL; | ||
2135 | |||
2136 | while (n--) { | ||
2137 | if (gfs2_glock_iter_next(gi)) { | ||
2138 | gfs2_glock_iter_free(gi); | ||
2139 | return NULL; | ||
2140 | } | ||
2141 | } | ||
2142 | |||
2143 | return gi; | ||
2144 | } | ||
2145 | |||
2146 | static void *gfs2_glock_seq_next(struct seq_file *file, void *iter_ptr, | ||
2147 | loff_t *pos) | ||
2148 | { | ||
2149 | struct glock_iter *gi = iter_ptr; | ||
2150 | |||
2151 | (*pos)++; | ||
2152 | |||
2153 | if (gfs2_glock_iter_next(gi)) { | ||
2154 | gfs2_glock_iter_free(gi); | ||
2155 | return NULL; | ||
2156 | } | ||
2157 | |||
2158 | return gi; | ||
2159 | } | ||
2160 | |||
2161 | static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr) | ||
2162 | { | ||
2163 | /* nothing for now */ | ||
2164 | } | ||
2165 | |||
2166 | static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr) | ||
2167 | { | ||
2168 | struct glock_iter *gi = iter_ptr; | ||
2169 | |||
2170 | gi->seq = file; | ||
2171 | dump_glock(gi, gi->gl); | ||
2172 | |||
2173 | return 0; | ||
2174 | } | ||
2175 | |||
2176 | static struct seq_operations gfs2_glock_seq_ops = { | ||
2177 | .start = gfs2_glock_seq_start, | ||
2178 | .next = gfs2_glock_seq_next, | ||
2179 | .stop = gfs2_glock_seq_stop, | ||
2180 | .show = gfs2_glock_seq_show, | ||
2181 | }; | ||
2182 | |||
2183 | static int gfs2_debugfs_open(struct inode *inode, struct file *file) | ||
2184 | { | ||
2185 | struct seq_file *seq; | ||
2186 | int ret; | ||
2187 | |||
2188 | ret = seq_open(file, &gfs2_glock_seq_ops); | ||
2189 | if (ret) | ||
2190 | return ret; | ||
2191 | |||
2192 | seq = file->private_data; | ||
2193 | seq->private = inode->i_private; | ||
2194 | |||
2195 | return 0; | ||
2196 | } | ||
2197 | |||
2198 | static const struct file_operations gfs2_debug_fops = { | ||
2199 | .owner = THIS_MODULE, | ||
2200 | .open = gfs2_debugfs_open, | ||
2201 | .read = seq_read, | ||
2202 | .llseek = seq_lseek, | ||
2203 | .release = seq_release | ||
2204 | }; | ||
2205 | |||
2206 | int gfs2_create_debugfs_file(struct gfs2_sbd *sdp) | ||
2207 | { | ||
2208 | sdp->debugfs_dentry = debugfs_create_file(sdp->sd_table_name, | ||
2209 | S_IFREG | S_IRUGO, | ||
2210 | gfs2_root, sdp, | ||
2211 | &gfs2_debug_fops); | ||
2212 | if (!sdp->debugfs_dentry) | ||
2213 | return -ENOMEM; | ||
2214 | |||
2215 | return 0; | ||
2216 | } | ||
2217 | |||
2218 | void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp) | ||
2219 | { | ||
2220 | if (sdp->debugfs_dentry) | ||
2221 | debugfs_remove(sdp->debugfs_dentry); | ||
2222 | } | ||
2223 | |||
2224 | int gfs2_register_debugfs(void) | ||
2225 | { | ||
2226 | gfs2_root = debugfs_create_dir("gfs2", NULL); | ||
2227 | return gfs2_root ? 0 : -ENOMEM; | ||
2228 | } | ||
2229 | |||
2230 | void gfs2_unregister_debugfs(void) | ||
2231 | { | ||
2232 | debugfs_remove(gfs2_root); | ||
2233 | } | ||
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index f50e40ceca43..d7cef7408728 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -135,5 +135,9 @@ void gfs2_scand_internal(struct gfs2_sbd *sdp); | |||
135 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait); | 135 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait); |
136 | 136 | ||
137 | int __init gfs2_glock_init(void); | 137 | int __init gfs2_glock_init(void); |
138 | int gfs2_create_debugfs_file(struct gfs2_sbd *sdp); | ||
139 | void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp); | ||
140 | int gfs2_register_debugfs(void); | ||
141 | void gfs2_unregister_debugfs(void); | ||
138 | 142 | ||
139 | #endif /* __GLOCK_DOT_H__ */ | 143 | #endif /* __GLOCK_DOT_H__ */ |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 49f0dbf40d86..7555261d911f 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -611,6 +611,7 @@ struct gfs2_sbd { | |||
611 | 611 | ||
612 | unsigned long sd_last_warning; | 612 | unsigned long sd_last_warning; |
613 | struct vfsmount *sd_gfs2mnt; | 613 | struct vfsmount *sd_gfs2mnt; |
614 | struct dentry *debugfs_dentry; /* for debugfs */ | ||
614 | }; | 615 | }; |
615 | 616 | ||
616 | #endif /* __INCORE_DOT_H__ */ | 617 | #endif /* __INCORE_DOT_H__ */ |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 6e8a59809abf..218395371dbe 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -103,6 +103,8 @@ static int __init init_gfs2_fs(void) | |||
103 | if (error) | 103 | if (error) |
104 | goto fail_unregister; | 104 | goto fail_unregister; |
105 | 105 | ||
106 | gfs2_register_debugfs(); | ||
107 | |||
106 | printk("GFS2 (built %s %s) installed\n", __DATE__, __TIME__); | 108 | printk("GFS2 (built %s %s) installed\n", __DATE__, __TIME__); |
107 | 109 | ||
108 | return 0; | 110 | return 0; |
@@ -130,6 +132,7 @@ fail: | |||
130 | 132 | ||
131 | static void __exit exit_gfs2_fs(void) | 133 | static void __exit exit_gfs2_fs(void) |
132 | { | 134 | { |
135 | gfs2_unregister_debugfs(); | ||
133 | unregister_filesystem(&gfs2_fs_type); | 136 | unregister_filesystem(&gfs2_fs_type); |
134 | unregister_filesystem(&gfs2meta_fs_type); | 137 | unregister_filesystem(&gfs2meta_fs_type); |
135 | 138 | ||
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index ee54cb667083..ecb8b18de0ee 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -690,6 +690,8 @@ static int fill_super(struct super_block *sb, void *data, int silent) | |||
690 | if (error) | 690 | if (error) |
691 | goto fail; | 691 | goto fail; |
692 | 692 | ||
693 | gfs2_create_debugfs_file(sdp); | ||
694 | |||
693 | error = gfs2_sys_fs_add(sdp); | 695 | error = gfs2_sys_fs_add(sdp); |
694 | if (error) | 696 | if (error) |
695 | goto fail; | 697 | goto fail; |
@@ -896,6 +898,7 @@ error: | |||
896 | 898 | ||
897 | static void gfs2_kill_sb(struct super_block *sb) | 899 | static void gfs2_kill_sb(struct super_block *sb) |
898 | { | 900 | { |
901 | gfs2_delete_debugfs_file(sb->s_fs_info); | ||
899 | kill_block_super(sb); | 902 | kill_block_super(sb); |
900 | } | 903 | } |
901 | 904 | ||