Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 bug fixes from Ted Ts'o:
"Ext4 bug fixes, including a regression fix"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: clarify impact of 'commit' mount option
ext4: fix unused-but-set-variable warning in ext4_add_entry()
jbd2: fix kernel-doc notation warning
ext4: use RCU API in debug_print_tree
ext4: validate the debug_want_extra_isize mount option at parse time
ext4: reserve revoke credits in __ext4_new_inode
ext4: unlock on error in ext4_expand_extra_isize()
ext4: optimize __ext4_check_dir_entry()
ext4: check for directory entries too close to block end
ext4: fix ext4_empty_dir() for directories with holes

+116 -104
+11 -8
Documentation/admin-guide/ext4.rst
··· 181 181 system after its metadata has been committed to the journal. 182 182 183 183 commit=nrsec (*) 184 - Ext4 can be told to sync all its data and metadata every 'nrsec' 185 - seconds. The default value is 5 seconds. This means that if you lose 186 - your power, you will lose as much as the latest 5 seconds of work (your 187 - filesystem will not be damaged though, thanks to the journaling). This 188 - default value (or any low value) will hurt performance, but it's good 189 - for data-safety. Setting it to 0 will have the same effect as leaving 190 - it at the default (5 seconds). Setting it to very large values will 191 - improve performance. 184 + This setting limits the maximum age of the running transaction to 185 + 'nrsec' seconds. The default value is 5 seconds. This means that if 186 + you lose your power, you will lose as much as the latest 5 seconds of 187 + metadata changes (your filesystem will not be damaged though, thanks 188 + to the journaling). This default value (or any low value) will hurt 189 + performance, but it's good for data-safety. Setting it to 0 will have 190 + the same effect as leaving it at the default (5 seconds). Setting it 191 + to very large values will improve performance. Note that due to 192 + delayed allocation even older data can be lost on power failure since 193 + writeback of those data begins only after time set in 194 + /proc/sys/vm/dirty_expire_centisecs. 192 195 193 196 barrier=<0|1(*)>, barrier(*), nobarrier 194 197 This enables/disables the use of write barriers in the jbd code.
+5 -1
fs/ext4/block_validity.c
··· 133 133 { 134 134 struct rb_node *node; 135 135 struct ext4_system_zone *entry; 136 + struct ext4_system_blocks *system_blks; 136 137 int first = 1; 137 138 138 139 printk(KERN_INFO "System zones: "); 139 - node = rb_first(&sbi->system_blks->root); 140 + rcu_read_lock(); 141 + system_blks = rcu_dereference(sbi->system_blks); 142 + node = rb_first(&system_blks->root); 140 143 while (node) { 141 144 entry = rb_entry(node, struct ext4_system_zone, node); 142 145 printk(KERN_CONT "%s%llu-%llu", first ? "" : ", ", ··· 147 144 first = 0; 148 145 node = rb_next(node); 149 146 } 147 + rcu_read_unlock(); 150 148 printk(KERN_CONT "\n"); 151 149 } 152 150
+5 -1
fs/ext4/dir.c
··· 72 72 const char *error_msg = NULL; 73 73 const int rlen = ext4_rec_len_from_disk(de->rec_len, 74 74 dir->i_sb->s_blocksize); 75 + const int next_offset = ((char *) de - buf) + rlen; 75 76 76 77 if (unlikely(rlen < EXT4_DIR_REC_LEN(1))) 77 78 error_msg = "rec_len is smaller than minimal"; ··· 80 79 error_msg = "rec_len % 4 != 0"; 81 80 else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len))) 82 81 error_msg = "rec_len is too small for name_len"; 83 - else if (unlikely(((char *) de - buf) + rlen > size)) 82 + else if (unlikely(next_offset > size)) 84 83 error_msg = "directory entry overrun"; 84 + else if (unlikely(next_offset > size - EXT4_DIR_REC_LEN(1) && 85 + next_offset != size)) 86 + error_msg = "directory entry too close to block end"; 85 87 else if (unlikely(le32_to_cpu(de->inode) > 86 88 le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))) 87 89 error_msg = "inode out of bounds";
+2 -2
fs/ext4/ialloc.c
··· 921 921 if (!handle) { 922 922 BUG_ON(nblocks <= 0); 923 923 handle = __ext4_journal_start_sb(dir->i_sb, line_no, 924 - handle_type, nblocks, 925 - 0, 0); 924 + handle_type, nblocks, 0, 925 + ext4_trans_default_revoke_credits(sb)); 926 926 if (IS_ERR(handle)) { 927 927 err = PTR_ERR(handle); 928 928 ext4_std_error(sb, err);
+2 -2
fs/ext4/inode.c
··· 5692 5692 error = ext4_journal_get_write_access(handle, iloc->bh); 5693 5693 if (error) { 5694 5694 brelse(iloc->bh); 5695 - goto out_stop; 5695 + goto out_unlock; 5696 5696 } 5697 5697 5698 5698 error = __ext4_expand_extra_isize(inode, new_extra_isize, iloc, ··· 5702 5702 if (!error) 5703 5703 error = rc; 5704 5704 5705 + out_unlock: 5705 5706 ext4_write_unlock_xattr(inode, &no_expand); 5706 - out_stop: 5707 5707 ext4_journal_stop(handle); 5708 5708 return error; 5709 5709 }
+21 -15
fs/ext4/namei.c
··· 2164 2164 struct buffer_head *bh = NULL; 2165 2165 struct ext4_dir_entry_2 *de; 2166 2166 struct super_block *sb; 2167 + #ifdef CONFIG_UNICODE 2167 2168 struct ext4_sb_info *sbi; 2169 + #endif 2168 2170 struct ext4_filename fname; 2169 2171 int retval; 2170 2172 int dx_fallback=0; ··· 2178 2176 csum_size = sizeof(struct ext4_dir_entry_tail); 2179 2177 2180 2178 sb = dir->i_sb; 2181 - sbi = EXT4_SB(sb); 2182 2179 blocksize = sb->s_blocksize; 2183 2180 if (!dentry->d_name.len) 2184 2181 return -EINVAL; 2185 2182 2186 2183 #ifdef CONFIG_UNICODE 2184 + sbi = EXT4_SB(sb); 2187 2185 if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) && 2188 2186 sbi->s_encoding && utf8_validate(sbi->s_encoding, &dentry->d_name)) 2189 2187 return -EINVAL; ··· 2824 2822 { 2825 2823 unsigned int offset; 2826 2824 struct buffer_head *bh; 2827 - struct ext4_dir_entry_2 *de, *de1; 2825 + struct ext4_dir_entry_2 *de; 2828 2826 struct super_block *sb; 2829 2827 2830 2828 if (ext4_has_inline_data(inode)) { ··· 2849 2847 return true; 2850 2848 2851 2849 de = (struct ext4_dir_entry_2 *) bh->b_data; 2852 - de1 = ext4_next_entry(de, sb->s_blocksize); 2853 - if (le32_to_cpu(de->inode) != inode->i_ino || 2854 - le32_to_cpu(de1->inode) == 0 || 2855 - strcmp(".", de->name) || strcmp("..", de1->name)) { 2856 - ext4_warning_inode(inode, "directory missing '.' and/or '..'"); 2850 + if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, 2851 + 0) || 2852 + le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) { 2853 + ext4_warning_inode(inode, "directory missing '.'"); 2857 2854 brelse(bh); 2858 2855 return true; 2859 2856 } 2860 - offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) + 2861 - ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize); 2862 - de = ext4_next_entry(de1, sb->s_blocksize); 2857 + offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); 2858 + de = ext4_next_entry(de, sb->s_blocksize); 2859 + if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size, 2860 + offset) || 2861 + le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) { 2862 + ext4_warning_inode(inode, "directory missing '..'"); 2863 + brelse(bh); 2864 + return true; 2865 + } 2866 + offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); 2863 2867 while (offset < inode->i_size) { 2864 - if ((void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { 2868 + if (!(offset & (sb->s_blocksize - 1))) { 2865 2869 unsigned int lblock; 2866 2870 brelse(bh); 2867 2871 lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb); ··· 2878 2870 } 2879 2871 if (IS_ERR(bh)) 2880 2872 return true; 2881 - de = (struct ext4_dir_entry_2 *) bh->b_data; 2882 2873 } 2874 + de = (struct ext4_dir_entry_2 *) (bh->b_data + 2875 + (offset & (sb->s_blocksize - 1))); 2883 2876 if (ext4_check_dir_entry(inode, NULL, de, bh, 2884 2877 bh->b_data, bh->b_size, offset)) { 2885 - de = (struct ext4_dir_entry_2 *)(bh->b_data + 2886 - sb->s_blocksize); 2887 2878 offset = (offset | (sb->s_blocksize - 1)) + 1; 2888 2879 continue; 2889 2880 } ··· 2891 2884 return false; 2892 2885 } 2893 2886 offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize); 2894 - de = ext4_next_entry(de, sb->s_blocksize); 2895 2887 } 2896 2888 brelse(bh); 2897 2889 return true;
+69 -74
fs/ext4/super.c
··· 1900 1900 } 1901 1901 sbi->s_commit_interval = HZ * arg; 1902 1902 } else if (token == Opt_debug_want_extra_isize) { 1903 + if ((arg & 1) || 1904 + (arg < 4) || 1905 + (arg > (sbi->s_inode_size - EXT4_GOOD_OLD_INODE_SIZE))) { 1906 + ext4_msg(sb, KERN_ERR, 1907 + "Invalid want_extra_isize %d", arg); 1908 + return -1; 1909 + } 1903 1910 sbi->s_want_extra_isize = arg; 1904 1911 } else if (token == Opt_max_batch_time) { 1905 1912 sbi->s_max_batch_time = arg; ··· 3561 3554 return 0; 3562 3555 } 3563 3556 3564 - static void ext4_clamp_want_extra_isize(struct super_block *sb) 3565 - { 3566 - struct ext4_sb_info *sbi = EXT4_SB(sb); 3567 - struct ext4_super_block *es = sbi->s_es; 3568 - unsigned def_extra_isize = sizeof(struct ext4_inode) - 3569 - EXT4_GOOD_OLD_INODE_SIZE; 3570 - 3571 - if (sbi->s_inode_size == EXT4_GOOD_OLD_INODE_SIZE) { 3572 - sbi->s_want_extra_isize = 0; 3573 - return; 3574 - } 3575 - if (sbi->s_want_extra_isize < 4) { 3576 - sbi->s_want_extra_isize = def_extra_isize; 3577 - if (ext4_has_feature_extra_isize(sb)) { 3578 - if (sbi->s_want_extra_isize < 3579 - le16_to_cpu(es->s_want_extra_isize)) 3580 - sbi->s_want_extra_isize = 3581 - le16_to_cpu(es->s_want_extra_isize); 3582 - if (sbi->s_want_extra_isize < 3583 - le16_to_cpu(es->s_min_extra_isize)) 3584 - sbi->s_want_extra_isize = 3585 - le16_to_cpu(es->s_min_extra_isize); 3586 - } 3587 - } 3588 - /* Check if enough inode space is available */ 3589 - if ((sbi->s_want_extra_isize > sbi->s_inode_size) || 3590 - (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize > 3591 - sbi->s_inode_size)) { 3592 - sbi->s_want_extra_isize = def_extra_isize; 3593 - ext4_msg(sb, KERN_INFO, 3594 - "required extra inode space not available"); 3595 - } 3596 - } 3597 - 3598 3557 static void ext4_set_resv_clusters(struct super_block *sb) 3599 3558 { 3600 3559 ext4_fsblk_t resv_clusters; ··· 3767 3794 * no mount option specified. 3768 3795 */ 3769 3796 sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT; 3797 + 3798 + if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) { 3799 + sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE; 3800 + sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO; 3801 + } else { 3802 + sbi->s_inode_size = le16_to_cpu(es->s_inode_size); 3803 + sbi->s_first_ino = le32_to_cpu(es->s_first_ino); 3804 + if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) { 3805 + ext4_msg(sb, KERN_ERR, "invalid first ino: %u", 3806 + sbi->s_first_ino); 3807 + goto failed_mount; 3808 + } 3809 + if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || 3810 + (!is_power_of_2(sbi->s_inode_size)) || 3811 + (sbi->s_inode_size > blocksize)) { 3812 + ext4_msg(sb, KERN_ERR, 3813 + "unsupported inode size: %d", 3814 + sbi->s_inode_size); 3815 + goto failed_mount; 3816 + } 3817 + /* 3818 + * i_atime_extra is the last extra field available for 3819 + * [acm]times in struct ext4_inode. Checking for that 3820 + * field should suffice to ensure we have extra space 3821 + * for all three. 3822 + */ 3823 + if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) + 3824 + sizeof(((struct ext4_inode *)0)->i_atime_extra)) { 3825 + sb->s_time_gran = 1; 3826 + sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX; 3827 + } else { 3828 + sb->s_time_gran = NSEC_PER_SEC; 3829 + sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX; 3830 + } 3831 + sb->s_time_min = EXT4_TIMESTAMP_MIN; 3832 + } 3833 + if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) { 3834 + sbi->s_want_extra_isize = sizeof(struct ext4_inode) - 3835 + EXT4_GOOD_OLD_INODE_SIZE; 3836 + if (ext4_has_feature_extra_isize(sb)) { 3837 + unsigned v, max = (sbi->s_inode_size - 3838 + EXT4_GOOD_OLD_INODE_SIZE); 3839 + 3840 + v = le16_to_cpu(es->s_want_extra_isize); 3841 + if (v > max) { 3842 + ext4_msg(sb, KERN_ERR, 3843 + "bad s_want_extra_isize: %d", v); 3844 + goto failed_mount; 3845 + } 3846 + if (sbi->s_want_extra_isize < v) 3847 + sbi->s_want_extra_isize = v; 3848 + 3849 + v = le16_to_cpu(es->s_min_extra_isize); 3850 + if (v > max) { 3851 + ext4_msg(sb, KERN_ERR, 3852 + "bad s_min_extra_isize: %d", v); 3853 + goto failed_mount; 3854 + } 3855 + if (sbi->s_want_extra_isize < v) 3856 + sbi->s_want_extra_isize = v; 3857 + } 3858 + } 3770 3859 3771 3860 if (sbi->s_es->s_mount_opts[0]) { 3772 3861 char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts, ··· 4067 4032 sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits, 4068 4033 has_huge_files); 4069 4034 sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files); 4070 - 4071 - if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) { 4072 - sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE; 4073 - sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO; 4074 - } else { 4075 - sbi->s_inode_size = le16_to_cpu(es->s_inode_size); 4076 - sbi->s_first_ino = le32_to_cpu(es->s_first_ino); 4077 - if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) { 4078 - ext4_msg(sb, KERN_ERR, "invalid first ino: %u", 4079 - sbi->s_first_ino); 4080 - goto failed_mount; 4081 - } 4082 - if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || 4083 - (!is_power_of_2(sbi->s_inode_size)) || 4084 - (sbi->s_inode_size > blocksize)) { 4085 - ext4_msg(sb, KERN_ERR, 4086 - "unsupported inode size: %d", 4087 - sbi->s_inode_size); 4088 - goto failed_mount; 4089 - } 4090 - /* 4091 - * i_atime_extra is the last extra field available for [acm]times in 4092 - * struct ext4_inode. Checking for that field should suffice to ensure 4093 - * we have extra space for all three. 4094 - */ 4095 - if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) + 4096 - sizeof(((struct ext4_inode *)0)->i_atime_extra)) { 4097 - sb->s_time_gran = 1; 4098 - sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX; 4099 - } else { 4100 - sb->s_time_gran = NSEC_PER_SEC; 4101 - sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX; 4102 - } 4103 - 4104 - sb->s_time_min = EXT4_TIMESTAMP_MIN; 4105 - } 4106 4035 4107 4036 sbi->s_desc_size = le16_to_cpu(es->s_desc_size); 4108 4037 if (ext4_has_feature_64bit(sb)) { ··· 4515 4516 ret = 0; 4516 4517 } else if (ret) 4517 4518 goto failed_mount4a; 4518 - 4519 - ext4_clamp_want_extra_isize(sb); 4520 4519 4521 4520 ext4_set_resv_clusters(sb); 4522 4521 ··· 5302 5305 err = -EINVAL; 5303 5306 goto restore_opts; 5304 5307 } 5305 - 5306 - ext4_clamp_want_extra_isize(sb); 5307 5308 5308 5309 if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^ 5309 5310 test_opt(sb, JOURNAL_CHECKSUM)) {
+1 -1
include/linux/jbd2.h
··· 457 457 * @h_journal: Which journal handle belongs to - used iff h_reserved set. 458 458 * @h_rsv_handle: Handle reserved for finishing the logical operation. 459 459 * @h_total_credits: Number of remaining buffers we are allowed to add to 460 - journal. These are dirty buffers and revoke descriptor blocks. 460 + * journal. These are dirty buffers and revoke descriptor blocks. 461 461 * @h_revoke_credits: Number of remaining revoke records available for handle 462 462 * @h_ref: Reference count on this handle. 463 463 * @h_err: Field for caller's use to track errors through large fs operations.