Commit aaa04b48 authored by OGAWA Hirofumi's avatar OGAWA Hirofumi Committed by Linus Torvalds

fatfs: ratelimit corruption report

Signed-off-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f40c396a
...@@ -242,9 +242,10 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) ...@@ -242,9 +242,10 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
while (*fclus < cluster) { while (*fclus < cluster) {
/* prevent the infinite loop of cluster chain */ /* prevent the infinite loop of cluster chain */
if (*fclus > limit) { if (*fclus > limit) {
fat_fs_error(sb, "%s: detected the cluster chain loop" fat_fs_error_ratelimit(sb,
" (i_pos %lld)", __func__, "%s: detected the cluster chain loop"
MSDOS_I(inode)->i_pos); " (i_pos %lld)", __func__,
MSDOS_I(inode)->i_pos);
nr = -EIO; nr = -EIO;
goto out; goto out;
} }
...@@ -253,9 +254,9 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) ...@@ -253,9 +254,9 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
if (nr < 0) if (nr < 0)
goto out; goto out;
else if (nr == FAT_ENT_FREE) { else if (nr == FAT_ENT_FREE) {
fat_fs_error(sb, "%s: invalid cluster chain" fat_fs_error_ratelimit(sb, "%s: invalid cluster chain"
" (i_pos %lld)", __func__, " (i_pos %lld)", __func__,
MSDOS_I(inode)->i_pos); MSDOS_I(inode)->i_pos);
nr = -EIO; nr = -EIO;
goto out; goto out;
} else if (nr == FAT_ENT_EOF) { } else if (nr == FAT_ENT_EOF) {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/nls.h> #include <linux/nls.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/ratelimit.h>
#include <linux/msdos_fs.h> #include <linux/msdos_fs.h>
/* /*
...@@ -82,6 +83,8 @@ struct msdos_sb_info { ...@@ -82,6 +83,8 @@ struct msdos_sb_info {
struct fatent_operations *fatent_ops; struct fatent_operations *fatent_ops;
struct inode *fat_inode; struct inode *fat_inode;
struct ratelimit_state ratelimit;
spinlock_t inode_hash_lock; spinlock_t inode_hash_lock;
struct hlist_head inode_hashtable[FAT_HASH_SIZE]; struct hlist_head inode_hashtable[FAT_HASH_SIZE];
}; };
...@@ -322,8 +325,13 @@ extern int fat_fill_super(struct super_block *sb, void *data, int silent, ...@@ -322,8 +325,13 @@ extern int fat_fill_super(struct super_block *sb, void *data, int silent,
extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
struct inode *i2); struct inode *i2);
/* fat/misc.c */ /* fat/misc.c */
extern void fat_fs_error(struct super_block *s, const char *fmt, ...) extern void
__attribute__ ((format (printf, 2, 3))) __cold; __fat_fs_error(struct super_block *s, int report, const char *fmt, ...)
__attribute__ ((format (printf, 3, 4))) __cold;
#define fat_fs_error(s, fmt, args...) \
__fat_fs_error(s, 1, fmt , ## args)
#define fat_fs_error_ratelimit(s, fmt, args...) \
__fat_fs_error(s, __ratelimit(&MSDOS_SB(s)->ratelimit), fmt , ## args)
extern int fat_clusters_flush(struct super_block *sb); extern int fat_clusters_flush(struct super_block *sb);
extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
......
...@@ -1250,6 +1250,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, ...@@ -1250,6 +1250,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
sb->s_op = &fat_sops; sb->s_op = &fat_sops;
sb->s_export_op = &fat_export_ops; sb->s_export_op = &fat_export_ops;
sbi->dir_ops = fs_dir_inode_ops; sbi->dir_ops = fs_dir_inode_ops;
ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
error = parse_options(data, isvfat, silent, &debug, &sbi->options); error = parse_options(data, isvfat, silent, &debug, &sbi->options);
if (error) if (error)
......
...@@ -20,27 +20,29 @@ ...@@ -20,27 +20,29 @@
* In case the file system is remounted read-only, it can be made writable * In case the file system is remounted read-only, it can be made writable
* again by remounting it. * again by remounting it.
*/ */
void fat_fs_error(struct super_block *s, const char *fmt, ...) void __fat_fs_error(struct super_block *s, int report, const char *fmt, ...)
{ {
struct fat_mount_options *opts = &MSDOS_SB(s)->options; struct fat_mount_options *opts = &MSDOS_SB(s)->options;
va_list args; va_list args;
printk(KERN_ERR "FAT: Filesystem error (dev %s)\n", s->s_id); if (report) {
printk(KERN_ERR "FAT: Filesystem error (dev %s)\n", s->s_id);
printk(KERN_ERR " "); printk(KERN_ERR " ");
va_start(args, fmt); va_start(args, fmt);
vprintk(fmt, args); vprintk(fmt, args);
va_end(args); va_end(args);
printk("\n"); printk("\n");
}
if (opts->errors == FAT_ERRORS_PANIC) if (opts->errors == FAT_ERRORS_PANIC)
panic(" FAT fs panic from previous error\n"); panic("FAT: fs panic from previous error\n");
else if (opts->errors == FAT_ERRORS_RO && !(s->s_flags & MS_RDONLY)) { else if (opts->errors == FAT_ERRORS_RO && !(s->s_flags & MS_RDONLY)) {
s->s_flags |= MS_RDONLY; s->s_flags |= MS_RDONLY;
printk(KERN_ERR " File system has been set read-only\n"); printk(KERN_ERR "FAT: Filesystem has been set read-only\n");
} }
} }
EXPORT_SYMBOL_GPL(fat_fs_error); EXPORT_SYMBOL_GPL(__fat_fs_error);
/* Flushes the number of free clusters on FAT32 */ /* Flushes the number of free clusters on FAT32 */
/* XXX: Need to write one per FSINFO block. Currently only writes 1 */ /* XXX: Need to write one per FSINFO block. Currently only writes 1 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment