Commit e461abeb authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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.
parent a7c8a1d3
...@@ -872,6 +872,8 @@ static struct buffer_head * ext3_find_entry (struct dentry *dentry, ...@@ -872,6 +872,8 @@ static struct buffer_head * ext3_find_entry (struct dentry *dentry,
wait_on_buffer(bh); wait_on_buffer(bh);
if (!buffer_uptodate(bh)) { if (!buffer_uptodate(bh)) {
/* read error, skip block & hope for the best */ /* read error, skip block & hope for the best */
ext3_error(sb, __FUNCTION__, "reading directory #%lu "
"offset %lu\n", dir->i_ino, block);
brelse(bh); brelse(bh);
goto next; goto next;
} }
...@@ -1763,14 +1765,19 @@ static int empty_dir (struct inode * inode) ...@@ -1763,14 +1765,19 @@ static int empty_dir (struct inode * inode)
struct buffer_head * bh; struct buffer_head * bh;
struct ext3_dir_entry_2 * de, * de1; struct ext3_dir_entry_2 * de, * de1;
struct super_block * sb; struct super_block * sb;
int err; int err = 0;
sb = inode->i_sb; sb = inode->i_sb;
if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) || if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) ||
!(bh = ext3_bread (NULL, inode, 0, 0, &err))) { !(bh = ext3_bread (NULL, inode, 0, 0, &err))) {
ext3_warning (inode->i_sb, "empty_dir", if (err)
"bad directory (dir #%lu) - no data block", ext3_error(inode->i_sb, __FUNCTION__,
inode->i_ino); "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; return 1;
} }
de = (struct ext3_dir_entry_2 *) bh->b_data; de = (struct ext3_dir_entry_2 *) bh->b_data;
...@@ -1792,24 +1799,26 @@ static int empty_dir (struct inode * inode) ...@@ -1792,24 +1799,26 @@ static int empty_dir (struct inode * inode)
while (offset < inode->i_size ) { while (offset < inode->i_size ) {
if (!bh || if (!bh ||
(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
err = 0;
brelse (bh); brelse (bh);
bh = ext3_bread (NULL, inode, bh = ext3_bread (NULL, inode,
offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err); offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err);
if (!bh) { if (!bh) {
#if 0 if (err)
ext3_error (sb, "empty_dir", ext3_error(sb, __FUNCTION__,
"directory #%lu contains a hole at offset %lu", "error %d reading directory"
inode->i_ino, offset); " #%lu offset %lu",
#endif err, inode->i_ino, offset);
offset += sb->s_blocksize; offset += sb->s_blocksize;
continue; continue;
} }
de = (struct ext3_dir_entry_2 *) bh->b_data; de = (struct ext3_dir_entry_2 *) bh->b_data;
} }
if (!ext3_check_dir_entry ("empty_dir", inode, de, bh, if (!ext3_check_dir_entry("empty_dir", inode, de, bh, offset)) {
offset)) { de = (struct ext3_dir_entry_2 *)(bh->b_data +
brelse (bh); sb->s_blocksize);
return 1; offset = (offset | (sb->s_blocksize - 1)) + 1;
continue;
} }
if (le32_to_cpu(de->inode)) { if (le32_to_cpu(de->inode)) {
brelse (bh); brelse (bh);
......
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