Skip to content

Commit 8a8b809

Browse files
committed
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: "Miscellaneous ext4 bug fixes (all stable fodder)" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: improve explanation of a mount failure caused by a misconfigured kernel jbd2: do not clear the BH_Mapped flag when forgetting a metadata buffer jbd2: move the clearing of b_modified flag to the journal_unmap_buffer() ext4: add cond_resched() to ext4_protect_reserved_inode ext4: fix checksum errors with indexed dirs ext4: fix support for inode sizes > 1024 bytes ext4: simplify checking quota limits in ext4_statfs() ext4: don't assume that mmp_nodename/bdevname have NUL
2 parents db70e26 + d65d87a commit 8a8b809

File tree

9 files changed

+86
-63
lines changed

9 files changed

+86
-63
lines changed

fs/ext4/block_validity.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ static int ext4_protect_reserved_inode(struct super_block *sb,
207207
return PTR_ERR(inode);
208208
num = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
209209
while (i < num) {
210+
cond_resched();
210211
map.m_lblk = i;
211212
map.m_len = num - i;
212213
n = ext4_map_blocks(NULL, inode, &map, 0);

fs/ext4/dir.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,14 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
129129
if (err != ERR_BAD_DX_DIR) {
130130
return err;
131131
}
132-
/*
133-
* We don't set the inode dirty flag since it's not
134-
* critical that it get flushed back to the disk.
135-
*/
136-
ext4_clear_inode_flag(file_inode(file),
137-
EXT4_INODE_INDEX);
132+
/* Can we just clear INDEX flag to ignore htree information? */
133+
if (!ext4_has_metadata_csum(sb)) {
134+
/*
135+
* We don't set the inode dirty flag since it's not
136+
* critical that it gets flushed back to the disk.
137+
*/
138+
ext4_clear_inode_flag(inode, EXT4_INODE_INDEX);
139+
}
138140
}
139141

140142
if (ext4_has_inline_data(inode)) {

fs/ext4/ext4.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2544,8 +2544,11 @@ void ext4_insert_dentry(struct inode *inode,
25442544
struct ext4_filename *fname);
25452545
static inline void ext4_update_dx_flag(struct inode *inode)
25462546
{
2547-
if (!ext4_has_feature_dir_index(inode->i_sb))
2547+
if (!ext4_has_feature_dir_index(inode->i_sb)) {
2548+
/* ext4_iget() should have caught this... */
2549+
WARN_ON_ONCE(ext4_has_feature_metadata_csum(inode->i_sb));
25482550
ext4_clear_inode_flag(inode, EXT4_INODE_INDEX);
2551+
}
25492552
}
25502553
static const unsigned char ext4_filetype_table[] = {
25512554
DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK

fs/ext4/inode.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4644,6 +4644,18 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
46444644
ret = -EFSCORRUPTED;
46454645
goto bad_inode;
46464646
}
4647+
/*
4648+
* If dir_index is not enabled but there's dir with INDEX flag set,
4649+
* we'd normally treat htree data as empty space. But with metadata
4650+
* checksumming that corrupts checksums so forbid that.
4651+
*/
4652+
if (!ext4_has_feature_dir_index(sb) && ext4_has_metadata_csum(sb) &&
4653+
ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) {
4654+
ext4_error_inode(inode, function, line, 0,
4655+
"iget: Dir with htree data on filesystem without dir_index feature.");
4656+
ret = -EFSCORRUPTED;
4657+
goto bad_inode;
4658+
}
46474659
ei->i_disksize = inode->i_size;
46484660
#ifdef CONFIG_QUOTA
46494661
ei->i_reserved_quota = 0;

fs/ext4/mmp.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ void __dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp,
120120
{
121121
__ext4_warning(sb, function, line, "%s", msg);
122122
__ext4_warning(sb, function, line,
123-
"MMP failure info: last update time: %llu, last update "
124-
"node: %s, last update device: %s",
125-
(long long unsigned int) le64_to_cpu(mmp->mmp_time),
126-
mmp->mmp_nodename, mmp->mmp_bdevname);
123+
"MMP failure info: last update time: %llu, last update node: %.*s, last update device: %.*s",
124+
(unsigned long long)le64_to_cpu(mmp->mmp_time),
125+
(int)sizeof(mmp->mmp_nodename), mmp->mmp_nodename,
126+
(int)sizeof(mmp->mmp_bdevname), mmp->mmp_bdevname);
127127
}
128128

129129
/*
@@ -154,6 +154,7 @@ static int kmmpd(void *data)
154154
mmp_check_interval = max(EXT4_MMP_CHECK_MULT * mmp_update_interval,
155155
EXT4_MMP_MIN_CHECK_INTERVAL);
156156
mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);
157+
BUILD_BUG_ON(sizeof(mmp->mmp_bdevname) < BDEVNAME_SIZE);
157158
bdevname(bh->b_bdev, mmp->mmp_bdevname);
158159

159160
memcpy(mmp->mmp_nodename, init_utsname()->nodename,
@@ -379,7 +380,8 @@ int ext4_multi_mount_protect(struct super_block *sb,
379380
/*
380381
* Start a kernel thread to update the MMP block periodically.
381382
*/
382-
EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%s",
383+
EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%.*s",
384+
(int)sizeof(mmp->mmp_bdevname),
383385
bdevname(bh->b_bdev,
384386
mmp->mmp_bdevname));
385387
if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) {

fs/ext4/namei.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,6 +2213,13 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
22132213
retval = ext4_dx_add_entry(handle, &fname, dir, inode);
22142214
if (!retval || (retval != ERR_BAD_DX_DIR))
22152215
goto out;
2216+
/* Can we just ignore htree data? */
2217+
if (ext4_has_metadata_csum(sb)) {
2218+
EXT4_ERROR_INODE(dir,
2219+
"Directory has corrupted htree index.");
2220+
retval = -EFSCORRUPTED;
2221+
goto out;
2222+
}
22162223
ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
22172224
dx_fallback++;
22182225
ext4_mark_inode_dirty(handle, dir);

fs/ext4/super.c

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3009,17 +3009,11 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
30093009
return 0;
30103010
}
30113011

