diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-05-09 23:55:38 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-05-09 23:55:38 -0700 |
| commit | e461abeb62ef330c4c1b1e9dae2a0a7a10213e79 (patch) | |
| tree | 1531642dd5dff91d67cda4a5871760188679722d /fs/ext3 | |
| parent | a7c8a1d320ff544a044f6fac5c7fda557f5ef60c (diff) | |
[PATCH] ext3 error handling fixes
From: Andreas Dilger <adilger@clusterfs.com>
a) we don't call ext3_error() for an IO error in ext3_find_entry(), so we
won't do the normal ext3 error handling (mark SB in error, remount-ro
or panic if desired);
b) in empty_dir() we don't continue checking for non-empty blocks after a
content error (ext3_check_dir_entry() calls ext3_error() already);
c) we had decided not to mark the SB in error for holes in directories to
allow leway in the indexed-directory implementation, but this change
incorrectly also disabled marking the SB in error for real IO errors.
Diffstat (limited to 'fs/ext3')
| -rw-r--r-- | fs/ext3/namei.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 6ed3d4ff2bd9..4da226dd9e65 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -872,6 +872,8 @@ restart: wait_on_buffer(bh); if (!buffer_uptodate(bh)) { /* read error, skip block & hope for the best */ + ext3_error(sb, __FUNCTION__, "reading directory #%lu " + "offset %lu\n", dir->i_ino, block); brelse(bh); goto next; } @@ -1763,14 +1765,19 @@ static int empty_dir (struct inode * inode) struct buffer_head * bh; struct ext3_dir_entry_2 * de, * de1; struct super_block * sb; - int err; + int err = 0; sb = inode->i_sb; if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) || !(bh = ext3_bread (NULL, inode, 0, 0, &err))) { - ext3_warning (inode->i_sb, "empty_dir", - "bad directory (dir #%lu) - no data block", - inode->i_ino); + if (err) + ext3_error(inode->i_sb, __FUNCTION__, + "error %d reading directory #%lu offset 0", + err, inode->i_ino); + else + ext3_warning(inode->i_sb, __FUNCTION__, + "bad directory (dir #%lu) - no data block", + inode->i_ino); return 1; } de = (struct ext3_dir_entry_2 *) bh->b_data; @@ -1792,24 +1799,26 @@ static int empty_dir (struct inode * inode) while (offset < inode->i_size ) { if (!bh || (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { + err = 0; brelse (bh); bh = ext3_bread (NULL, inode, offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err); if (!bh) { -#if 0 - ext3_error (sb, "empty_dir", - "directory #%lu contains a hole at offset %lu", - inode->i_ino, offset); -#endif + if (err) + ext3_error(sb, __FUNCTION__, + "error %d reading directory" + " #%lu offset %lu", + err, inode->i_ino, offset); offset += sb->s_blocksize; continue; } de = (struct ext3_dir_entry_2 *) bh->b_data; } - if (!ext3_check_dir_entry ("empty_dir", inode, de, bh, - offset)) { - brelse (bh); - return 1; + if (!ext3_check_dir_entry("empty_dir", inode, de, bh, offset)) { + de = (struct ext3_dir_entry_2 *)(bh->b_data + + sb->s_blocksize); + offset = (offset | (sb->s_blocksize - 1)) + 1; + continue; } if (le32_to_cpu(de->inode)) { brelse (bh); |
