aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2008-10-16 01:04:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-16 14:21:46 -0400
commitbd39597cbd42a784105a04010100e27267481c67 (patch)
treeafe3e40d871f4581146f5679ea546670fe93f4f2 /fs
parentd707d31c972b657dfc2efefd0b99cc4e14223dab (diff)
ext2: 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. [akpm@linux-foundation.org: coding-style fixes] 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')
-rw-r--r--fs/ext2/dir.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index a78c6b4af060..11a49ce84392 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -103,7 +103,7 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len)
103 return err; 103 return err;
104} 104}
105 105
106static void ext2_check_page(struct page *page) 106static void ext2_check_page(struct page *page, int quiet)
107{ 107{
108 struct inode *dir = page->mapping->host; 108 struct inode *dir = page->mapping->host;
109 struct super_block *sb = dir->i_sb; 109 struct super_block *sb = dir->i_sb;
@@ -146,10 +146,10 @@ out:
146 /* Too bad, we had an error */ 146 /* Too bad, we had an error */
147 147
148Ebadsize: 148Ebadsize:
149 ext2_error(sb, "ext2_check_page", 149 if (!quiet)
150 "size of directory #%lu is not a multiple of chunk size", 150 ext2_error(sb, __func__,
151 dir->i_ino 151 "size of directory #%lu is not a multiple "
152 ); 152 "of chunk size", dir->i_ino);
153 goto fail; 153 goto fail;
154Eshort: 154Eshort:
155 error = "rec_len is smaller than minimal"; 155 error = "rec_len is smaller than minimal";
@@ -166,32 +166,36 @@ Espan:
166Einumber: 166Einumber:
167 error = "inode out of bounds"; 167 error = "inode out of bounds";
168bad_entry: 168bad_entry:
169 ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - " 169 if (!quiet)
170 "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", 170 ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - "
171 dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs, 171 "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
172 (unsigned long) le32_to_cpu(p->inode), 172 dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
173 rec_len, p->name_len); 173 (unsigned long) le32_to_cpu(p->inode),
174 rec_len, p->name_len);
174 goto fail; 175 goto fail;
175Eend: 176Eend:
176 p = (ext2_dirent *)(kaddr + offs); 177 if (!quiet) {
177 ext2_error (sb, "ext2_check_page", 178 p = (ext2_dirent *)(kaddr + offs);
178 "entry in directory #%lu spans the page boundary" 179 ext2_error(sb, "ext2_check_page",
179 "offset=%lu, inode=%lu", 180 "entry in directory #%lu spans the page boundary"
180 dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs, 181 "offset=%lu, inode=%lu",
181 (unsigned long) le32_to_cpu(p->inode)); 182 dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
183 (unsigned long) le32_to_cpu(p->inode));
184 }
182fail: 185fail:
183 SetPageChecked(page); 186 SetPageChecked(page);
184 SetPageError(page); 187 SetPageError(page);
185} 188}
186 189
187static struct page * ext2_get_page(struct inode *dir, unsigned long n) 190static struct page * ext2_get_page(struct inode *dir, unsigned long n,
191 int quiet)
188{ 192{
189 struct address_space *mapping = dir->i_mapping; 193 struct address_space *mapping = dir->i_mapping;
190 struct page *page = read_mapping_page(mapping, n, NULL); 194 struct page *page = read_mapping_page(mapping, n, NULL);
191 if (!IS_ERR(page)) { 195 if (!IS_ERR(page)) {
192 kmap(page); 196 kmap(page);
193 if (!PageChecked(page)) 197 if (!PageChecked(page))
194 ext2_check_page(page); 198 ext2_check_page(page, quiet);
195 if (PageError(page)) 199 if (PageError(page))
196 goto fail; 200 goto fail;
197 } 201 }
@@ -292,7 +296,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
292 for ( ; n < npages; n++, offset = 0) { 296 for ( ; n < npages; n++, offset = 0) {
293 char *kaddr, *limit; 297 char *kaddr, *limit;
294 ext2_dirent *de; 298 ext2_dirent *de;
295 struct page *page = ext2_get_page(inode, n); 299 struct page *page = ext2_get_page(inode, n, 0);
296 300
297 if (IS_ERR(page)) { 301 if (IS_ERR(page)) {
298 ext2_error(sb, __func__, 302 ext2_error(sb, __func__,
@@ -361,6 +365,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
361 struct page *page = NULL; 365 struct page *page = NULL;
362 struct ext2_inode_info *ei = EXT2_I(dir); 366 struct ext2_inode_info *ei = EXT2_I(dir);
363 ext2_dirent * de; 367 ext2_dirent * de;
368 int dir_has_error = 0;
364 369
365 if (npages == 0) 370 if (npages == 0)
366 goto out; 371 goto out;
@@ -374,7 +379,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
374 n = start; 379 n = start;
375 do { 380 do {
376 char *kaddr; 381 char *kaddr;
377 page = ext2_get_page(dir, n); 382 page = ext2_get_page(dir, n, dir_has_error);
378 if (!IS_ERR(page)) { 383 if (!IS_ERR(page)) {
379 kaddr = page_address(page); 384 kaddr = page_address(page);
380 de = (ext2_dirent *) kaddr; 385 de = (ext2_dirent *) kaddr;
@@ -391,7 +396,9 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
391 de = ext2_next_entry(de); 396 de = ext2_next_entry(de);
392 } 397 }
393 ext2_put_page(page); 398 ext2_put_page(page);
394 } 399 } else
400 dir_has_error = 1;
401
395 if (++n >= npages) 402 if (++n >= npages)
396 n = 0; 403 n = 0;
397 /* next page is past the blocks we've got */ 404 /* next page is past the blocks we've got */
@@ -414,7 +421,7 @@ found:
414 421
415struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p) 422struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
416{ 423{
417 struct page *page = ext2_get_page(dir, 0); 424 struct page *page = ext2_get_page(dir, 0, 0);
418 ext2_dirent *de = NULL; 425 ext2_dirent *de = NULL;
419 426
420 if (!IS_ERR(page)) { 427 if (!IS_ERR(page)) {
@@ -487,7 +494,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
487 for (n = 0; n <= npages; n++) { 494 for (n = 0; n <= npages; n++) {
488 char *dir_end; 495 char *dir_end;
489 496
490 page = ext2_get_page(dir, n); 497 page = ext2_get_page(dir, n, 0);
491 err = PTR_ERR(page); 498 err = PTR_ERR(page);
492 if (IS_ERR(page)) 499 if (IS_ERR(page))
493 goto out; 500 goto out;
@@ -655,14 +662,17 @@ int ext2_empty_dir (struct inode * inode)
655{ 662{
656 struct page *page = NULL; 663 struct page *page = NULL;
657 unsigned long i, npages = dir_pages(inode); 664 unsigned long i, npages = dir_pages(inode);
665 int dir_has_error = 0;
658 666
659 for (i = 0; i < npages; i++) { 667 for (i = 0; i < npages; i++) {
660 char *kaddr; 668 char *kaddr;
661 ext2_dirent * de; 669 ext2_dirent * de;
662 page = ext2_get_page(inode, i); 670 page = ext2_get_page(inode, i, dir_has_error);
663 671
664 if (IS_ERR(page)) 672 if (IS_ERR(page)) {
673 dir_has_error = 1;
665 continue; 674 continue;
675 }
666 676
667 kaddr = page_address(page); 677 kaddr = page_address(page);
668 de = (ext2_dirent *)kaddr; 678 de = (ext2_dirent *)kaddr;