diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2010-05-24 17:33:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 11:07:04 -0400 |
commit | aaa04b4875f30659a0eb429e0e5203ae7fb7b18e (patch) | |
tree | 7a7e71455e8e318f08d03748b528fbffca853bfa | |
parent | f40c396a9ab04eae526990e2b2cef875b424ed4e (diff) |
fatfs: ratelimit corruption report
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/fat/cache.c | 13 | ||||
-rw-r--r-- | fs/fat/fat.h | 12 | ||||
-rw-r--r-- | fs/fat/inode.c | 2 | ||||
-rw-r--r-- | fs/fat/misc.c | 22 |
4 files changed, 31 insertions, 18 deletions
diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 113f0a1e565d..ae8200f84e39 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c | |||
@@ -242,9 +242,10 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) | |||
242 | while (*fclus < cluster) { | 242 | while (*fclus < cluster) { |
243 | /* prevent the infinite loop of cluster chain */ | 243 | /* prevent the infinite loop of cluster chain */ |
244 | if (*fclus > limit) { | 244 | if (*fclus > limit) { |
245 | fat_fs_error(sb, "%s: detected the cluster chain loop" | 245 | fat_fs_error_ratelimit(sb, |
246 | " (i_pos %lld)", __func__, | 246 | "%s: detected the cluster chain loop" |
247 | MSDOS_I(inode)->i_pos); | 247 | " (i_pos %lld)", __func__, |
248 | MSDOS_I(inode)->i_pos); | ||
248 | nr = -EIO; | 249 | nr = -EIO; |
249 | goto out; | 250 | goto out; |
250 | } | 251 | } |
@@ -253,9 +254,9 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) | |||
253 | if (nr < 0) | 254 | if (nr < 0) |
254 | goto out; | 255 | goto out; |
255 | else if (nr == FAT_ENT_FREE) { | 256 | else if (nr == FAT_ENT_FREE) { |
256 | fat_fs_error(sb, "%s: invalid cluster chain" | 257 | fat_fs_error_ratelimit(sb, "%s: invalid cluster chain" |
257 | " (i_pos %lld)", __func__, | 258 | " (i_pos %lld)", __func__, |
258 | MSDOS_I(inode)->i_pos); | 259 | MSDOS_I(inode)->i_pos); |
259 | nr = -EIO; | 260 | nr = -EIO; |
260 | goto out; | 261 | goto out; |
261 | } else if (nr == FAT_ENT_EOF) { | 262 | } else if (nr == FAT_ENT_EOF) { |
diff --git a/fs/fat/fat.h b/fs/fat/fat.h index eb821ee1a333..53dba57b49a1 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/nls.h> | 6 | #include <linux/nls.h> |
7 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
8 | #include <linux/mutex.h> | 8 | #include <linux/mutex.h> |
9 | #include <linux/ratelimit.h> | ||
9 | #include <linux/msdos_fs.h> | 10 | #include <linux/msdos_fs.h> |
10 | 11 | ||
11 | /* | 12 | /* |
@@ -82,6 +83,8 @@ struct msdos_sb_info { | |||
82 | struct fatent_operations *fatent_ops; | 83 | struct fatent_operations *fatent_ops; |
83 | struct inode *fat_inode; | 84 | struct inode *fat_inode; |
84 | 85 | ||
86 | struct ratelimit_state ratelimit; | ||
87 | |||
85 | spinlock_t inode_hash_lock; | 88 | spinlock_t inode_hash_lock; |
86 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; | 89 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; |
87 | }; | 90 | }; |
@@ -322,8 +325,13 @@ extern int fat_fill_super(struct super_block *sb, void *data, int silent, | |||
322 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, | 325 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, |
323 | struct inode *i2); | 326 | struct inode *i2); |
324 | /* fat/misc.c */ | 327 | /* fat/misc.c */ |
325 | extern void fat_fs_error(struct super_block *s, const char *fmt, ...) | 328 | extern void |
326 | __attribute__ ((format (printf, 2, 3))) __cold; | 329 | __fat_fs_error(struct super_block *s, int report, const char *fmt, ...) |
330 | __attribute__ ((format (printf, 3, 4))) __cold; | ||
331 | #define fat_fs_error(s, fmt, args...) \ | ||
332 | __fat_fs_error(s, 1, fmt , ## args) | ||
333 | #define fat_fs_error_ratelimit(s, fmt, args...) \ | ||
334 | __fat_fs_error(s, __ratelimit(&MSDOS_SB(s)->ratelimit), fmt , ## args) | ||
327 | extern int fat_clusters_flush(struct super_block *sb); | 335 | extern int fat_clusters_flush(struct super_block *sb); |
328 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); | 336 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); |
329 | extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, | 337 | extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index c611818893b2..ed33904926ee 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -1250,6 +1250,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, | |||
1250 | sb->s_op = &fat_sops; | 1250 | sb->s_op = &fat_sops; |
1251 | sb->s_export_op = &fat_export_ops; | 1251 | sb->s_export_op = &fat_export_ops; |
1252 | sbi->dir_ops = fs_dir_inode_ops; | 1252 | sbi->dir_ops = fs_dir_inode_ops; |
1253 | ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, | ||
1254 | DEFAULT_RATELIMIT_BURST); | ||
1253 | 1255 | ||
1254 | error = parse_options(data, isvfat, silent, &debug, &sbi->options); | 1256 | error = parse_options(data, isvfat, silent, &debug, &sbi->options); |
1255 | if (error) | 1257 | if (error) |
diff --git a/fs/fat/misc.c b/fs/fat/misc.c index d3da05f26465..1fa23f6ffba5 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c | |||
@@ -20,27 +20,29 @@ | |||
20 | * In case the file system is remounted read-only, it can be made writable | 20 | * In case the file system is remounted read-only, it can be made writable |
21 | * again by remounting it. | 21 | * again by remounting it. |
22 | */ | 22 | */ |
23 | void fat_fs_error(struct super_block *s, const char *fmt, ...) | 23 | void __fat_fs_error(struct super_block *s, int report, const char *fmt, ...) |
24 | { | 24 | { |
25 | struct fat_mount_options *opts = &MSDOS_SB(s)->options; | 25 | struct fat_mount_options *opts = &MSDOS_SB(s)->options; |
26 | va_list args; | 26 | va_list args; |
27 | 27 | ||
28 | printk(KERN_ERR "FAT: Filesystem error (dev %s)\n", s->s_id); | 28 | if (report) { |
29 | printk(KERN_ERR "FAT: Filesystem error (dev %s)\n", s->s_id); | ||
29 | 30 | ||
30 | printk(KERN_ERR " "); | 31 | printk(KERN_ERR " "); |
31 | va_start(args, fmt); | 32 | va_start(args, fmt); |
32 | vprintk(fmt, args); | 33 | vprintk(fmt, args); |
33 | va_end(args); | 34 | va_end(args); |
34 | printk("\n"); | 35 | printk("\n"); |
36 | } | ||
35 | 37 | ||
36 | if (opts->errors == FAT_ERRORS_PANIC) | 38 | if (opts->errors == FAT_ERRORS_PANIC) |
37 | panic(" FAT fs panic from previous error\n"); | 39 | panic("FAT: fs panic from previous error\n"); |
38 | else if (opts->errors == FAT_ERRORS_RO && !(s->s_flags & MS_RDONLY)) { | 40 | else if (opts->errors == FAT_ERRORS_RO && !(s->s_flags & MS_RDONLY)) { |
39 | s->s_flags |= MS_RDONLY; | 41 | s->s_flags |= MS_RDONLY; |
40 | printk(KERN_ERR " File system has been set read-only\n"); | 42 | printk(KERN_ERR "FAT: Filesystem has been set read-only\n"); |
41 | } | 43 | } |
42 | } | 44 | } |
43 | EXPORT_SYMBOL_GPL(fat_fs_error); | 45 | EXPORT_SYMBOL_GPL(__fat_fs_error); |
44 | 46 | ||
45 | /* Flushes the number of free clusters on FAT32 */ | 47 | /* Flushes the number of free clusters on FAT32 */ |
46 | /* XXX: Need to write one per FSINFO block. Currently only writes 1 */ | 48 | /* XXX: Need to write one per FSINFO block. Currently only writes 1 */ |