History

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

Linus Torvalds committed 7 years ago

Commit 17403fa2 parents 231c807 18915b57 files · +58 −59Browse files

Unified · Split

7 files
  1. fs/ext4/ext4_jbd2.h +1 −1
  2. fs/ext4/file.c +1 −1
  3. fs/ext4/indirect.c +22 −21
  4. fs/ext4/inode.c +0 −30
  5. fs/ext4/ioctl.c +7 −0
  6. fs/ext4/resize.c +14 −3
  7. fs/ext4/super.c +13 −3
fs/ext4/ext4_jbd2.h+1−1
@@ -384,7 +384,7 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle, · 383 unmodified lines
384{384{
385 struct ext4_inode_info *ei = EXT4_I(inode);385 struct ext4_inode_info *ei = EXT4_I(inode);
386 386
387 if (ext4_handle_valid(handle)) {387 if (ext4_handle_valid(handle) && !is_handle_aborted(handle)) {
388 ei->i_sync_tid = handle->h_transaction->t_tid;388 ei->i_sync_tid = handle->h_transaction->t_tid;
389 if (datasync)389 if (datasync)
390 ei->i_datasync_tid = handle->h_transaction->t_tid;390 ei->i_datasync_tid = handle->h_transaction->t_tid;
fs/ext4/file.c+1−1
@@ -125,7 +125,7 @@ ext4_unaligned_aio(struct inode *inode, struct iov_iter *from, loff_t pos) · 124 unmodified lines
125 struct super_block *sb = inode->i_sb;125 struct super_block *sb = inode->i_sb;
126 int blockmask = sb->s_blocksize - 1;126 int blockmask = sb->s_blocksize - 1;
127 127
128 if (pos >= i_size_read(inode))128 if (pos >= ALIGN(i_size_read(inode), sb->s_blocksize))
129 return 0;129 return 0;
130 130
131 if ((pos | iov_iter_alignment(from)) & blockmask)131 if ((pos | iov_iter_alignment(from)) & blockmask)
fs/ext4/indirect.c+22−21
@@ -1222,6 +1222,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode, · 1221 unmodified lines
1222 ext4_lblk_t offsets[4], offsets2[4];1222 ext4_lblk_t offsets[4], offsets2[4];
1223 Indirect chain[4], chain2[4];1223 Indirect chain[4], chain2[4];
1224 Indirect *partial, *partial2;1224 Indirect *partial, *partial2;
1225 Indirect *p = NULL, *p2 = NULL;
1225 ext4_lblk_t max_block;1226 ext4_lblk_t max_block;
1226 __le32 nr = 0, nr2 = 0;1227 __le32 nr = 0, nr2 = 0;
1227 int n = 0, n2 = 0;1228 int n = 0, n2 = 0;
@@ -1263,7 +1264,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode, · 35 unmodified lines
1263 }1264 }
1264 1265
1265 1266
1266 partial = ext4_find_shared(inode, n, offsets, chain, &nr);1267 partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
1267 if (nr) {1268 if (nr) {
1268 if (partial == chain) {1269 if (partial == chain) {
1269 /* Shared branch grows from the inode */1270 /* Shared branch grows from the inode */
@@ -1288,13 +1289,11 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode, · 18 unmodified lines
1288 partial->p + 1,1289 partial->p + 1,
1289 (__le32 *)partial->bh->b_data+addr_per_block,1290 (__le32 *)partial->bh->b_data+addr_per_block,
1290 (chain+n-1) - partial);1291 (chain+n-1) - partial);
1291 BUFFER_TRACE(partial->bh, "call brelse");
1292 brelse(partial->bh);
1293 partial--;1292 partial--;
1294 }1293 }
1295 1294
1296end_range:1295end_range:
1297 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);1296 partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1298 if (nr2) {1297 if (nr2) {
1299 if (partial2 == chain2) {1298 if (partial2 == chain2) {
1300 /*1299 /*
@@ -1324,16 +1323,14 @@ end_range: · 23 unmodified lines
1324 (__le32 *)partial2->bh->b_data,1323 (__le32 *)partial2->bh->b_data,
1325 partial2->p,1324 partial2->p,
1326 (chain2+n2-1) - partial2);1325 (chain2+n2-1) - partial2);
1327 BUFFER_TRACE(partial2->bh, "call brelse");
1328 brelse(partial2->bh);
1329 partial2--;1326 partial2--;
1330 }1327 }
1331 goto do_indirects;1328 goto do_indirects;
1332 }1329 }
1333 1330
1334 /* Punch happened within the same level (n == n2) */1331 /* Punch happened within the same level (n == n2) */
1335 partial = ext4_find_shared(inode, n, offsets, chain, &nr);1332 partial = p = ext4_find_shared(inode, n, offsets, chain, &nr);
1336 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);1333 partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1337 1334
1338 /* Free top, but only if partial2 isn't its subtree. */1335 /* Free top, but only if partial2 isn't its subtree. */
1339 if (nr) {1336 if (nr) {
@@ -1390,11 +1387,7 @@ end_range: · 50 unmodified lines
1390 partial->p + 1,1387 partial->p + 1,
1391 partial2->p,1388 partial2->p,
1392 (chain+n-1) - partial);1389 (chain+n-1) - partial);
1393 BUFFER_TRACE(partial->bh, "call brelse");1390 goto cleanup;
1394 brelse(partial->bh);
1395 BUFFER_TRACE(partial2->bh, "call brelse");
1396 brelse(partial2->bh);
1397 return 0;
1398 }1391 }
1399 1392
1400 /*1393 /*
@@ -1409,8 +1402,6 @@ end_range: · 8 unmodified lines
1409 partial->p + 1,1402 partial->p + 1,
1410 (__le32 *)partial->bh->b_data+addr_per_block,1403 (__le32 *)partial->bh->b_data+addr_per_block,
1411 (chain+n-1) - partial);1404 (chain+n-1) - partial);
1412 BUFFER_TRACE(partial->bh, "call brelse");
1413 brelse(partial->bh);
1414 partial--;1405 partial--;
1415 }1406 }
1416 if (partial2 > chain2 && depth2 <= depth) {1407 if (partial2 > chain2 && depth2 <= depth) {
@@ -1418,11 +1409,21 @@ end_range: · 1 unmodified line
1418 (__le32 *)partial2->bh->b_data,1409 (__le32 *)partial2->bh->b_data,
1419 partial2->p,1410 partial2->p,
1420 (chain2+n2-1) - partial2);1411 (chain2+n2-1) - partial2);
1421 BUFFER_TRACE(partial2->bh, "call brelse");
1422 brelse(partial2->bh);
1423 partial2--;1412 partial2--;
1424 }1413 }
1425 }1414 }
1415
1416cleanup:
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 }
1426 return 0;1427 return 0;
1427 1428
1428do_indirects:1429do_indirects:
@@ -1430,7 +1431,7 @@ do_indirects: · 1 unmodified line
1430 switch (offsets[0]) {1431 switch (offsets[0]) {
1431 default:1432 default:
1432 if (++n >= n2)1433 if (++n >= n2)
1433 return 0;1434 break;
1434 nr = i_data[EXT4_IND_BLOCK];1435 nr = i_data[EXT4_IND_BLOCK];
1435 if (nr) {1436 if (nr) {
1436 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);1437 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
@@ -1439,7 +1440,7 @@ do_indirects: · 2 unmodified lines
1439 /* fall through */1440 /* fall through */
1440 case EXT4_IND_BLOCK:1441 case EXT4_IND_BLOCK:
1441 if (++n >= n2)1442 if (++n >= n2)
1442 return 0;1443 break;
1443 nr = i_data[EXT4_DIND_BLOCK];1444 nr = i_data[EXT4_DIND_BLOCK];
1444 if (nr) {1445 if (nr) {
1445 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);1446 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
@@ -1448,7 +1449,7 @@ do_indirects: · 2 unmodified lines
1448 /* fall through */1449 /* fall through */
1449 case EXT4_DIND_BLOCK:1450 case EXT4_DIND_BLOCK:
1450 if (++n >= n2)1451 if (++n >= n2)
1451 return 0;1452 break;
1452 nr = i_data[EXT4_TIND_BLOCK];1453 nr = i_data[EXT4_TIND_BLOCK];
1453 if (nr) {1454 if (nr) {
1454 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);1455 ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
@@ -1458,5 +1459,5 @@ do_indirects: · 3 unmodified lines
1458 case EXT4_TIND_BLOCK:1459 case EXT4_TIND_BLOCK:
1459 ;1460 ;
1460 }1461 }
1461 return 0;1462 goto cleanup;
1462}1463}
fs/ext4/inode.c+0−30
@@ -6080,36 +6080,6 @@ out: · 6079 unmodified lines
6080 return;6080 return;
6081}6081}
6082 6082
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 */
6091static 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
6113int ext4_change_inode_journal_flag(struct inode *inode, int val)6083int ext4_change_inode_journal_flag(struct inode *inode, int val)
6114{6084{
6115 journal_t *journal;6085 journal_t *journal;
fs/ext4/ioctl.c+7−0
@@ -1000,6 +1000,13 @@ resizefs_out: · 999 unmodified lines
1000 if (!blk_queue_discard(q))1000 if (!blk_queue_discard(q))
1001 return -EOPNOTSUPP;1001 return -EOPNOTSUPP;
1002 1002
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
1003 if (copy_from_user(&range, (struct fstrim_range __user *)arg,1010 if (copy_from_user(&range, (struct fstrim_range __user *)arg,
1004 sizeof(range)))1011 sizeof(range)))
1005 return -EFAULT;1012 return -EFAULT;
fs/ext4/resize.c+14−3
@@ -932,11 +932,18 @@ static int add_new_gdb_meta_bg(struct super_block *sb, · 931 unmodified lines
932 memcpy(n_group_desc, o_group_desc,932 memcpy(n_group_desc, o_group_desc,
933 EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));933 EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
934 n_group_desc[gdb_num] = gdb_bh;934 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
935 EXT4_SB(sb)->s_group_desc = n_group_desc;944 EXT4_SB(sb)->s_group_desc = n_group_desc;
936 EXT4_SB(sb)->s_gdb_count++;945 EXT4_SB(sb)->s_gdb_count++;
937 kvfree(o_group_desc);946 kvfree(o_group_desc);
938 BUFFER_TRACE(gdb_bh, "get_write_access");
939 err = ext4_journal_get_write_access(handle, gdb_bh);
940 return err;947 return err;
941}948}
942 949
@@ -2073,6 +2080,10 @@ out: · 1130 unmodified lines
2073 free_flex_gd(flex_gd);2080 free_flex_gd(flex_gd);
2074 if (resize_inode != NULL)2081 if (resize_inode != NULL)
2075 iput(resize_inode);2082 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));
2077 return err;2088 return err;
2078}2089}
fs/ext4/super.c+13−3
@@ -430,6 +430,12 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) · 429 unmodified lines
430 spin_unlock(&sbi->s_md_lock);430 spin_unlock(&sbi->s_md_lock);
431}431}
432 432
433static bool system_going_down(void)
434{
435 return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
436 || system_state == SYSTEM_RESTART;
437}
438
433/* Deal with the reporting of failure conditions on a filesystem such as439/* Deal with the reporting of failure conditions on a filesystem such as
434 * inconsistencies detected or read IO failures.440 * inconsistencies detected or read IO failures.
435 *441 *
@@ -460,7 +466,12 @@ static void ext4_handle_error(struct super_block *sb) · 24 unmodified lines
460 if (journal)466 if (journal)
461 jbd2_journal_abort(journal, -EIO);467 jbd2_journal_abort(journal, -EIO);
462 }468 }
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()) {
464 ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");475 ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
465 /*476 /*
466 * Make sure updated value of ->s_mount_flags will be visible477 * Make sure updated value of ->s_mount_flags will be visible
@@ -468,8 +479,7 @@ static void ext4_handle_error(struct super_block *sb) · 1 unmodified line
468 */479 */
469 smp_wmb();480 smp_wmb();
470 sb->s_flags |= SB_RDONLY;481 sb->s_flags |= SB_RDONLY;
471 }482 } else if (test_opt(sb, ERRORS_PANIC)) {
472 if (test_opt(sb, ERRORS_PANIC)) {
473 if (EXT4_SB(sb)->s_journal &&483 if (EXT4_SB(sb)->s_journal &&
474 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))484 !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
475 return;485 return;