diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/ext4.h | 10 | ||||
-rw-r--r-- | fs/ext4/inode.c | 13 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 41 | ||||
-rw-r--r-- | fs/ext4/super.c | 13 |
4 files changed, 45 insertions, 32 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index d8ec824f5a25..5a41881cafca 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1639,9 +1639,13 @@ extern void __ext4_warning(struct super_block *, const char *, | |||
1639 | #define ext4_warning(sb, message...) __ext4_warning(sb, __func__, ## message) | 1639 | #define ext4_warning(sb, message...) __ext4_warning(sb, __func__, ## message) |
1640 | extern void ext4_msg(struct super_block *, const char *, const char *, ...) | 1640 | extern void ext4_msg(struct super_block *, const char *, const char *, ...) |
1641 | __attribute__ ((format (printf, 3, 4))); | 1641 | __attribute__ ((format (printf, 3, 4))); |
1642 | extern void ext4_grp_locked_error(struct super_block *, ext4_group_t, | 1642 | extern void __ext4_grp_locked_error(const char *, unsigned int, \ |
1643 | const char *, const char *, ...) | 1643 | struct super_block *, ext4_group_t, \ |
1644 | __attribute__ ((format (printf, 4, 5))); | 1644 | unsigned long, ext4_fsblk_t, \ |
1645 | const char *, ...) | ||
1646 | __attribute__ ((format (printf, 7, 8))); | ||
1647 | #define ext4_grp_locked_error(sb, grp, message...) \ | ||
1648 | __ext4_grp_locked_error(__func__, __LINE__, (sb), (grp), ## message) | ||
1645 | extern void ext4_update_dynamic_rev(struct super_block *sb); | 1649 | extern void ext4_update_dynamic_rev(struct super_block *sb); |
1646 | extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb, | 1650 | extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb, |
1647 | __u32 compat); | 1651 | __u32 compat); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b485987f0146..64baadb4956d 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1128,8 +1128,8 @@ void ext4_da_update_reserve_space(struct inode *inode, | |||
1128 | ext4_discard_preallocations(inode); | 1128 | ext4_discard_preallocations(inode); |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | static int check_block_validity(struct inode *inode, const char *func, | 1131 | static int __check_block_validity(struct inode *inode, const char *func, |
1132 | struct ext4_map_blocks *map) | 1132 | struct ext4_map_blocks *map) |
1133 | { | 1133 | { |
1134 | if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, | 1134 | if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, |
1135 | map->m_len)) { | 1135 | map->m_len)) { |
@@ -1142,6 +1142,9 @@ static int check_block_validity(struct inode *inode, const char *func, | |||
1142 | return 0; | 1142 | return 0; |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | #define check_block_validity(inode, map) \ | ||
1146 | __check_block_validity((inode), __func__, (map)) | ||
1147 | |||
1145 | /* | 1148 | /* |
1146 | * Return the number of contiguous dirty pages in a given inode | 1149 | * Return the number of contiguous dirty pages in a given inode |
1147 | * starting at page frame idx. | 1150 | * starting at page frame idx. |
@@ -1244,7 +1247,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
1244 | up_read((&EXT4_I(inode)->i_data_sem)); | 1247 | up_read((&EXT4_I(inode)->i_data_sem)); |
1245 | 1248 | ||
1246 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { | 1249 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { |
1247 | int ret = check_block_validity(inode, __func__, map); | 1250 | int ret = check_block_validity(inode, map); |
1248 | if (ret != 0) | 1251 | if (ret != 0) |
1249 | return ret; | 1252 | return ret; |
1250 | } | 1253 | } |
@@ -1324,9 +1327,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
1324 | 1327 | ||
1325 | up_write((&EXT4_I(inode)->i_data_sem)); | 1328 | up_write((&EXT4_I(inode)->i_data_sem)); |
1326 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { | 1329 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { |
1327 | int ret = check_block_validity(inode, | 1330 | int ret = check_block_validity(inode, map); |
1328 | "ext4_map_blocks_after_alloc", | ||
1329 | map); | ||
1330 | if (ret != 0) | 1331 | if (ret != 0) |
1331 | return ret; | 1332 | return ret; |
1332 | } | 1333 | } |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index b2948b047973..3dfad95f0f98 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -446,10 +446,11 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b, | |||
446 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); | 446 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); |
447 | blocknr += first + i; | 447 | blocknr += first + i; |
448 | ext4_grp_locked_error(sb, e4b->bd_group, | 448 | ext4_grp_locked_error(sb, e4b->bd_group, |
449 | __func__, "double-free of inode" | 449 | inode ? inode->i_ino : 0, |
450 | " %lu's block %llu(bit %u in group %u)", | 450 | blocknr, |
451 | inode ? inode->i_ino : 0, blocknr, | 451 | "freeing block already freed " |
452 | first + i, e4b->bd_group); | 452 | "(bit %u)", |
453 | first + i); | ||
453 | } | 454 | } |
454 | mb_clear_bit(first + i, e4b->bd_info->bb_bitmap); | 455 | mb_clear_bit(first + i, e4b->bd_info->bb_bitmap); |
455 | } | 456 | } |
@@ -712,9 +713,9 @@ void ext4_mb_generate_buddy(struct super_block *sb, | |||
712 | grp->bb_fragments = fragments; | 713 | grp->bb_fragments = fragments; |
713 | 714 | ||
714 | if (free != grp->bb_free) { | 715 | if (free != grp->bb_free) { |
715 | ext4_grp_locked_error(sb, group, __func__, | 716 | ext4_grp_locked_error(sb, group, 0, 0, |
716 | "EXT4-fs: group %u: %u blocks in bitmap, %u in gd", | 717 | "%u blocks in bitmap, %u in gd", |
717 | group, free, grp->bb_free); | 718 | free, grp->bb_free); |
718 | /* | 719 | /* |
719 | * If we intent to continue, we consider group descritor | 720 | * If we intent to continue, we consider group descritor |
720 | * corrupt and update bb_free using bitmap value | 721 | * corrupt and update bb_free using bitmap value |
@@ -1296,10 +1297,10 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, | |||
1296 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); | 1297 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); |
1297 | blocknr += block; | 1298 | blocknr += block; |
1298 | ext4_grp_locked_error(sb, e4b->bd_group, | 1299 | ext4_grp_locked_error(sb, e4b->bd_group, |
1299 | __func__, "double-free of inode" | 1300 | inode ? inode->i_ino : 0, |
1300 | " %lu's block %llu(bit %u in group %u)", | 1301 | blocknr, |
1301 | inode ? inode->i_ino : 0, blocknr, block, | 1302 | "freeing already freed block " |
1302 | e4b->bd_group); | 1303 | "(bit %u)", block); |
1303 | } | 1304 | } |
1304 | mb_clear_bit(block, EXT4_MB_BITMAP(e4b)); | 1305 | mb_clear_bit(block, EXT4_MB_BITMAP(e4b)); |
1305 | e4b->bd_info->bb_counters[order]++; | 1306 | e4b->bd_info->bb_counters[order]++; |
@@ -1788,8 +1789,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1788 | * free blocks even though group info says we | 1789 | * free blocks even though group info says we |
1789 | * we have free blocks | 1790 | * we have free blocks |
1790 | */ | 1791 | */ |
1791 | ext4_grp_locked_error(sb, e4b->bd_group, | 1792 | ext4_grp_locked_error(sb, e4b->bd_group, 0, 0, |
1792 | __func__, "%d free blocks as per " | 1793 | "%d free blocks as per " |
1793 | "group info. But bitmap says 0", | 1794 | "group info. But bitmap says 0", |
1794 | free); | 1795 | free); |
1795 | break; | 1796 | break; |
@@ -1798,8 +1799,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1798 | mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex); | 1799 | mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex); |
1799 | BUG_ON(ex.fe_len <= 0); | 1800 | BUG_ON(ex.fe_len <= 0); |
1800 | if (free < ex.fe_len) { | 1801 | if (free < ex.fe_len) { |
1801 | ext4_grp_locked_error(sb, e4b->bd_group, | 1802 | ext4_grp_locked_error(sb, e4b->bd_group, 0, 0, |
1802 | __func__, "%d free blocks as per " | 1803 | "%d free blocks as per " |
1803 | "group info. But got %d blocks", | 1804 | "group info. But got %d blocks", |
1804 | free, ex.fe_len); | 1805 | free, ex.fe_len); |
1805 | /* | 1806 | /* |
@@ -3584,8 +3585,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, | |||
3584 | pa, (unsigned long) pa->pa_lstart, | 3585 | pa, (unsigned long) pa->pa_lstart, |
3585 | (unsigned long) pa->pa_pstart, | 3586 | (unsigned long) pa->pa_pstart, |
3586 | (unsigned long) pa->pa_len); | 3587 | (unsigned long) pa->pa_len); |
3587 | ext4_grp_locked_error(sb, group, | 3588 | ext4_grp_locked_error(sb, group, 0, 0, "free %u, pa_free %u", |
3588 | __func__, "free %u, pa_free %u", | ||
3589 | free, pa->pa_free); | 3589 | free, pa->pa_free); |
3590 | /* | 3590 | /* |
3591 | * pa is already deleted so we use the value obtained | 3591 | * pa is already deleted so we use the value obtained |
@@ -4395,6 +4395,7 @@ static noinline_for_stack int | |||
4395 | ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | 4395 | ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, |
4396 | struct ext4_free_data *new_entry) | 4396 | struct ext4_free_data *new_entry) |
4397 | { | 4397 | { |
4398 | ext4_group_t group = e4b->bd_group; | ||
4398 | ext4_grpblk_t block; | 4399 | ext4_grpblk_t block; |
4399 | struct ext4_free_data *entry; | 4400 | struct ext4_free_data *entry; |
4400 | struct ext4_group_info *db = e4b->bd_info; | 4401 | struct ext4_group_info *db = e4b->bd_info; |
@@ -4427,9 +4428,9 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | |||
4427 | else if (block >= (entry->start_blk + entry->count)) | 4428 | else if (block >= (entry->start_blk + entry->count)) |
4428 | n = &(*n)->rb_right; | 4429 | n = &(*n)->rb_right; |
4429 | else { | 4430 | else { |
4430 | ext4_grp_locked_error(sb, e4b->bd_group, __func__, | 4431 | ext4_grp_locked_error(sb, group, 0, |
4431 | "Double free of blocks %d (%d %d)", | 4432 | ext4_group_first_block_no(sb, group) + block, |
4432 | block, entry->start_blk, entry->count); | 4433 | "Block already on to-be-freed list"); |
4433 | return 0; | 4434 | return 0; |
4434 | } | 4435 | } |
4435 | } | 4436 | } |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 11441e483b62..39aeb454bf2c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -514,8 +514,10 @@ void __ext4_warning(struct super_block *sb, const char *function, | |||
514 | va_end(args); | 514 | va_end(args); |
515 | } | 515 | } |
516 | 516 | ||
517 | void ext4_grp_locked_error(struct super_block *sb, ext4_group_t grp, | 517 | void __ext4_grp_locked_error(const char *function, unsigned int line, |
518 | const char *function, const char *fmt, ...) | 518 | struct super_block *sb, ext4_group_t grp, |
519 | unsigned long ino, ext4_fsblk_t block, | ||
520 | const char *fmt, ...) | ||
519 | __releases(bitlock) | 521 | __releases(bitlock) |
520 | __acquires(bitlock) | 522 | __acquires(bitlock) |
521 | { | 523 | { |
@@ -523,7 +525,12 @@ __acquires(bitlock) | |||
523 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 525 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
524 | 526 | ||
525 | va_start(args, fmt); | 527 | va_start(args, fmt); |
526 | printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function); | 528 | printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u", |
529 | sb->s_id, function, line, grp); | ||
530 | if (ino) | ||
531 | printk("inode %lu: ", ino); | ||
532 | if (block) | ||
533 | printk("block %llu:", (unsigned long long) block); | ||
527 | vprintk(fmt, args); | 534 | vprintk(fmt, args); |
528 | printk("\n"); | 535 | printk("\n"); |
529 | va_end(args); | 536 | va_end(args); |