3012-
#ifndef CONFIG_QUOTA
3013-
if (ext4_has_feature_quota(sb) && !readonly) {
3012+
#if !defined(CONFIG_QUOTA) || !defined(CONFIG_QFMT_V2)
3013+
if (!readonly && (ext4_has_feature_quota(sb) ||
3014+
ext4_has_feature_project(sb))) {
30143015
ext4_msg(sb, KERN_ERR,
3015-
"Filesystem with quota feature cannot be mounted RDWR "
3016-
"without CONFIG_QUOTA");
3017-
return 0;
3018-
}
3019-
if (ext4_has_feature_project(sb) && !readonly) {
3020-
ext4_msg(sb, KERN_ERR,
3021-
"Filesystem with project quota feature cannot be mounted RDWR "
3022-
"without CONFIG_QUOTA");
3016+
"The kernel was not built with CONFIG_QUOTA and CONFIG_QFMT_V2");
30233017
return 0;
30243018
}
30253019
#endif /* CONFIG_QUOTA */
@@ -3814,6 +3808,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
38143808
*/
38153809
sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
38163810

3811+
blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
3812+
if (blocksize < EXT4_MIN_BLOCK_SIZE ||
3813+
blocksize > EXT4_MAX_BLOCK_SIZE) {
3814+
ext4_msg(sb, KERN_ERR,
3815+
"Unsupported filesystem blocksize %d (%d log_block_size)",
3816+
blocksize, le32_to_cpu(es->s_log_block_size));
3817+
goto failed_mount;
3818+
}
3819+
38173820
if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
38183821
sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
38193822
sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
@@ -3831,6 +3834,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
38313834
ext4_msg(sb, KERN_ERR,
38323835
"unsupported inode size: %d",
38333836
sbi->s_inode_size);
3837+
ext4_msg(sb, KERN_ERR, "blocksize: %d", blocksize);
38343838
goto failed_mount;
38353839
}
38363840
/*
@@ -4033,14 +4037,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
40334037
if (!ext4_feature_set_ok(sb, (sb_rdonly(sb))))
40344038
goto failed_mount;
40354039

4036-
blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
4037-
if (blocksize < EXT4_MIN_BLOCK_SIZE ||
4038-
blocksize > EXT4_MAX_BLOCK_SIZE) {
4039-
ext4_msg(sb, KERN_ERR,
4040-
"Unsupported filesystem blocksize %d (%d log_block_size)",
4041-
blocksize, le32_to_cpu(es->s_log_block_size));
4042-
goto failed_mount;
4043-
}
40444040
if (le32_to_cpu(es->s_log_block_size) >
40454041
(EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
40464042
ext4_msg(sb, KERN_ERR,
@@ -5585,10 +5581,7 @@ static int ext4_statfs_project(struct super_block *sb,
55855581
return PTR_ERR(dquot);
55865582
spin_lock(&dquot->dq_dqb_lock);
55875583

5588-
limit = 0;
5589-
if (dquot->dq_dqb.dqb_bsoftlimit &&
5590-
(!limit || dquot->dq_dqb.dqb_bsoftlimit < limit))
5591-
limit = dquot->dq_dqb.dqb_bsoftlimit;
5584+
limit = dquot->dq_dqb.dqb_bsoftlimit;
55925585
if (dquot->dq_dqb.dqb_bhardlimit &&
55935586
(!limit || dquot->dq_dqb.dqb_bhardlimit < limit))
55945587
limit = dquot->dq_dqb.dqb_bhardlimit;
@@ -5603,10 +5596,7 @@ static int ext4_statfs_project(struct super_block *sb,
56035596
(buf->f_blocks - curblock) : 0;
56045597
}
56055598

5606-
limit = 0;
5607-
if (dquot->dq_dqb.dqb_isoftlimit &&
5608-
(!limit || dquot->dq_dqb.dqb_isoftlimit < limit))
5609-
limit = dquot->dq_dqb.dqb_isoftlimit;
5599+
limit = dquot->dq_dqb.dqb_isoftlimit;
56105600
if (dquot->dq_dqb.dqb_ihardlimit &&
56115601
(!limit || dquot->dq_dqb.dqb_ihardlimit < limit))
56125602
limit = dquot->dq_dqb.dqb_ihardlimit;

fs/jbd2/commit.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -976,29 +976,33 @@ void jbd2_journal_commit_transaction(journal_t *journal)
976976
* it. */
977977

