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 fixes from Ted Ts'o:
"Fix a memory leak on an error path, and two races when modifying
inodes relating to the inline_data and metadata checksum features"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: fix two spelling nits
ext4: lock the xattr block before checksuming it
jbd2: don't leak memory if setting up journal fails
ext4: mark inode dirty after converting inline directory

+47 -50
+2 -3
fs/ext4/inline.c
··· 1169 1169 set_buffer_uptodate(dir_block); 1170 1170 err = ext4_handle_dirty_dirent_node(handle, inode, dir_block); 1171 1171 if (err) 1172 - goto out; 1172 + return err; 1173 1173 set_buffer_verified(dir_block); 1174 - out: 1175 - return err; 1174 + return ext4_mark_inode_dirty(handle, inode); 1176 1175 } 1177 1176 1178 1177 static int ext4_convert_inline_data_nolock(handle_t *handle,
+1 -1
fs/ext4/inode.c
··· 5400 5400 * If there is inline data in the inode, the inode will normally not 5401 5401 * have data blocks allocated (it may have an external xattr block). 5402 5402 * Report at least one sector for such files, so tools like tar, rsync, 5403 - * others doen't incorrectly think the file is completely sparse. 5403 + * others don't incorrectly think the file is completely sparse. 5404 5404 */ 5405 5405 if (unlikely(ext4_has_inline_data(inode))) 5406 5406 stat->blocks += (stat->size + 511) >> 9;
+1 -1
fs/ext4/move_extent.c
··· 511 511 if ((orig_start & ~(PAGE_MASK >> orig_inode->i_blkbits)) != 512 512 (donor_start & ~(PAGE_MASK >> orig_inode->i_blkbits))) { 513 513 ext4_debug("ext4 move extent: orig and donor's start " 514 - "offset are not alligned [ino:orig %lu, donor %lu]\n", 514 + "offsets are not aligned [ino:orig %lu, donor %lu]\n", 515 515 orig_inode->i_ino, donor_inode->i_ino); 516 516 return -EINVAL; 517 517 }
+31 -34
fs/ext4/xattr.c
··· 131 131 } 132 132 133 133 static int ext4_xattr_block_csum_verify(struct inode *inode, 134 - sector_t block_nr, 135 - struct ext4_xattr_header *hdr) 134 + struct buffer_head *bh) 136 135 { 137 - if (ext4_has_metadata_csum(inode->i_sb) && 138 - (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr))) 139 - return 0; 140 - return 1; 136 + struct ext4_xattr_header *hdr = BHDR(bh); 137 + int ret = 1; 138 + 139 + if (ext4_has_metadata_csum(inode->i_sb)) { 140 + lock_buffer(bh); 141 + ret = (hdr->h_checksum == ext4_xattr_block_csum(inode, 142 + bh->b_blocknr, hdr)); 143 + unlock_buffer(bh); 144 + } 145 + return ret; 141 146 } 142 147 143 148 static void ext4_xattr_block_csum_set(struct inode *inode, 144 - sector_t block_nr, 145 - struct ext4_xattr_header *hdr) 149 + struct buffer_head *bh) 146 150 { 147 - if (!ext4_has_metadata_csum(inode->i_sb)) 148 - return; 149 - 150 - hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr); 151 - } 152 - 153 - static inline int ext4_handle_dirty_xattr_block(handle_t *handle, 154 - struct inode *inode, 155 - struct buffer_head *bh) 156 - { 157 - ext4_xattr_block_csum_set(inode, bh->b_blocknr, BHDR(bh)); 158 - return ext4_handle_dirty_metadata(handle, inode, bh); 151 + if (ext4_has_metadata_csum(inode->i_sb)) 152 + BHDR(bh)->h_checksum = ext4_xattr_block_csum(inode, 153 + bh->b_blocknr, BHDR(bh)); 159 154 } 160 155 161 156 static inline const struct xattr_handler * ··· 228 233 if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || 229 234 BHDR(bh)->h_blocks != cpu_to_le32(1)) 230 235 return -EFSCORRUPTED; 231 - if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) 236 + if (!ext4_xattr_block_csum_verify(inode, bh)) 232 237 return -EFSBADCRC; 233 238 error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, 234 239 bh->b_data); ··· 613 618 } 614 619 } 615 620 621 + ext4_xattr_block_csum_set(inode, bh); 616 622 /* 617 623 * Beware of this ugliness: Releasing of xattr block references 618 624 * from different inodes can race and so we have to protect 619 625 * from a race where someone else frees the block (and releases 620 626 * its journal_head) before we are done dirtying the buffer. In 621 627 * nojournal mode this race is harmless and we actually cannot 622 - * call ext4_handle_dirty_xattr_block() with locked buffer as 628 + * call ext4_handle_dirty_metadata() with locked buffer as 623 629 * that function can call sync_dirty_buffer() so for that case 624 630 * we handle the dirtying after unlocking the buffer. 625 631 */ 626 632 if (ext4_handle_valid(handle)) 627 - error = ext4_handle_dirty_xattr_block(handle, inode, 628 - bh); 633 + error = ext4_handle_dirty_metadata(handle, inode, bh); 629 634 unlock_buffer(bh); 630 635 if (!ext4_handle_valid(handle)) 631 - error = ext4_handle_dirty_xattr_block(handle, inode, 632 - bh); 636 + error = ext4_handle_dirty_metadata(handle, inode, bh); 633 637 if (IS_SYNC(inode)) 634 638 ext4_handle_sync(handle); 635 639 dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1)); ··· 857 863 ext4_xattr_cache_insert(ext4_mb_cache, 858 864 bs->bh); 859 865 } 866 + ext4_xattr_block_csum_set(inode, bs->bh); 860 867 unlock_buffer(bs->bh); 861 868 if (error == -EFSCORRUPTED) 862 869 goto bad_block; 863 870 if (!error) 864 - error = ext4_handle_dirty_xattr_block(handle, 865 - inode, 866 - bs->bh); 871 + error = ext4_handle_dirty_metadata(handle, 872 + inode, 873 + bs->bh); 867 874 if (error) 868 875 goto cleanup; 869 876 goto inserted; ··· 962 967 ce->e_reusable = 0; 963 968 ea_bdebug(new_bh, "reusing; refcount now=%d", 964 969 ref); 970 + ext4_xattr_block_csum_set(inode, new_bh); 965 971 unlock_buffer(new_bh); 966 - error = ext4_handle_dirty_xattr_block(handle, 967 - inode, 968 - new_bh); 972 + error = ext4_handle_dirty_metadata(handle, 973 + inode, 974 + new_bh); 969 975 if (error) 970 976 goto cleanup_dquot; 971 977 } ··· 1016 1020 goto getblk_failed; 1017 1021 } 1018 1022 memcpy(new_bh->b_data, s->base, new_bh->b_size); 1023 + ext4_xattr_block_csum_set(inode, new_bh); 1019 1024 set_buffer_uptodate(new_bh); 1020 1025 unlock_buffer(new_bh); 1021 1026 ext4_xattr_cache_insert(ext4_mb_cache, new_bh); 1022 - error = ext4_handle_dirty_xattr_block(handle, 1023 - inode, new_bh); 1027 + error = ext4_handle_dirty_metadata(handle, inode, 1028 + new_bh); 1024 1029 if (error) 1025 1030 goto cleanup; 1026 1031 }
+11 -11
fs/jbd2/journal.c
··· 1125 1125 1126 1126 /* Set up a default-sized revoke table for the new mount. */ 1127 1127 err = jbd2_journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH); 1128 - if (err) { 1129 - kfree(journal); 1130 - return NULL; 1131 - } 1128 + if (err) 1129 + goto err_cleanup; 1132 1130 1133 1131 spin_lock_init(&journal->j_history_lock); 1134 1132 ··· 1143 1145 journal->j_wbufsize = n; 1144 1146 journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *), 1145 1147 GFP_KERNEL); 1146 - if (!journal->j_wbuf) { 1147 - kfree(journal); 1148 - return NULL; 1149 - } 1148 + if (!journal->j_wbuf) 1149 + goto err_cleanup; 1150 1150 1151 1151 bh = getblk_unmovable(journal->j_dev, start, journal->j_blocksize); 1152 1152 if (!bh) { 1153 1153 pr_err("%s: Cannot get buffer for journal superblock\n", 1154 1154 __func__); 1155 - kfree(journal->j_wbuf); 1156 - kfree(journal); 1157 - return NULL; 1155 + goto err_cleanup; 1158 1156 } 1159 1157 journal->j_sb_buffer = bh; 1160 1158 journal->j_superblock = (journal_superblock_t *)bh->b_data; 1161 1159 1162 1160 return journal; 1161 + 1162 + err_cleanup: 1163 + kfree(journal->j_wbuf); 1164 + jbd2_journal_destroy_revoke(journal); 1165 + kfree(journal); 1166 + return NULL; 1163 1167 } 1164 1168 1165 1169 /* jbd2_journal_init_dev and jbd2_journal_init_inode:
+1
fs/jbd2/revoke.c
··· 280 280 281 281 fail1: 282 282 jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); 283 + journal->j_revoke_table[0] = NULL; 283 284 fail0: 284 285 return -ENOMEM; 285 286 }