Skip to content

Commit 17403fa

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 for 5.1" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: prohibit fstrim in norecovery mode ext4: cleanup bh release code in ext4_ind_remove_space() ext4: brelse all indirect buffer in ext4_ind_remove_space() ext4: report real fs size after failed resize ext4: add missing brelse() in add_new_gdb_meta_bg() ext4: remove useless ext4_pin_inode() ext4: avoid panic during forced reboot ext4: fix data corruption caused by unaligned direct AIO ext4: fix NULL pointer dereference while journal is aborted
2 parents 231c807 + 18915b5 commit 17403fa

File tree

7 files changed

+58
-59
lines changed

7 files changed

+58
-59
lines changed

fs/ext4/ext4_jbd2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle,
384384
{
385385
struct ext4_inode_info *ei = EXT4_I(inode);
386386

387-
if (ext4_handle_valid(handle)) {
387+
if (ext4_handle_valid(handle) && !is_handle_aborted(handle)) {
388388
ei->i_sync_tid = handle->h_transaction->t_tid;
389389
if (datasync)
390390
ei->i_datasync_tid = handle->h_transaction->t_tid;

fs/ext4/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ ext4_unaligned_aio(struct inode *inode, struct iov_iter *from, loff_t pos)
125125
struct super_block *sb = inode->i_sb;
126126
int blockmask = sb->s_blocksize - 1;
127127

128-
if (pos >= i_size_read(inode))
128+
if (pos >= ALIGN(i_size_read(inode), sb->s_blocksize))
129129
return 0;
130130

131131
if ((pos | iov_iter_alignment(from)) & blockmask)

fs/ext4/indirect.c

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
12221222
ext4_lblk_t offsets[4], offsets2[4];
12231223
Indirect chain[4], chain2[4];
12241224
Indirect *partial, *partial2;
1225+
Indirect *p = NULL, *p2 = NULL;
12251226
ext4_lblk_t max_block;
12261227
__le32 nr = 0, nr2 = 0;
12271228
int n = 0, n2 = 0;
@@ -1263,7 +1264,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
12631264
}
12641265

12651266

1266-
partial = ext4_find_shared(inode, n, offsets, chain, &nr);
1267+
partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
12671268
if (nr) {
12681269
if (partial == chain) {
12691270
/* Shared branch grows from the inode */
@@ -1288,13 +1289,11 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
12881289
partial->p + 1,
12891290
(__le32 *)partial->bh->b_data+addr_per_block,
12901291
(chain+n-1) - partial);
1291-
BUFFER_TRACE(partial->bh, "call brelse");
1292-
brelse(partial->bh);
12931292
partial--;
12941293
}
12951294

12961295
end_range:
1297-
partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1296+
partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
12981297
if (nr2) {
12991298
if (partial2 == chain2) {
13001299
/*
@@ -1324,16 +1323,14 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
13241323
(__le32 *)partial2->bh->b_data,
13251324
partial2->p,
13261325
(chain2+n2-1) - partial2);
1327-
BUFFER_TRACE(partial2->bh, "call brelse");
1328-
brelse(partial2->bh);
13291326
partial2--;
13301327
}
13311328
goto do_indirects;
13321329
}
13331330

13341331
/* Punch happened within the same level (n == n2) */
1335-
partial = ext4_find_shared(inode, n, offsets, chain, &nr);
1336-
partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1332+
partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
1333+
partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
13371334

13381335
/* Free top, but only if partial2 isn't its subtree. */
13391336
if (nr) {
@@ -1390,11 +1387,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
13901387
partial->p + 1,
13911388
partial2->p,
13921389
(chain+n-1) - partial);
1393-
BUFFER_TRACE(partial->bh, "call brelse");
1394-
brelse(partial->bh);
1395-
BUFFER_TRACE(partial2->bh, "call brelse");
1396-
brelse(partial2->bh);
1397-
return 0;
1390+
goto cleanup;
13981391
}
13991392

14001393
/*
@@ -1409,28 +1402,36 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14091402
partial->p + 1,
14101403
(__le32 *)partial->bh->b_data+addr_per_block,
14111404
(chain+n-1) - partial);
1412-
BUFFER_TRACE(partial->bh, "call brelse");
1413-
brelse(partial->bh);
14141405
partial--;
14151406
}
14161407
if (partial2 > chain2 && depth2 <= depth) {
14171408
ext4_free_branches(handle, inode, partial2->bh,
14181409
(__le32 *)partial2->bh->b_data,
14191410
partial2->p,
14201411
(chain2+n2-1) - partial2);
1421-
BUFFER_TRACE(partial2->bh, "call brelse");
1422-
brelse(partial2->bh);
14231412
partial2--;
14241413
}
14251414
}
1415+
1416+
cleanup:
1417+
while (p && p > chain) {
1418+
BUFFER_TRACE(p->bh, "call brelse");
1419+
brelse(p->bh);
1420+
p--;
1421+
}
1422+
while (p2 && p2 > chain2) {
1423+
BUFFER_TRACE(p2->bh, "call brelse");
1424+
brelse(p2->bh);
1425+
p2--;
1426+
}
14261427
return 0;
14271428

14281429
do_indirects:
14291430
/* Kill the remaining (whole) subtrees */
14301431
switch (offsets[0]) {
14311432
default:
14321433
if (++n >= n2)
1433-
return 0;
1434+
break;
14341435
nr = i_data[EXT4_IND_BLOCK];
14351436
if (nr) {
14361437
ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
@@ -1439,7 +1440,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14391440
/* fall through */
14401441
case EXT4_IND_BLOCK:
14411442
if (++n >= n2)
1442-
return 0;
1443+
break;
14431444
nr = i_data[EXT4_DIND_BLOCK];
14441445
if (nr) {
14451446
ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
@@ -1448,7 +1449,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14481449
/* fall through */
14491450
case EXT4_DIND_BLOCK:
14501451
if (++n >= n2)
1451-
return 0;
1452+
break;
14521453
nr = i_data[EXT4_TIND_BLOCK];
14531454
if (nr) {
14541455
ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
@@ -1458,5 +1459,5 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14581459
case EXT4_TIND_BLOCK:
14591460
;
14601461
}
1461-
return 0;
1462+
goto cleanup;
14621463
}

fs/ext4/inode.c

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6080,36 +6080,6 @@ void ext4_dirty_inode(struct inode *inode, int flags)
60806080
return;
60816081
}
60826082

6083-
#if 0
6084-
/*
6085-
* Bind an inode's backing buffer_head into this transaction, to prevent
6086-
* it from being flushed to disk early. Unlike
6087-
* ext4_reserve_inode_write, this leaves behind no bh reference and
6088-
* returns no iloc structure, so the caller needs to repeat the iloc
6089-
* lookup to mark the inode dirty later.
6090-
*/
6091-
static int ext4_pin_inode(handle_t *handle, struct inode *inode)
6092-
{
6093-
struct ext4_iloc iloc;
6094-
6095-
int err = 0;
6096-
if (handle) {
6097-
err = ext4_get_inode_loc(inode, &iloc);
6098-
if (!err) {
6099-
BUFFER_TRACE(iloc.bh, "get_write_access");
6100-
err = jbd2_journal_get_write_access(handle, iloc.bh);
6101-
if (!err)
6102-
err = ext4_handle_dirty_metadata(handle,
6103-
NULL,
6104-
iloc.bh);
6105-
brelse(iloc.bh);
6106-
}
6107-
}
6108-
ext4_std_error(inode->i_sb, err);
6109-
return err;
6110-
}
6111-
#endif
6112-
61136083
int ext4_change_inode_journal_flag(struct inode *inode, int val)
61146084
{
61156085
journal_t *journal;

fs/ext4/ioctl.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,13 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
10001000
if (!blk_queue_discard(q))
10011001
return -EOPNOTSUPP;
10021002

1003+
/*
1004+
* We haven't replayed the journal, so we cannot use our
1005+
* block-bitmap-guided storage zapping commands.
1006+
*/
1007+
if (test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb))
1008+
return -EROFS;
1009+
10031010
if (copy_from_user(&range, (struct fstrim_range __user *)arg,
10041011
sizeof(range)))
10051012
return -EFAULT;

fs/ext4/resize.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -932,11 +932,18 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
932932
memcpy(n_group_desc, o_group_desc,
933933
EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
934934
n_group_desc[gdb_num] = gdb_bh;
935+
936+
BUFFER_TRACE(gdb_bh, "get_write_access");
937+
err = ext4_journal_get_write_access(handle, gdb_bh);
938+
if (err) {
939+
kvfree(n_group_desc);
940+
brelse(gdb_bh);
941+
return err;
942+
}
943+
935944
EXT4_SB(sb)->s_group_desc = n_group_desc;
936945
EXT4_SB(sb)->s_gdb_count++;
937946
kvfree(o_group_desc);
938-
BUFFER_TRACE(gdb_bh, "get_write_access");
939-
err = ext4_journal_get_write_access(handle, gdb_bh);
940947
return err;
941948
}
942949

@@ -2073,6 +2080,10 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
20732080
free_flex_gd(flex_gd);
20742081
if (resize_inode != NULL)
20752082
iput(resize_inode);
2076-
ext4_msg(sb, KERN_INFO, "resized filesystem to %llu", n_blocks_count);
2083+
if (err)
2084+
ext4_warning(sb, "error (%d) occurred during "
2085+
"file system resize", err);
2086+
ext4_msg(sb, KERN_INFO, "resized filesystem to %llu",
2087+
ext4_blocks_count(es));
20772088
return err;
20782089
}

fs/ext4/super.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,12 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
430430
spin_unlock(&sbi->s_md_lock);
431431
}
432432

433+
static bool system_going_down(void)
434+
{
435+
return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
436+
|| system_state == SYSTEM_RESTART;
437+
}
438+
433439
/* Deal with the reporting of failure conditions on a filesystem such as
434440
* inconsistencies detected or read IO failures.
435441
*
@@ -460,16 +466,20 @@ static void ext4_handle_error(struct super_block *sb)
460466
if (journal)
461467
jbd2_journal_abort(journal, -EIO);
462468
}
463-
if (test_opt(sb, ERRORS_RO)) {
469+
/*
470+
* We force ERRORS_RO behavior when system is rebooting. Otherwise we
471+
* could panic during 'reboot -f' as the underlying device got already
472+
* disabled.
473+
*/
474+
if (test_opt(sb, ERRORS_RO) || system_going_down()) {
464475
ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
465476
/*
466477
* Make sure updated value of ->s_mount_flags will be visible
467478
* before ->s_flags update
468479
*/
469480
smp_wmb();
470481
sb->s_flags |= SB_RDONLY;
471-
}
472-
if (test_opt(sb, ERRORS_PANIC)) {
482+
} else if (test_opt(sb, ERRORS_PANIC)) {
473483
if (EXT4_SB(sb)->s_journal &&
474484
!(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
475485
return;

0 commit comments

Comments
 (0)