978978
/*
979-
* A buffer which has been freed while still being journaled by
980-
* a previous transaction.
981-
*/
982-
if (buffer_freed(bh)) {
979+
* A buffer which has been freed while still being journaled
980+
* by a previous transaction, refile the buffer to BJ_Forget of
981+
* the running transaction. If the just committed transaction
982+
* contains "add to orphan" operation, we can completely
983+
* invalidate the buffer now. We are rather through in that
984+
* since the buffer may be still accessible when blocksize <
985+
* pagesize and it is attached to the last partial page.
986+
*/
987+
if (buffer_freed(bh) && !jh->b_next_transaction) {
988+
struct address_space *mapping;
989+
990+
clear_buffer_freed(bh);
991+
clear_buffer_jbddirty(bh);
992+
983993
/*
984-
* If the running transaction is the one containing
985-
* "add to orphan" operation (b_next_transaction !=
986-
* NULL), we have to wait for that transaction to
987-
* commit before we can really get rid of the buffer.
988-
* So just clear b_modified to not confuse transaction
989-
* credit accounting and refile the buffer to
990-
* BJ_Forget of the running transaction. If the just
991-
* committed transaction contains "add to orphan"
992-
* operation, we can completely invalidate the buffer
993-
* now. We are rather through in that since the
994-
* buffer may be still accessible when blocksize <
995-
* pagesize and it is attached to the last partial
996-
* page.
994+
* Block device buffers need to stay mapped all the
995+
* time, so it is enough to clear buffer_jbddirty and
996+
* buffer_freed bits. For the file mapping buffers (i.e.
997+
* journalled data) we need to unmap buffer and clear
998+
* more bits. We also need to be careful about the check
999+
* because the data page mapping can get cleared under
1000+
* out hands, which alse need not to clear more bits
1001+
* because the page and buffers will be freed and can
1002+
* never be reused once we are done with them.
9971003
*/
998-
jh->b_modified = 0;
999-
if (!jh->b_next_transaction) {
1000-
clear_buffer_freed(bh);
1001-
clear_buffer_jbddirty(bh);
1004+
mapping = READ_ONCE(bh->b_page->mapping);
1005+
if (mapping && !sb_is_blkdev_sb(mapping->host->i_sb)) {
10021006
clear_buffer_mapped(bh);
10031007
clear_buffer_new(bh);
10041008
clear_buffer_req(bh);

fs/jbd2/transaction.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,14 +2329,16 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
23292329
return -EBUSY;
23302330
}
23312331
/*
2332-
* OK, buffer won't be reachable after truncate. We just set
2333-
* j_next_transaction to the running transaction (if there is
2334-
* one) and mark buffer as freed so that commit code knows it
2335-
* should clear dirty bits when it is done with the buffer.
2332+
* OK, buffer won't be reachable after truncate. We just clear
2333+
* b_modified to not confuse transaction credit accounting, and
2334+
* set j_next_transaction to the running transaction (if there
2335+
* is one) and mark buffer as freed so that commit code knows
2336+
* it should clear dirty bits when it is done with the buffer.
23362337
*/
23372338
set_buffer_freed(bh);
23382339
if (journal->j_running_transaction && buffer_jbddirty(bh))
23392340
jh->b_next_transaction = journal->j_running_transaction;
2341+
jh->b_modified = 0;
23402342
spin_unlock(&journal->j_list_lock);
23412343
spin_unlock(&jh->b_state_lock);
23422344
write_unlock(&journal->j_state_lock);

0 commit comments

Comments
 (0)