Commit 9da1f6d0 authored by Theodore Ts'o's avatar Theodore Ts'o Committed by Greg Kroah-Hartman

ext4: add ext4_sb_bread() to disambiguate ENOMEM cases

commit fb265c9c upstream.

Today, when sb_bread() returns NULL, this can either be because of an
I/O error or because the system failed to allocate the buffer.  Since
it's an old interface, changing would require changing many call
sites.

So instead we create our own ext4_sb_bread(), which also allows us to
set the REQ_META flag.

Also fixed a problem in the xattr code where a NULL return in a
function could also mean that the xattr was not found, which could
lead to the wrong error getting returned to userspace.

Fixes: ac27a0ec ("ext4: initial copy of files from ext3")
Cc: stable@kernel.org # 2.6.19
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9f0fc584
...@@ -2568,6 +2568,8 @@ extern int ext4_group_extend(struct super_block *sb, ...@@ -2568,6 +2568,8 @@ extern int ext4_group_extend(struct super_block *sb,
extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
/* super.c */ /* super.c */
extern struct buffer_head *ext4_sb_bread(struct super_block *sb,
sector_t block, int op_flags);
extern int ext4_seq_options_show(struct seq_file *seq, void *offset); extern int ext4_seq_options_show(struct seq_file *seq, void *offset);
extern int ext4_calculate_overhead(struct super_block *sb); extern int ext4_calculate_overhead(struct super_block *sb);
extern void ext4_superblock_csum_set(struct super_block *sb); extern void ext4_superblock_csum_set(struct super_block *sb);
......
...@@ -123,9 +123,9 @@ static int update_ind_extent_range(handle_t *handle, struct inode *inode, ...@@ -123,9 +123,9 @@ static int update_ind_extent_range(handle_t *handle, struct inode *inode,
int i, retval = 0; int i, retval = 0;
unsigned long max_entries = inode->i_sb->s_blocksize >> 2; unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
bh = sb_bread(inode->i_sb, pblock); bh = ext4_sb_bread(inode->i_sb, pblock, 0);
if (!bh) if (IS_ERR(bh))
return -EIO; return PTR_ERR(bh);
i_data = (__le32 *)bh->b_data; i_data = (__le32 *)bh->b_data;
for (i = 0; i < max_entries; i++) { for (i = 0; i < max_entries; i++) {
...@@ -152,9 +152,9 @@ static int update_dind_extent_range(handle_t *handle, struct inode *inode, ...@@ -152,9 +152,9 @@ static int update_dind_extent_range(handle_t *handle, struct inode *inode,
int i, retval = 0; int i, retval = 0;
unsigned long max_entries = inode->i_sb->s_blocksize >> 2; unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
bh = sb_bread(inode->i_sb, pblock); bh = ext4_sb_bread(inode->i_sb, pblock, 0);
if (!bh) if (IS_ERR(bh))
return -EIO; return PTR_ERR(bh);
i_data = (__le32 *)bh->b_data; i_data = (__le32 *)bh->b_data;
for (i = 0; i < max_entries; i++) { for (i = 0; i < max_entries; i++) {
...@@ -182,9 +182,9 @@ static int update_tind_extent_range(handle_t *handle, struct inode *inode, ...@@ -182,9 +182,9 @@ static int update_tind_extent_range(handle_t *handle, struct inode *inode,
int i, retval = 0; int i, retval = 0;
unsigned long max_entries = inode->i_sb->s_blocksize >> 2; unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
bh = sb_bread(inode->i_sb, pblock); bh = ext4_sb_bread(inode->i_sb, pblock, 0);
if (!bh) if (IS_ERR(bh))
return -EIO; return PTR_ERR(bh);
i_data = (__le32 *)bh->b_data; i_data = (__le32 *)bh->b_data;
for (i = 0; i < max_entries; i++) { for (i = 0; i < max_entries; i++) {
...@@ -231,9 +231,9 @@ static int free_dind_blocks(handle_t *handle, ...@@ -231,9 +231,9 @@ static int free_dind_blocks(handle_t *handle,
struct buffer_head *bh; struct buffer_head *bh;
unsigned long max_entries = inode->i_sb->s_blocksize >> 2; unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
bh = sb_bread(inode->i_sb, le32_to_cpu(i_data)); bh = ext4_sb_bread(inode->i_sb, le32_to_cpu(i_data), 0);
if (!bh) if (IS_ERR(bh))
return -EIO; return PTR_ERR(bh);
tmp_idata = (__le32 *)bh->b_data; tmp_idata = (__le32 *)bh->b_data;
for (i = 0; i < max_entries; i++) { for (i = 0; i < max_entries; i++) {
...@@ -261,9 +261,9 @@ static int free_tind_blocks(handle_t *handle, ...@@ -261,9 +261,9 @@ static int free_tind_blocks(handle_t *handle,
struct buffer_head *bh; struct buffer_head *bh;
unsigned long max_entries = inode->i_sb->s_blocksize >> 2; unsigned long max_entries = inode->i_sb->s_blocksize >> 2;
bh = sb_bread(inode->i_sb, le32_to_cpu(i_data)); bh = ext4_sb_bread(inode->i_sb, le32_to_cpu(i_data), 0);
if (!bh) if (IS_ERR(bh))
return -EIO; return PTR_ERR(bh);
tmp_idata = (__le32 *)bh->b_data; tmp_idata = (__le32 *)bh->b_data;
for (i = 0; i < max_entries; i++) { for (i = 0; i < max_entries; i++) {
...@@ -389,9 +389,9 @@ static int free_ext_idx(handle_t *handle, struct inode *inode, ...@@ -389,9 +389,9 @@ static int free_ext_idx(handle_t *handle, struct inode *inode,
struct ext4_extent_header *eh; struct ext4_extent_header *eh;
block = ext4_idx_pblock(ix); block = ext4_idx_pblock(ix);
bh = sb_bread(inode->i_sb, block); bh = ext4_sb_bread(inode->i_sb, block, 0);
if (!bh) if (IS_ERR(bh))
return -EIO; return PTR_ERR(bh);
eh = (struct ext4_extent_header *)bh->b_data; eh = (struct ext4_extent_header *)bh->b_data;
if (eh->eh_depth != 0) { if (eh->eh_depth != 0) {
......
...@@ -127,10 +127,12 @@ static int verify_group_input(struct super_block *sb, ...@@ -127,10 +127,12 @@ static int verify_group_input(struct super_block *sb,
else if (free_blocks_count < 0) else if (free_blocks_count < 0)
ext4_warning(sb, "Bad blocks count %u", ext4_warning(sb, "Bad blocks count %u",
input->blocks_count); input->blocks_count);
else if (!(bh = sb_bread(sb, end - 1))) else if (IS_ERR(bh = ext4_sb_bread(sb, end - 1, 0))) {
err = PTR_ERR(bh);
bh = NULL;
ext4_warning(sb, "Cannot read last block (%llu)", ext4_warning(sb, "Cannot read last block (%llu)",
end - 1); end - 1);
else if (outside(input->block_bitmap, start, end)) } else if (outside(input->block_bitmap, start, end))
ext4_warning(sb, "Block bitmap not in group (block %llu)", ext4_warning(sb, "Block bitmap not in group (block %llu)",
(unsigned long long)input->block_bitmap); (unsigned long long)input->block_bitmap);
else if (outside(input->inode_bitmap, start, end)) else if (outside(input->inode_bitmap, start, end))
...@@ -757,11 +759,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -757,11 +759,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
struct ext4_super_block *es = EXT4_SB(sb)->s_es; struct ext4_super_block *es = EXT4_SB(sb)->s_es;
unsigned long gdb_num = group / EXT4_DESC_PER_BLOCK(sb); unsigned long gdb_num = group / EXT4_DESC_PER_BLOCK(sb);
ext4_fsblk_t gdblock = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num; ext4_fsblk_t gdblock = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num;
struct buffer_head **o_group_desc, **n_group_desc; struct buffer_head **o_group_desc, **n_group_desc = NULL;
struct buffer_head *dind; struct buffer_head *dind = NULL;
struct buffer_head *gdb_bh; struct buffer_head *gdb_bh = NULL;
int gdbackups; int gdbackups;
struct ext4_iloc iloc; struct ext4_iloc iloc = { .bh = NULL };
__le32 *data; __le32 *data;
int err; int err;
...@@ -770,21 +772,22 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -770,21 +772,22 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
"EXT4-fs: ext4_add_new_gdb: adding group block %lu\n", "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n",
gdb_num); gdb_num);
gdb_bh = sb_bread(sb, gdblock); gdb_bh = ext4_sb_bread(sb, gdblock, 0);
if (!gdb_bh) if (IS_ERR(gdb_bh))
return -EIO; return PTR_ERR(gdb_bh);
gdbackups = verify_reserved_gdb(sb, group, gdb_bh); gdbackups = verify_reserved_gdb(sb, group, gdb_bh);
if (gdbackups < 0) { if (gdbackups < 0) {
err = gdbackups; err = gdbackups;
goto exit_bh; goto errout;
} }
data = EXT4_I(inode)->i_data + EXT4_DIND_BLOCK; data = EXT4_I(inode)->i_data + EXT4_DIND_BLOCK;
dind = sb_bread(sb, le32_to_cpu(*data)); dind = ext4_sb_bread(sb, le32_to_cpu(*data), 0);
if (!dind) { if (IS_ERR(dind)) {
err = -EIO; err = PTR_ERR(dind);
goto exit_bh; dind = NULL;
goto errout;
} }
data = (__le32 *)dind->b_data; data = (__le32 *)dind->b_data;
...@@ -792,18 +795,18 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -792,18 +795,18 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
ext4_warning(sb, "new group %u GDT block %llu not reserved", ext4_warning(sb, "new group %u GDT block %llu not reserved",
group, gdblock); group, gdblock);
err = -EINVAL; err = -EINVAL;
goto exit_dind; goto errout;
} }
BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access"); BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get_write_access");
err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh); err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
if (unlikely(err)) if (unlikely(err))
goto exit_dind; goto errout;
BUFFER_TRACE(gdb_bh, "get_write_access"); BUFFER_TRACE(gdb_bh, "get_write_access");
err = ext4_journal_get_write_access(handle, gdb_bh); err = ext4_journal_get_write_access(handle, gdb_bh);
if (unlikely(err)) if (unlikely(err))
goto exit_dind; goto errout;
BUFFER_TRACE(dind, "get_write_access"); BUFFER_TRACE(dind, "get_write_access");
err = ext4_journal_get_write_access(handle, dind); err = ext4_journal_get_write_access(handle, dind);
...@@ -813,7 +816,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -813,7 +816,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
/* ext4_reserve_inode_write() gets a reference on the iloc */ /* ext4_reserve_inode_write() gets a reference on the iloc */
err = ext4_reserve_inode_write(handle, inode, &iloc); err = ext4_reserve_inode_write(handle, inode, &iloc);
if (unlikely(err)) if (unlikely(err))
goto exit_dind; goto errout;
n_group_desc = ext4_kvmalloc((gdb_num + 1) * n_group_desc = ext4_kvmalloc((gdb_num + 1) *
sizeof(struct buffer_head *), sizeof(struct buffer_head *),
...@@ -822,7 +825,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -822,7 +825,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
err = -ENOMEM; err = -ENOMEM;
ext4_warning(sb, "not enough memory for %lu groups", ext4_warning(sb, "not enough memory for %lu groups",
gdb_num + 1); gdb_num + 1);
goto exit_inode; goto errout;
} }
/* /*
...@@ -838,7 +841,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -838,7 +841,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
err = ext4_handle_dirty_metadata(handle, NULL, dind); err = ext4_handle_dirty_metadata(handle, NULL, dind);
if (unlikely(err)) { if (unlikely(err)) {
ext4_std_error(sb, err); ext4_std_error(sb, err);
goto exit_inode; goto errout;
} }
inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9;
ext4_mark_iloc_dirty(handle, inode, &iloc); ext4_mark_iloc_dirty(handle, inode, &iloc);
...@@ -846,8 +849,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -846,8 +849,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh); err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh);
if (unlikely(err)) { if (unlikely(err)) {
ext4_std_error(sb, err); ext4_std_error(sb, err);
iloc.bh = NULL; goto errout;
goto exit_inode;
} }
brelse(dind); brelse(dind);
...@@ -863,15 +865,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ...@@ -863,15 +865,11 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
err = ext4_handle_dirty_super(handle, sb); err = ext4_handle_dirty_super(handle, sb);
if (err) if (err)
ext4_std_error(sb, err); ext4_std_error(sb, err);
return err; return err;
errout:
exit_inode:
kvfree(n_group_desc); kvfree(n_group_desc);
brelse(iloc.bh); brelse(iloc.bh);
exit_dind:
brelse(dind); brelse(dind);
exit_bh:
brelse(gdb_bh); brelse(gdb_bh);
ext4_debug("leaving with error %d\n", err); ext4_debug("leaving with error %d\n", err);
...@@ -891,9 +889,9 @@ static int add_new_gdb_meta_bg(struct super_block *sb, ...@@ -891,9 +889,9 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
gdblock = ext4_meta_bg_first_block_no(sb, group) + gdblock = ext4_meta_bg_first_block_no(sb, group) +
ext4_bg_has_super(sb, group); ext4_bg_has_super(sb, group);
gdb_bh = sb_bread(sb, gdblock); gdb_bh = ext4_sb_bread(sb, gdblock, 0);
if (!gdb_bh) if (IS_ERR(gdb_bh))
return -EIO; return PTR_ERR(gdb_bh);
n_group_desc = ext4_kvmalloc((gdb_num + 1) * n_group_desc = ext4_kvmalloc((gdb_num + 1) *
sizeof(struct buffer_head *), sizeof(struct buffer_head *),
GFP_NOFS); GFP_NOFS);
...@@ -949,9 +947,10 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, ...@@ -949,9 +947,10 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
return -ENOMEM; return -ENOMEM;
data = EXT4_I(inode)->i_data + EXT4_DIND_BLOCK; data = EXT4_I(inode)->i_data + EXT4_DIND_BLOCK;
dind = sb_bread(sb, le32_to_cpu(*data)); dind = ext4_sb_bread(sb, le32_to_cpu(*data), 0);
if (!dind) { if (IS_ERR(dind)) {
err = -EIO; err = PTR_ERR(dind);
dind = NULL;
goto exit_free; goto exit_free;
} }
...@@ -970,9 +969,10 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, ...@@ -970,9 +969,10 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
err = -EINVAL; err = -EINVAL;
goto exit_bh; goto exit_bh;
} }
primary[res] = sb_bread(sb, blk); primary[res] = ext4_sb_bread(sb, blk, 0);
if (!primary[res]) { if (IS_ERR(primary[res])) {
err = -EIO; err = PTR_ERR(primary[res]);
primary[res] = NULL;
goto exit_bh; goto exit_bh;
} }
gdbackups = verify_reserved_gdb(sb, group, primary[res]); gdbackups = verify_reserved_gdb(sb, group, primary[res]);
......
...@@ -140,6 +140,29 @@ MODULE_ALIAS_FS("ext3"); ...@@ -140,6 +140,29 @@ MODULE_ALIAS_FS("ext3");
MODULE_ALIAS("ext3"); MODULE_ALIAS("ext3");
#define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type) #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
/*
* This works like sb_bread() except it uses ERR_PTR for error
* returns. Currently with sb_bread it's impossible to distinguish
* between ENOMEM and EIO situations (since both result in a NULL
* return.
*/
struct buffer_head *
ext4_sb_bread(struct super_block *sb, sector_t block, int op_flags)
{
struct buffer_head *bh = sb_getblk(sb, block);
if (bh == NULL)
return ERR_PTR(-ENOMEM);
if (buffer_uptodate(bh))
return bh;
ll_rw_block(REQ_OP_READ, REQ_META | op_flags, 1, &bh);
wait_on_buffer(bh);
if (buffer_uptodate(bh))
return bh;
put_bh(bh);
return ERR_PTR(-EIO);
}
static int ext4_verify_csum_type(struct super_block *sb, static int ext4_verify_csum_type(struct super_block *sb,
struct ext4_super_block *es) struct ext4_super_block *es)
{ {
......
...@@ -521,14 +521,13 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name, ...@@ -521,14 +521,13 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld", ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
name_index, name, buffer, (long)buffer_size); name_index, name, buffer, (long)buffer_size);
error = -ENODATA;
if (!EXT4_I(inode)->i_file_acl) if (!EXT4_I(inode)->i_file_acl)
goto cleanup; return -ENODATA;
ea_idebug(inode, "reading block %llu", ea_idebug(inode, "reading block %llu",
(unsigned long long)EXT4_I(inode)->i_file_acl); (unsigned long long)EXT4_I(inode)->i_file_acl);
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
if (!bh) if (IS_ERR(bh))
goto cleanup; return PTR_ERR(bh);
ea_bdebug(bh, "b_count=%d, refcount=%d", ea_bdebug(bh, "b_count=%d, refcount=%d",
atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount)); atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
error = ext4_xattr_check_block(inode, bh); error = ext4_xattr_check_block(inode, bh);
...@@ -695,26 +694,23 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -695,26 +694,23 @@ ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
ea_idebug(inode, "buffer=%p, buffer_size=%ld", ea_idebug(inode, "buffer=%p, buffer_size=%ld",
buffer, (long)buffer_size); buffer, (long)buffer_size);
error = 0;
if (!EXT4_I(inode)->i_file_acl) if (!EXT4_I(inode)->i_file_acl)
goto cleanup; return 0;
ea_idebug(inode, "reading block %llu", ea_idebug(inode, "reading block %llu",
(unsigned long long)EXT4_I(inode)->i_file_acl); (unsigned long long)EXT4_I(inode)->i_file_acl);
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
error = -EIO; if (IS_ERR(bh))
if (!bh) return PTR_ERR(bh);
goto cleanup;
ea_bdebug(bh, "b_count=%d, refcount=%d", ea_bdebug(bh, "b_count=%d, refcount=%d",
atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount)); atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
error = ext4_xattr_check_block(inode, bh); error = ext4_xattr_check_block(inode, bh);
if (error) if (error)
goto cleanup; goto cleanup;
ext4_xattr_block_cache_insert(EA_BLOCK_CACHE(inode), bh); ext4_xattr_block_cache_insert(EA_BLOCK_CACHE(inode), bh);
error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size); error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer,
buffer_size);
cleanup: cleanup:
brelse(bh); brelse(bh);
return error; return error;
} }
...@@ -829,9 +825,9 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage) ...@@ -829,9 +825,9 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
} }
if (EXT4_I(inode)->i_file_acl) { if (EXT4_I(inode)->i_file_acl) {
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
if (!bh) { if (IS_ERR(bh)) {
ret = -EIO; ret = PTR_ERR(bh);
goto out; goto out;
} }
...@@ -1824,16 +1820,15 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i, ...@@ -1824,16 +1820,15 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
if (EXT4_I(inode)->i_file_acl) { if (EXT4_I(inode)->i_file_acl) {
/* The inode already has an extended attribute block. */ /* The inode already has an extended attribute block. */
bs->bh = sb_bread(sb, EXT4_I(inode)->i_file_acl); bs->bh = ext4_sb_bread(sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
error = -EIO; if (IS_ERR(bs->bh))
if (!bs->bh) return PTR_ERR(bs->bh);
goto cleanup;
ea_bdebug(bs->bh, "b_count=%d, refcount=%d", ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
atomic_read(&(bs->bh->b_count)), atomic_read(&(bs->bh->b_count)),
le32_to_cpu(BHDR(bs->bh)->h_refcount)); le32_to_cpu(BHDR(bs->bh)->h_refcount));
error = ext4_xattr_check_block(inode, bs->bh); error = ext4_xattr_check_block(inode, bs->bh);
if (error) if (error)
goto cleanup; return error;
/* Find the named attribute. */ /* Find the named attribute. */
bs->s.base = BHDR(bs->bh); bs->s.base = BHDR(bs->bh);
bs->s.first = BFIRST(bs->bh); bs->s.first = BFIRST(bs->bh);
...@@ -1842,13 +1837,10 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i, ...@@ -1842,13 +1837,10 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
error = xattr_find_entry(inode, &bs->s.here, bs->s.end, error = xattr_find_entry(inode, &bs->s.here, bs->s.end,
i->name_index, i->name, 1); i->name_index, i->name, 1);
if (error && error != -ENODATA) if (error && error != -ENODATA)
goto cleanup; return error;
bs->s.not_found = error; bs->s.not_found = error;
} }
error = 0; return 0;
cleanup:
return error;
} }
static int static int
...@@ -2277,9 +2269,9 @@ static struct buffer_head *ext4_xattr_get_block(struct inode *inode) ...@@ -2277,9 +2269,9 @@ static struct buffer_head *ext4_xattr_get_block(struct inode *inode)
if (!EXT4_I(inode)->i_file_acl) if (!EXT4_I(inode)->i_file_acl)
return NULL; return NULL;
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
if (!bh) if (IS_ERR(bh))
return ERR_PTR(-EIO); return bh;
error = ext4_xattr_check_block(inode, bh); error = ext4_xattr_check_block(inode, bh);
if (error) { if (error) {
brelse(bh); brelse(bh);
...@@ -2749,10 +2741,11 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, ...@@ -2749,10 +2741,11 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
if (EXT4_I(inode)->i_file_acl) { if (EXT4_I(inode)->i_file_acl) {
struct buffer_head *bh; struct buffer_head *bh;
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
error = -EIO; if (IS_ERR(bh)) {
if (!bh) error = PTR_ERR(bh);
goto cleanup; goto cleanup;
}
error = ext4_xattr_check_block(inode, bh); error = ext4_xattr_check_block(inode, bh);
if (error) { if (error) {
brelse(bh); brelse(bh);
...@@ -2906,11 +2899,12 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, ...@@ -2906,11 +2899,12 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
} }
if (EXT4_I(inode)->i_file_acl) { if (EXT4_I(inode)->i_file_acl) {
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl); bh = ext4_sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
if (!bh) { if (IS_ERR(bh)) {
EXT4_ERROR_INODE(inode, "block %llu read error", error = PTR_ERR(bh);
EXT4_I(inode)->i_file_acl); if (error == -EIO)
error = -EIO; EXT4_ERROR_INODE(inode, "block %llu read error",
EXT4_I(inode)->i_file_acl);
goto cleanup; goto cleanup;
} }
error = ext4_xattr_check_block(inode, bh); error = ext4_xattr_check_block(inode, bh);
...@@ -3063,8 +3057,10 @@ ext4_xattr_block_cache_find(struct inode *inode, ...@@ -3063,8 +3057,10 @@ ext4_xattr_block_cache_find(struct inode *inode,
while (ce) { while (ce) {
struct buffer_head *bh; struct buffer_head *bh;
bh = sb_bread(inode->i_sb, ce->e_value); bh = ext4_sb_bread(inode->i_sb, ce->e_value, REQ_PRIO);
if (!bh) { if (IS_ERR(bh)) {
if (PTR_ERR(bh) == -ENOMEM)
return NULL;
EXT4_ERROR_INODE(inode, "block %lu read error", EXT4_ERROR_INODE(inode, "block %lu read error",
(unsigned long)ce->e_value); (unsigned long)ce->e_value);
} else if (ext4_xattr_cmp(header, BHDR(bh)) == 0) { } else if (ext4_xattr_cmp(header, BHDR(bh)) == 0) {
......
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