diff options
author | Joel Becker <joel.becker@oracle.com> | 2009-01-06 17:57:08 -0500 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2009-06-03 22:15:36 -0400 |
commit | 73be192b17e43b6dc4f492dab41d70ab5b9d2908 (patch) | |
tree | 9482070421cda81f490036b28033d4f300a58a94 /fs/ocfs2/super.c | |
parent | 15633a220ffe74fc61bc8117e6a89a494011ea3d (diff) |
ocfs2: Add statistics for the checksum and ecc operations.
It would be nice to know how often we get checksum failures. Even
better, how many of them we can fix with the single bit ecc. So, we add
a statistics structure. The structure can be installed into debugfs
wherever the user wants.
For ocfs2, we'll put it in the superblock-specific debugfs directory and
pass it down from our higher-level functions. The stats are only
registered with debugfs when the filesystem supports metadata ecc.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/super.c')
-rw-r--r-- | fs/ocfs2/super.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index d05f3caec410..86f500c5d63d 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -118,10 +118,12 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb); | |||
118 | static int ocfs2_check_volume(struct ocfs2_super *osb); | 118 | static int ocfs2_check_volume(struct ocfs2_super *osb); |
119 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, | 119 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, |
120 | struct buffer_head *bh, | 120 | struct buffer_head *bh, |
121 | u32 sectsize); | 121 | u32 sectsize, |
122 | struct ocfs2_blockcheck_stats *stats); | ||
122 | static int ocfs2_initialize_super(struct super_block *sb, | 123 | static int ocfs2_initialize_super(struct super_block *sb, |
123 | struct buffer_head *bh, | 124 | struct buffer_head *bh, |
124 | int sector_size); | 125 | int sector_size, |
126 | struct ocfs2_blockcheck_stats *stats); | ||
125 | static int ocfs2_get_sector(struct super_block *sb, | 127 | static int ocfs2_get_sector(struct super_block *sb, |
126 | struct buffer_head **bh, | 128 | struct buffer_head **bh, |
127 | int block, | 129 | int block, |
@@ -711,7 +713,8 @@ out: | |||
711 | 713 | ||
712 | static int ocfs2_sb_probe(struct super_block *sb, | 714 | static int ocfs2_sb_probe(struct super_block *sb, |
713 | struct buffer_head **bh, | 715 | struct buffer_head **bh, |
714 | int *sector_size) | 716 | int *sector_size, |
717 | struct ocfs2_blockcheck_stats *stats) | ||
715 | { | 718 | { |
716 | int status, tmpstat; | 719 | int status, tmpstat; |
717 | struct ocfs1_vol_disk_hdr *hdr; | 720 | struct ocfs1_vol_disk_hdr *hdr; |
@@ -777,7 +780,8 @@ static int ocfs2_sb_probe(struct super_block *sb, | |||
777 | goto bail; | 780 | goto bail; |
778 | } | 781 | } |
779 | di = (struct ocfs2_dinode *) (*bh)->b_data; | 782 | di = (struct ocfs2_dinode *) (*bh)->b_data; |
780 | status = ocfs2_verify_volume(di, *bh, blksize); | 783 | memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats)); |
784 | status = ocfs2_verify_volume(di, *bh, blksize, stats); | ||
781 | if (status >= 0) | 785 | if (status >= 0) |
782 | goto bail; | 786 | goto bail; |
783 | brelse(*bh); | 787 | brelse(*bh); |
@@ -983,6 +987,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
983 | struct ocfs2_super *osb = NULL; | 987 | struct ocfs2_super *osb = NULL; |
984 | struct buffer_head *bh = NULL; | 988 | struct buffer_head *bh = NULL; |
985 | char nodestr[8]; | 989 | char nodestr[8]; |
990 | struct ocfs2_blockcheck_stats stats; | ||
986 | 991 | ||
987 | mlog_entry("%p, %p, %i", sb, data, silent); | 992 | mlog_entry("%p, %p, %i", sb, data, silent); |
988 | 993 | ||
@@ -992,13 +997,13 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
992 | } | 997 | } |
993 | 998 | ||
994 | /* probe for superblock */ | 999 | /* probe for superblock */ |
995 | status = ocfs2_sb_probe(sb, &bh, §or_size); | 1000 | status = ocfs2_sb_probe(sb, &bh, §or_size, &stats); |
996 | if (status < 0) { | 1001 | if (status < 0) { |
997 | mlog(ML_ERROR, "superblock probe failed!\n"); | 1002 | mlog(ML_ERROR, "superblock probe failed!\n"); |
998 | goto read_super_error; | 1003 | goto read_super_error; |
999 | } | 1004 | } |
1000 | 1005 | ||
1001 | status = ocfs2_initialize_super(sb, bh, sector_size); | 1006 | status = ocfs2_initialize_super(sb, bh, sector_size, &stats); |
1002 | osb = OCFS2_SB(sb); | 1007 | osb = OCFS2_SB(sb); |
1003 | if (status < 0) { | 1008 | if (status < 0) { |
1004 | mlog_errno(status); | 1009 | mlog_errno(status); |
@@ -1108,6 +1113,18 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) | |||
1108 | goto read_super_error; | 1113 | goto read_super_error; |
1109 | } | 1114 | } |
1110 | 1115 | ||
1116 | if (ocfs2_meta_ecc(osb)) { | ||
1117 | status = ocfs2_blockcheck_stats_debugfs_install( | ||
1118 | &osb->osb_ecc_stats, | ||
1119 | osb->osb_debug_root); | ||
1120 | if (status) { | ||
1121 | mlog(ML_ERROR, | ||
1122 | "Unable to create blockcheck statistics " | ||
1123 | "files\n"); | ||
1124 | goto read_super_error; | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1111 | status = ocfs2_mount_volume(sb); | 1128 | status = ocfs2_mount_volume(sb); |
1112 | if (osb->root_inode) | 1129 | if (osb->root_inode) |
1113 | inode = igrab(osb->root_inode); | 1130 | inode = igrab(osb->root_inode); |
@@ -1849,6 +1866,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
1849 | if (osb->cconn) | 1866 | if (osb->cconn) |
1850 | ocfs2_dlm_shutdown(osb, hangup_needed); | 1867 | ocfs2_dlm_shutdown(osb, hangup_needed); |
1851 | 1868 | ||
1869 | ocfs2_blockcheck_stats_debugfs_remove(&osb->osb_ecc_stats); | ||
1852 | debugfs_remove(osb->osb_debug_root); | 1870 | debugfs_remove(osb->osb_debug_root); |
1853 | 1871 | ||
1854 | if (hangup_needed) | 1872 | if (hangup_needed) |
@@ -1896,7 +1914,8 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu | |||
1896 | 1914 | ||
1897 | static int ocfs2_initialize_super(struct super_block *sb, | 1915 | static int ocfs2_initialize_super(struct super_block *sb, |
1898 | struct buffer_head *bh, | 1916 | struct buffer_head *bh, |
1899 | int sector_size) | 1917 | int sector_size, |
1918 | struct ocfs2_blockcheck_stats *stats) | ||
1900 | { | 1919 | { |
1901 | int status; | 1920 | int status; |
1902 | int i, cbits, bbits; | 1921 | int i, cbits, bbits; |
@@ -1955,6 +1974,9 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1955 | atomic_set(&osb->alloc_stats.bg_allocs, 0); | 1974 | atomic_set(&osb->alloc_stats.bg_allocs, 0); |
1956 | atomic_set(&osb->alloc_stats.bg_extends, 0); | 1975 | atomic_set(&osb->alloc_stats.bg_extends, 0); |
1957 | 1976 | ||
1977 | /* Copy the blockcheck stats from the superblock probe */ | ||
1978 | osb->osb_ecc_stats = *stats; | ||
1979 | |||
1958 | ocfs2_init_node_maps(osb); | 1980 | ocfs2_init_node_maps(osb); |
1959 | 1981 | ||
1960 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", | 1982 | snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", |
@@ -2192,7 +2214,8 @@ bail: | |||
2192 | */ | 2214 | */ |
2193 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, | 2215 | static int ocfs2_verify_volume(struct ocfs2_dinode *di, |
2194 | struct buffer_head *bh, | 2216 | struct buffer_head *bh, |
2195 | u32 blksz) | 2217 | u32 blksz, |
2218 | struct ocfs2_blockcheck_stats *stats) | ||
2196 | { | 2219 | { |
2197 | int status = -EAGAIN; | 2220 | int status = -EAGAIN; |
2198 | 2221 | ||
@@ -2205,7 +2228,8 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di, | |||
2205 | OCFS2_FEATURE_INCOMPAT_META_ECC) { | 2228 | OCFS2_FEATURE_INCOMPAT_META_ECC) { |
2206 | status = ocfs2_block_check_validate(bh->b_data, | 2229 | status = ocfs2_block_check_validate(bh->b_data, |
2207 | bh->b_size, | 2230 | bh->b_size, |
2208 | &di->i_check); | 2231 | &di->i_check, |
2232 | stats); | ||
2209 | if (status) | 2233 | if (status) |
2210 | goto out; | 2234 | goto out; |
2211 | } | 2235 | } |