Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d82abae authored by Eric Sandeen's avatar Eric Sandeen Committed by Linus Torvalds
Browse files

dir_index: error out instead of BUG on corrupt dx dirs



Convert asserts (BUGs) in dx_probe from bad on-disk data to recoverable
errors with helpful warnings.  With help catching other asserts from Duane
Griffin <duaneg@dghda.com>

Signed-off-by: default avatarEric Sandeen <sandeen@redhat.com>
Acked-by: default avatarDuane Griffin <duaneg@dghda.com>
Acked-by: default avatarTheodore Ts'o <tytso@mit.edu>
Cc: <stable@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e67aa27a
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -379,13 +379,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,

	entries = (struct dx_entry *) (((char *)&root->info) +
				       root->info.info_length);
	assert(dx_get_limit(entries) == dx_root_limit(dir,
						      root->info.info_length));

	if (dx_get_limit(entries) != dx_root_limit(dir,
						   root->info.info_length)) {
		ext3_warning(dir->i_sb, __FUNCTION__,
			     "dx entry: limit != root limit");
		brelse(bh);
		*err = ERR_BAD_DX_DIR;
		goto fail;
	}

	dxtrace (printk("Look up %x", hash));
	while (1)
	{
		count = dx_get_count(entries);
		assert (count && count <= dx_get_limit(entries));
		if (!count || count > dx_get_limit(entries)) {
			ext3_warning(dir->i_sb, __FUNCTION__,
				     "dx entry: no count or count > limit");
			brelse(bh);
			*err = ERR_BAD_DX_DIR;
			goto fail2;
		}

		p = entries + 1;
		q = entries + count - 1;
		while (p <= q)
@@ -423,8 +438,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
		if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
			goto fail2;
		at = entries = ((struct dx_node *) bh->b_data)->entries;
		assert (dx_get_limit(entries) == dx_node_limit (dir));
		if (dx_get_limit(entries) != dx_node_limit (dir)) {
			ext3_warning(dir->i_sb, __FUNCTION__,
				     "dx entry: limit != node limit");
			brelse(bh);
			*err = ERR_BAD_DX_DIR;
			goto fail2;
		}
		frame++;
		frame->bh = NULL;
	}
fail2:
	while (frame >= frame_in) {
@@ -432,6 +454,10 @@ dx_probe(struct dentry *dentry, struct inode *dir,
		frame--;
	}
fail:
	if (*err == ERR_BAD_DX_DIR)
		ext3_warning(dir->i_sb, __FUNCTION__,
			     "Corrupt dir inode %ld, running e2fsck is "
			     "recommended.", dir->i_ino);
	return NULL;
}

+30 −4
Original line number Diff line number Diff line
@@ -379,13 +379,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,

	entries = (struct dx_entry *) (((char *)&root->info) +
				       root->info.info_length);
	assert(dx_get_limit(entries) == dx_root_limit(dir,
						      root->info.info_length));

	if (dx_get_limit(entries) != dx_root_limit(dir,
						   root->info.info_length)) {
		ext4_warning(dir->i_sb, __FUNCTION__,
			     "dx entry: limit != root limit");
		brelse(bh);
		*err = ERR_BAD_DX_DIR;
		goto fail;
	}

	dxtrace (printk("Look up %x", hash));
	while (1)
	{
		count = dx_get_count(entries);
		assert (count && count <= dx_get_limit(entries));
		if (!count || count > dx_get_limit(entries)) {
			ext4_warning(dir->i_sb, __FUNCTION__,
				     "dx entry: no count or count > limit");
			brelse(bh);
			*err = ERR_BAD_DX_DIR;
			goto fail2;
		}

		p = entries + 1;
		q = entries + count - 1;
		while (p <= q)
@@ -423,8 +438,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
		if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
			goto fail2;
		at = entries = ((struct dx_node *) bh->b_data)->entries;
		assert (dx_get_limit(entries) == dx_node_limit (dir));
		if (dx_get_limit(entries) != dx_node_limit (dir)) {
			ext4_warning(dir->i_sb, __FUNCTION__,
				     "dx entry: limit != node limit");
			brelse(bh);
			*err = ERR_BAD_DX_DIR;
			goto fail2;
		}
		frame++;
		frame->bh = NULL;
	}
fail2:
	while (frame >= frame_in) {
@@ -432,6 +454,10 @@ dx_probe(struct dentry *dentry, struct inode *dir,
		frame--;
	}
fail:
	if (*err == ERR_BAD_DX_DIR)
		ext4_warning(dir->i_sb, __FUNCTION__,
			     "Corrupt dir inode %ld, running e2fsck is "
			     "recommended.", dir->i_ino);
	return NULL;
}