summary refs log tree commit diff
path: root/fs/ext3
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2008-10-18 20:28:00 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-20 08:52:38 -0700
commitcdbf6dba28e8e6268c8420857696309470009fd9 (patch)
treeab41f3c567a5e94f3c0e500ab796ad3bdd38806c /fs/ext3
parent5ec8b75e3a2a94860ee99b5456fe1a963c8680e5 (diff)
downloadlinux-cdbf6dba28e8e6268c8420857696309470009fd9.tar.gz
ext3: avoid printk floods in the face of directory corruption
A very large directory with many read failures (either due to storage
problems, or due to invalid size & blocks from corruption) will generate a
printk storm as the filesystem continues to try to read all the blocks.
This flood of messages can tie up the box until it is complete - which may
be a very long time, especially for very large corrupted values.

This is fixed by only reporting the corruption once each time we try to
read the directory.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: Eugene Teo <eugeneteo@kernel.sg>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/dir.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index 28b681ef47e8..4c82531ea0a8 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -102,6 +102,7 @@ static int ext3_readdir(struct file * filp,
 	int err;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	int ret = 0;
+	int dir_has_error = 0;
 
 	sb = inode->i_sb;
 
@@ -148,9 +149,12 @@ static int ext3_readdir(struct file * filp,
 		 * of recovering data when there's a bad sector
 		 */
 		if (!bh) {
-			ext3_error (sb, "ext3_readdir",
-				"directory #%lu contains a hole at offset %lu",
-				inode->i_ino, (unsigned long)filp->f_pos);
+			if (!dir_has_error) {
+				ext3_error(sb, __func__, "directory #%lu "
+					"contains a hole at offset %lld",
+					inode->i_ino, filp->f_pos);
+				dir_has_error = 1;
+			}
 			/* corrupt size?  Maybe no more blocks to read */
 			if (filp->f_pos > inode->i_blocks << 9)
 				break;