1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 26fd058f7STheodore Ts'o /* 36fd058f7STheodore Ts'o * linux/fs/ext4/block_validity.c 46fd058f7STheodore Ts'o * 56fd058f7STheodore Ts'o * Copyright (C) 2009 66fd058f7STheodore Ts'o * Theodore Ts'o (tytso@mit.edu) 76fd058f7STheodore Ts'o * 86fd058f7STheodore Ts'o * Track which blocks in the filesystem are metadata blocks that 96fd058f7STheodore Ts'o * should never be used as data blocks by files or directories. 106fd058f7STheodore Ts'o */ 116fd058f7STheodore Ts'o 126fd058f7STheodore Ts'o #include <linux/time.h> 136fd058f7STheodore Ts'o #include <linux/fs.h> 146fd058f7STheodore Ts'o #include <linux/namei.h> 156fd058f7STheodore Ts'o #include <linux/quotaops.h> 166fd058f7STheodore Ts'o #include <linux/buffer_head.h> 176fd058f7STheodore Ts'o #include <linux/swap.h> 186fd058f7STheodore Ts'o #include <linux/pagemap.h> 196fd058f7STheodore Ts'o #include <linux/blkdev.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 216fd058f7STheodore Ts'o #include "ext4.h" 226fd058f7STheodore Ts'o 236fd058f7STheodore Ts'o struct ext4_system_zone { 246fd058f7STheodore Ts'o struct rb_node node; 256fd058f7STheodore Ts'o ext4_fsblk_t start_blk; 266fd058f7STheodore Ts'o unsigned int count; 276fd058f7STheodore Ts'o }; 286fd058f7STheodore Ts'o 296fd058f7STheodore Ts'o static struct kmem_cache *ext4_system_zone_cachep; 306fd058f7STheodore Ts'o 315dabfc78STheodore Ts'o int __init ext4_init_system_zone(void) 326fd058f7STheodore Ts'o { 3316828088STheodore Ts'o ext4_system_zone_cachep = KMEM_CACHE(ext4_system_zone, 0); 346fd058f7STheodore Ts'o if (ext4_system_zone_cachep == NULL) 356fd058f7STheodore Ts'o return -ENOMEM; 366fd058f7STheodore Ts'o return 0; 376fd058f7STheodore Ts'o } 386fd058f7STheodore Ts'o 395dabfc78STheodore Ts'o void ext4_exit_system_zone(void) 406fd058f7STheodore Ts'o { 417727ae52Szhangyi (F) rcu_barrier(); 426fd058f7STheodore Ts'o kmem_cache_destroy(ext4_system_zone_cachep); 436fd058f7STheodore Ts'o } 446fd058f7STheodore Ts'o 456fd058f7STheodore Ts'o static inline int can_merge(struct ext4_system_zone *entry1, 466fd058f7STheodore Ts'o struct ext4_system_zone *entry2) 476fd058f7STheodore Ts'o { 486fd058f7STheodore Ts'o if ((entry1->start_blk + entry1->count) == entry2->start_blk) 496fd058f7STheodore Ts'o return 1; 506fd058f7STheodore Ts'o return 0; 516fd058f7STheodore Ts'o } 526fd058f7STheodore Ts'o 537727ae52Szhangyi (F) static void release_system_zone(struct ext4_system_blocks *system_blks) 547727ae52Szhangyi (F) { 557727ae52Szhangyi (F) struct ext4_system_zone *entry, *n; 567727ae52Szhangyi (F) 577727ae52Szhangyi (F) rbtree_postorder_for_each_entry_safe(entry, n, 587727ae52Szhangyi (F) &system_blks->root, node) 597727ae52Szhangyi (F) kmem_cache_free(ext4_system_zone_cachep, entry); 607727ae52Szhangyi (F) } 617727ae52Szhangyi (F) 626fd058f7STheodore Ts'o /* 636fd058f7STheodore Ts'o * Mark a range of blocks as belonging to the "system zone" --- that 646fd058f7STheodore Ts'o * is, filesystem metadata blocks which should never be used by 656fd058f7STheodore Ts'o * inodes. 666fd058f7STheodore Ts'o */ 677727ae52Szhangyi (F) static int add_system_zone(struct ext4_system_blocks *system_blks, 686fd058f7STheodore Ts'o ext4_fsblk_t start_blk, 696fd058f7STheodore Ts'o unsigned int count) 706fd058f7STheodore Ts'o { 71bf9a379dSJan Kara struct ext4_system_zone *new_entry, *entry; 727727ae52Szhangyi (F) struct rb_node **n = &system_blks->root.rb_node, *node; 736fd058f7STheodore Ts'o struct rb_node *parent = NULL, *new_node = NULL; 746fd058f7STheodore Ts'o 756fd058f7STheodore Ts'o while (*n) { 766fd058f7STheodore Ts'o parent = *n; 776fd058f7STheodore Ts'o entry = rb_entry(parent, struct ext4_system_zone, node); 786fd058f7STheodore Ts'o if (start_blk < entry->start_blk) 796fd058f7STheodore Ts'o n = &(*n)->rb_left; 806fd058f7STheodore Ts'o else if (start_blk >= (entry->start_blk + entry->count)) 816fd058f7STheodore Ts'o n = &(*n)->rb_right; 82bf9a379dSJan Kara else /* Unexpected overlap of system zones. */ 83bf9a379dSJan Kara return -EFSCORRUPTED; 846fd058f7STheodore Ts'o } 856fd058f7STheodore Ts'o 866fd058f7STheodore Ts'o new_entry = kmem_cache_alloc(ext4_system_zone_cachep, 876fd058f7STheodore Ts'o GFP_KERNEL); 886fd058f7STheodore Ts'o if (!new_entry) 896fd058f7STheodore Ts'o return -ENOMEM; 906fd058f7STheodore Ts'o new_entry->start_blk = start_blk; 916fd058f7STheodore Ts'o new_entry->count = count; 926fd058f7STheodore Ts'o new_node = &new_entry->node; 936fd058f7STheodore Ts'o 946fd058f7STheodore Ts'o rb_link_node(new_node, parent, n); 957727ae52Szhangyi (F) rb_insert_color(new_node, &system_blks->root); 966fd058f7STheodore Ts'o 976fd058f7STheodore Ts'o /* Can we merge to the left? */ 986fd058f7STheodore Ts'o node = rb_prev(new_node); 996fd058f7STheodore Ts'o if (node) { 1006fd058f7STheodore Ts'o entry = rb_entry(node, struct ext4_system_zone, node); 1016fd058f7STheodore Ts'o if (can_merge(entry, new_entry)) { 1026fd058f7STheodore Ts'o new_entry->start_blk = entry->start_blk; 1036fd058f7STheodore Ts'o new_entry->count += entry->count; 1047727ae52Szhangyi (F) rb_erase(node, &system_blks->root); 1056fd058f7STheodore Ts'o kmem_cache_free(ext4_system_zone_cachep, entry); 1066fd058f7STheodore Ts'o } 1076fd058f7STheodore Ts'o } 1086fd058f7STheodore Ts'o 1096fd058f7STheodore Ts'o /* Can we merge to the right? */ 1106fd058f7STheodore Ts'o node = rb_next(new_node); 1116fd058f7STheodore Ts'o if (node) { 1126fd058f7STheodore Ts'o entry = rb_entry(node, struct ext4_system_zone, node); 1136fd058f7STheodore Ts'o if (can_merge(new_entry, entry)) { 1146fd058f7STheodore Ts'o new_entry->count += entry->count; 1157727ae52Szhangyi (F) rb_erase(node, &system_blks->root); 1166fd058f7STheodore Ts'o kmem_cache_free(ext4_system_zone_cachep, entry); 1176fd058f7STheodore Ts'o } 1186fd058f7STheodore Ts'o } 1196fd058f7STheodore Ts'o return 0; 1206fd058f7STheodore Ts'o } 1216fd058f7STheodore Ts'o 1226fd058f7STheodore Ts'o static void debug_print_tree(struct ext4_sb_info *sbi) 1236fd058f7STheodore Ts'o { 1246fd058f7STheodore Ts'o struct rb_node *node; 1256fd058f7STheodore Ts'o struct ext4_system_zone *entry; 12669000d82SPhong Tran struct ext4_system_blocks *system_blks; 1276fd058f7STheodore Ts'o int first = 1; 1286fd058f7STheodore Ts'o 1296fd058f7STheodore Ts'o printk(KERN_INFO "System zones: "); 13069000d82SPhong Tran rcu_read_lock(); 13169000d82SPhong Tran system_blks = rcu_dereference(sbi->system_blks); 13269000d82SPhong Tran node = rb_first(&system_blks->root); 1336fd058f7STheodore Ts'o while (node) { 1346fd058f7STheodore Ts'o entry = rb_entry(node, struct ext4_system_zone, node); 135d74f3d25SJoe Perches printk(KERN_CONT "%s%llu-%llu", first ? "" : ", ", 1366fd058f7STheodore Ts'o entry->start_blk, entry->start_blk + entry->count - 1); 1376fd058f7STheodore Ts'o first = 0; 1386fd058f7STheodore Ts'o node = rb_next(node); 1396fd058f7STheodore Ts'o } 14069000d82SPhong Tran rcu_read_unlock(); 141d74f3d25SJoe Perches printk(KERN_CONT "\n"); 1426fd058f7STheodore Ts'o } 1436fd058f7STheodore Ts'o 1447727ae52Szhangyi (F) /* 1457727ae52Szhangyi (F) * Returns 1 if the passed-in block region (start_blk, 1467727ae52Szhangyi (F) * start_blk+count) is valid; 0 if some part of the block region 1477727ae52Szhangyi (F) * overlaps with filesystem metadata blocks. 1487727ae52Szhangyi (F) */ 1497727ae52Szhangyi (F) static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi, 1507727ae52Szhangyi (F) struct ext4_system_blocks *system_blks, 1517727ae52Szhangyi (F) ext4_fsblk_t start_blk, 1527727ae52Szhangyi (F) unsigned int count) 1537727ae52Szhangyi (F) { 1547727ae52Szhangyi (F) struct ext4_system_zone *entry; 1557727ae52Szhangyi (F) struct rb_node *n; 1567727ae52Szhangyi (F) 1577727ae52Szhangyi (F) if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || 1587727ae52Szhangyi (F) (start_blk + count < start_blk) || 15954d3adbcSTheodore Ts'o (start_blk + count > ext4_blocks_count(sbi->s_es))) 1607727ae52Szhangyi (F) return 0; 1617727ae52Szhangyi (F) 1627727ae52Szhangyi (F) if (system_blks == NULL) 1637727ae52Szhangyi (F) return 1; 1647727ae52Szhangyi (F) 1657727ae52Szhangyi (F) n = system_blks->root.rb_node; 1667727ae52Szhangyi (F) while (n) { 1677727ae52Szhangyi (F) entry = rb_entry(n, struct ext4_system_zone, node); 1687727ae52Szhangyi (F) if (start_blk + count - 1 < entry->start_blk) 1697727ae52Szhangyi (F) n = n->rb_left; 1707727ae52Szhangyi (F) else if (start_blk >= (entry->start_blk + entry->count)) 1717727ae52Szhangyi (F) n = n->rb_right; 17254d3adbcSTheodore Ts'o else 1737727ae52Szhangyi (F) return 0; 1747727ae52Szhangyi (F) } 1757727ae52Szhangyi (F) return 1; 1767727ae52Szhangyi (F) } 1777727ae52Szhangyi (F) 1787727ae52Szhangyi (F) static int ext4_protect_reserved_inode(struct super_block *sb, 1797727ae52Szhangyi (F) struct ext4_system_blocks *system_blks, 1807727ae52Szhangyi (F) u32 ino) 181345c0dbfSTheodore Ts'o { 182345c0dbfSTheodore Ts'o struct inode *inode; 183345c0dbfSTheodore Ts'o struct ext4_sb_info *sbi = EXT4_SB(sb); 184345c0dbfSTheodore Ts'o struct ext4_map_blocks map; 185fbbbbd2fSColin Ian King u32 i = 0, num; 186fbbbbd2fSColin Ian King int err = 0, n; 187345c0dbfSTheodore Ts'o 188345c0dbfSTheodore Ts'o if ((ino < EXT4_ROOT_INO) || 189345c0dbfSTheodore Ts'o (ino > le32_to_cpu(sbi->s_es->s_inodes_count))) 190345c0dbfSTheodore Ts'o return -EINVAL; 191345c0dbfSTheodore Ts'o inode = ext4_iget(sb, ino, EXT4_IGET_SPECIAL); 192345c0dbfSTheodore Ts'o if (IS_ERR(inode)) 193345c0dbfSTheodore Ts'o return PTR_ERR(inode); 194345c0dbfSTheodore Ts'o num = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; 195345c0dbfSTheodore Ts'o while (i < num) { 196af133adeSShijie Luo cond_resched(); 197345c0dbfSTheodore Ts'o map.m_lblk = i; 198345c0dbfSTheodore Ts'o map.m_len = num - i; 199345c0dbfSTheodore Ts'o n = ext4_map_blocks(NULL, inode, &map, 0); 200345c0dbfSTheodore Ts'o if (n < 0) { 201345c0dbfSTheodore Ts'o err = n; 202345c0dbfSTheodore Ts'o break; 203345c0dbfSTheodore Ts'o } 204345c0dbfSTheodore Ts'o if (n == 0) { 205345c0dbfSTheodore Ts'o i++; 206345c0dbfSTheodore Ts'o } else { 2077727ae52Szhangyi (F) if (!ext4_data_block_valid_rcu(sbi, system_blks, 2087727ae52Szhangyi (F) map.m_pblk, n)) { 209345c0dbfSTheodore Ts'o err = -EFSCORRUPTED; 21054d3adbcSTheodore Ts'o __ext4_error(sb, __func__, __LINE__, -err, 21154d3adbcSTheodore Ts'o map.m_pblk, "blocks %llu-%llu " 21254d3adbcSTheodore Ts'o "from inode %u overlap system zone", 21354d3adbcSTheodore Ts'o map.m_pblk, 21454d3adbcSTheodore Ts'o map.m_pblk + map.m_len - 1, ino); 215345c0dbfSTheodore Ts'o break; 216345c0dbfSTheodore Ts'o } 2177727ae52Szhangyi (F) err = add_system_zone(system_blks, map.m_pblk, n); 218345c0dbfSTheodore Ts'o if (err < 0) 219345c0dbfSTheodore Ts'o break; 220345c0dbfSTheodore Ts'o i += n; 221345c0dbfSTheodore Ts'o } 222345c0dbfSTheodore Ts'o } 223345c0dbfSTheodore Ts'o iput(inode); 224345c0dbfSTheodore Ts'o return err; 225345c0dbfSTheodore Ts'o } 226345c0dbfSTheodore Ts'o 2277727ae52Szhangyi (F) static void ext4_destroy_system_zone(struct rcu_head *rcu) 2287727ae52Szhangyi (F) { 2297727ae52Szhangyi (F) struct ext4_system_blocks *system_blks; 2307727ae52Szhangyi (F) 2317727ae52Szhangyi (F) system_blks = container_of(rcu, struct ext4_system_blocks, rcu); 2327727ae52Szhangyi (F) release_system_zone(system_blks); 2337727ae52Szhangyi (F) kfree(system_blks); 2347727ae52Szhangyi (F) } 2357727ae52Szhangyi (F) 2367727ae52Szhangyi (F) /* 2377727ae52Szhangyi (F) * Build system zone rbtree which is used for block validity checking. 2387727ae52Szhangyi (F) * 2397727ae52Szhangyi (F) * The update of system_blks pointer in this function is protected by 2407727ae52Szhangyi (F) * sb->s_umount semaphore. However we have to be careful as we can be 2417727ae52Szhangyi (F) * racing with ext4_data_block_valid() calls reading system_blks rbtree 2427727ae52Szhangyi (F) * protected only by RCU. That's why we first build the rbtree and then 2437727ae52Szhangyi (F) * swap it in place. 2447727ae52Szhangyi (F) */ 2456fd058f7STheodore Ts'o int ext4_setup_system_zone(struct super_block *sb) 2466fd058f7STheodore Ts'o { 2476fd058f7STheodore Ts'o ext4_group_t ngroups = ext4_get_groups_count(sb); 2486fd058f7STheodore Ts'o struct ext4_sb_info *sbi = EXT4_SB(sb); 2497727ae52Szhangyi (F) struct ext4_system_blocks *system_blks; 2506fd058f7STheodore Ts'o struct ext4_group_desc *gdp; 2516fd058f7STheodore Ts'o ext4_group_t i; 2526fd058f7STheodore Ts'o int flex_size = ext4_flex_bg_size(sbi); 2536fd058f7STheodore Ts'o int ret; 2546fd058f7STheodore Ts'o 2556fd058f7STheodore Ts'o if (!test_opt(sb, BLOCK_VALIDITY)) { 2567727ae52Szhangyi (F) if (sbi->system_blks) 2576fd058f7STheodore Ts'o ext4_release_system_zone(sb); 2586fd058f7STheodore Ts'o return 0; 2596fd058f7STheodore Ts'o } 2607727ae52Szhangyi (F) if (sbi->system_blks) 2616fd058f7STheodore Ts'o return 0; 2626fd058f7STheodore Ts'o 2637727ae52Szhangyi (F) system_blks = kzalloc(sizeof(*system_blks), GFP_KERNEL); 2647727ae52Szhangyi (F) if (!system_blks) 2657727ae52Szhangyi (F) return -ENOMEM; 2667727ae52Szhangyi (F) 2676fd058f7STheodore Ts'o for (i=0; i < ngroups; i++) { 2684b99faa2SKhazhismel Kumykov cond_resched(); 2696fd058f7STheodore Ts'o if (ext4_bg_has_super(sb, i) && 2706fd058f7STheodore Ts'o ((i < 5) || ((i % flex_size) == 0))) 2717727ae52Szhangyi (F) add_system_zone(system_blks, 2727727ae52Szhangyi (F) ext4_group_first_block_no(sb, i), 2731032988cSTheodore Ts'o ext4_bg_num_gdb(sb, i) + 1); 2746fd058f7STheodore Ts'o gdp = ext4_get_group_desc(sb, i, NULL); 2757727ae52Szhangyi (F) ret = add_system_zone(system_blks, 2767727ae52Szhangyi (F) ext4_block_bitmap(sb, gdp), 1); 2776fd058f7STheodore Ts'o if (ret) 2787727ae52Szhangyi (F) goto err; 2797727ae52Szhangyi (F) ret = add_system_zone(system_blks, 2807727ae52Szhangyi (F) ext4_inode_bitmap(sb, gdp), 1); 2816fd058f7STheodore Ts'o if (ret) 2827727ae52Szhangyi (F) goto err; 2837727ae52Szhangyi (F) ret = add_system_zone(system_blks, 2847727ae52Szhangyi (F) ext4_inode_table(sb, gdp), 2856fd058f7STheodore Ts'o sbi->s_itb_per_group); 2866fd058f7STheodore Ts'o if (ret) 2877727ae52Szhangyi (F) goto err; 2886fd058f7STheodore Ts'o } 289345c0dbfSTheodore Ts'o if (ext4_has_feature_journal(sb) && sbi->s_es->s_journal_inum) { 2907727ae52Szhangyi (F) ret = ext4_protect_reserved_inode(sb, system_blks, 291345c0dbfSTheodore Ts'o le32_to_cpu(sbi->s_es->s_journal_inum)); 292345c0dbfSTheodore Ts'o if (ret) 2937727ae52Szhangyi (F) goto err; 294345c0dbfSTheodore Ts'o } 2956fd058f7STheodore Ts'o 2967727ae52Szhangyi (F) /* 2977727ae52Szhangyi (F) * System blks rbtree complete, announce it once to prevent racing 2987727ae52Szhangyi (F) * with ext4_data_block_valid() accessing the rbtree at the same 2997727ae52Szhangyi (F) * time. 3007727ae52Szhangyi (F) */ 3017727ae52Szhangyi (F) rcu_assign_pointer(sbi->system_blks, system_blks); 3027727ae52Szhangyi (F) 3036fd058f7STheodore Ts'o if (test_opt(sb, DEBUG)) 30449598e04SJun Piao debug_print_tree(sbi); 3056fd058f7STheodore Ts'o return 0; 3067727ae52Szhangyi (F) err: 3077727ae52Szhangyi (F) release_system_zone(system_blks); 3087727ae52Szhangyi (F) kfree(system_blks); 3097727ae52Szhangyi (F) return ret; 3106fd058f7STheodore Ts'o } 3116fd058f7STheodore Ts'o 3126fd058f7STheodore Ts'o /* 3137727ae52Szhangyi (F) * Called when the filesystem is unmounted or when remounting it with 3147727ae52Szhangyi (F) * noblock_validity specified. 3157727ae52Szhangyi (F) * 3167727ae52Szhangyi (F) * The update of system_blks pointer in this function is protected by 3177727ae52Szhangyi (F) * sb->s_umount semaphore. However we have to be careful as we can be 3187727ae52Szhangyi (F) * racing with ext4_data_block_valid() calls reading system_blks rbtree 3197727ae52Szhangyi (F) * protected only by RCU. So we first clear the system_blks pointer and 3207727ae52Szhangyi (F) * then free the rbtree only after RCU grace period expires. 3216fd058f7STheodore Ts'o */ 3227727ae52Szhangyi (F) void ext4_release_system_zone(struct super_block *sb) 3237727ae52Szhangyi (F) { 3247727ae52Szhangyi (F) struct ext4_system_blocks *system_blks; 3257727ae52Szhangyi (F) 3267727ae52Szhangyi (F) system_blks = rcu_dereference_protected(EXT4_SB(sb)->system_blks, 3277727ae52Szhangyi (F) lockdep_is_held(&sb->s_umount)); 3287727ae52Szhangyi (F) rcu_assign_pointer(EXT4_SB(sb)->system_blks, NULL); 3297727ae52Szhangyi (F) 3307727ae52Szhangyi (F) if (system_blks) 3317727ae52Szhangyi (F) call_rcu(&system_blks->rcu, ext4_destroy_system_zone); 3327727ae52Szhangyi (F) } 3337727ae52Szhangyi (F) 3346fd058f7STheodore Ts'o int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk, 3356fd058f7STheodore Ts'o unsigned int count) 3366fd058f7STheodore Ts'o { 3377727ae52Szhangyi (F) struct ext4_system_blocks *system_blks; 3387727ae52Szhangyi (F) int ret; 3396fd058f7STheodore Ts'o 3407727ae52Szhangyi (F) /* 3417727ae52Szhangyi (F) * Lock the system zone to prevent it being released concurrently 3427727ae52Szhangyi (F) * when doing a remount which inverse current "[no]block_validity" 3437727ae52Szhangyi (F) * mount option. 3447727ae52Szhangyi (F) */ 3457727ae52Szhangyi (F) rcu_read_lock(); 3467727ae52Szhangyi (F) system_blks = rcu_dereference(sbi->system_blks); 3477727ae52Szhangyi (F) ret = ext4_data_block_valid_rcu(sbi, system_blks, start_blk, 3487727ae52Szhangyi (F) count); 3497727ae52Szhangyi (F) rcu_read_unlock(); 3507727ae52Szhangyi (F) return ret; 3516fd058f7STheodore Ts'o } 3526fd058f7STheodore Ts'o 3531f7d1e77STheodore Ts'o int ext4_check_blockref(const char *function, unsigned int line, 3541f7d1e77STheodore Ts'o struct inode *inode, __le32 *p, unsigned int max) 3551f7d1e77STheodore Ts'o { 3561f7d1e77STheodore Ts'o __le32 *bref = p; 3571f7d1e77STheodore Ts'o unsigned int blk; 3581f7d1e77STheodore Ts'o 359170417c8STheodore Ts'o if (ext4_has_feature_journal(inode->i_sb) && 360170417c8STheodore Ts'o (inode->i_ino == 361170417c8STheodore Ts'o le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) 362170417c8STheodore Ts'o return 0; 363170417c8STheodore Ts'o 3641f7d1e77STheodore Ts'o while (bref < p+max) { 3651f7d1e77STheodore Ts'o blk = le32_to_cpu(*bref++); 3661f7d1e77STheodore Ts'o if (blk && 3671f7d1e77STheodore Ts'o unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb), 3681f7d1e77STheodore Ts'o blk, 1))) { 3691f7d1e77STheodore Ts'o ext4_error_inode(inode, function, line, blk, 3701f7d1e77STheodore Ts'o "invalid block"); 3716a797d27SDarrick J. Wong return -EFSCORRUPTED; 3721f7d1e77STheodore Ts'o } 3731f7d1e77STheodore Ts'o } 3741f7d1e77STheodore Ts'o return 0; 3751f7d1e77STheodore Ts'o } 376dae1e52cSAmir Goldstein 377