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
Unified · Split
| @@ -384,7 +384,7 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle, · 383 unmodified lines | ||
| 384 | 384 | { |
| 385 | 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 | 388 | ei->i_sync_tid = handle->h_transaction->t_tid; |
| 389 | 389 | if (datasync) |
| 390 | 390 | ei->i_datasync_tid = handle->h_transaction->t_tid; |
| @@ -125,7 +125,7 @@ ext4_unaligned_aio(struct inode *inode, struct iov_iter *from, loff_t pos) · 124 unmodified lines | ||
| 125 | 125 | struct super_block *sb = inode->i_sb; |
| 126 | 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 | 129 | return 0; |
| 130 | 130 | |
| 131 | 131 | if ((pos | iov_iter_alignment(from)) & blockmask) |
| @@ -1222,6 +1222,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode, · 1221 unmodified lines | ||
| 1222 | 1222 | ext4_lblk_t offsets[4], offsets2[4]; |
| 1223 | 1223 | Indirect chain[4], chain2[4]; |
| 1224 | 1224 | Indirect *partial, *partial2; |
| 1225 | + Indirect *p = NULL, *p2 = NULL; | |
| 1225 | 1226 | ext4_lblk_t max_block; |
| 1226 | 1227 | __le32 nr = 0, nr2 = 0; |
| 1227 | 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 | 1268 | if (nr) { |
| 1268 | 1269 | if (partial == chain) { |
| 1269 | 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 | 1289 | partial->p + 1, |
| 1289 | 1290 | (__le32 *)partial->bh->b_data+addr_per_block, |
| 1290 | 1291 | (chain+n-1) - partial); |
| 1291 | − BUFFER_TRACE(partial->bh, "call brelse"); | |
| 1292 | − brelse(partial->bh); | |
| 1293 | 1292 | partial--; |
| 1294 | 1293 | } |
| 1295 | 1294 | |
| 1296 | 1295 | end_range: |
| 1297 | − partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); | |
| 1296 | + partial2 = p2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); | |
| 1298 | 1297 | if (nr2) { |
| 1299 | 1298 | if (partial2 == chain2) { |
| 1300 | 1299 | /* |
| @@ -1324,16 +1323,14 @@ end_range: · 23 unmodified lines | ||
| 1324 | 1323 | (__le32 *)partial2->bh->b_data, |
| 1325 | 1324 | partial2->p, |
| 1326 | 1325 | (chain2+n2-1) - partial2); |
| 1327 | − BUFFER_TRACE(partial2->bh, "call brelse"); | |
| 1328 | − brelse(partial2->bh); | |
| 1329 | 1326 | partial2--; |
| 1330 | 1327 | } |
| 1331 | 1328 | goto do_indirects; |
| 1332 | 1329 | } |
| 1333 | 1330 | |
| 1334 | 1331 | /* 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); | |
| 1337 | 1334 | |
| 1338 | 1335 | /* Free top, but only if partial2 isn't its subtree. */ |
| 1339 | 1336 | if (nr) { |
| @@ -1390,11 +1387,7 @@ end_range: · 50 unmodified lines | ||
| 1390 | 1387 | partial->p + 1, |
| 1391 | 1388 | partial2->p, |
| 1392 | 1389 | (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; | |
| 1398 | 1391 | } |
| 1399 | 1392 | |
| 1400 | 1393 | /* |
| @@ -1409,8 +1402,6 @@ end_range: · 8 unmodified lines | ||
| 1409 | 1402 | partial->p + 1, |
| 1410 | 1403 | (__le32 *)partial->bh->b_data+addr_per_block, |
| 1411 | 1404 | (chain+n-1) - partial); |
| 1412 | − BUFFER_TRACE(partial->bh, "call brelse"); | |
| 1413 | − brelse(partial->bh); | |
| 1414 | 1405 | partial--; |
| 1415 | 1406 | } |
| 1416 | 1407 | if (partial2 > chain2 && depth2 <= depth) { |
| @@ -1418,11 +1409,21 @@ end_range: · 1 unmodified line | ||
| 1418 | 1409 | (__le32 *)partial2->bh->b_data, |
| 1419 | 1410 | partial2->p, |
| 1420 | 1411 | (chain2+n2-1) - partial2); |
| 1421 | − BUFFER_TRACE(partial2->bh, "call brelse"); | |
| 1422 | − brelse(partial2->bh); | |
| 1423 | 1412 | partial2--; |
| 1424 | 1413 | } |
| 1425 | 1414 | } |
| 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 | + } | |
| 1426 | 1427 | return 0; |
| 1427 | 1428 | |
| 1428 | 1429 | do_indirects: |
| @@ -1430,7 +1431,7 @@ do_indirects: · 1 unmodified line | ||
| 1430 | 1431 | switch (offsets[0]) { |
| 1431 | 1432 | default: |
| 1432 | 1433 | if (++n >= n2) |
| 1433 | − return 0; | |
| 1434 | + break; | |
| 1434 | 1435 | nr = i_data[EXT4_IND_BLOCK]; |
| 1435 | 1436 | if (nr) { |
| 1436 | 1437 | ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1); |
| @@ -1439,7 +1440,7 @@ do_indirects: · 2 unmodified lines | ||
| 1439 | 1440 | /* fall through */ |
| 1440 | 1441 | case EXT4_IND_BLOCK: |
| 1441 | 1442 | if (++n >= n2) |
| 1442 | − return 0; | |
| 1443 | + break; | |
| 1443 | 1444 | nr = i_data[EXT4_DIND_BLOCK]; |
| 1444 | 1445 | if (nr) { |
| 1445 | 1446 | ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2); |
| @@ -1448,7 +1449,7 @@ do_indirects: · 2 unmodified lines | ||
| 1448 | 1449 | /* fall through */ |
| 1449 | 1450 | case EXT4_DIND_BLOCK: |
| 1450 | 1451 | if (++n >= n2) |
| 1451 | − return 0; | |
| 1452 | + break; | |
| 1452 | 1453 | nr = i_data[EXT4_TIND_BLOCK]; |
| 1453 | 1454 | if (nr) { |
| 1454 | 1455 | ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3); |
| @@ -1458,5 +1459,5 @@ do_indirects: · 3 unmodified lines | ||
| 1458 | 1459 | case EXT4_TIND_BLOCK: |
| 1459 | 1460 | ; |
| 1460 | 1461 | } |
| 1461 | − return 0; | |
| 1462 | + goto cleanup; | |
| 1462 | 1463 | } |
| @@ -6080,36 +6080,6 @@ out: · 6079 unmodified lines | ||
| 6080 | 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 | − */ | |
| 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 | − | |
| 6113 | 6083 | int ext4_change_inode_journal_flag(struct inode *inode, int val) |
| 6114 | 6084 | { |
| 6115 | 6085 | journal_t *journal; |
| @@ -1000,6 +1000,13 @@ resizefs_out: · 999 unmodified lines | ||
| 1000 | 1000 | if (!blk_queue_discard(q)) |
| 1001 | 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 | 1010 | if (copy_from_user(&range, (struct fstrim_range __user *)arg, |
| 1004 | 1011 | sizeof(range))) |
| 1005 | 1012 | return -EFAULT; |
| @@ -932,11 +932,18 @@ static int add_new_gdb_meta_bg(struct super_block *sb, · 931 unmodified lines | ||
| 932 | 932 | memcpy(n_group_desc, o_group_desc, |
| 933 | 933 | EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); |
| 934 | 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 | 944 | EXT4_SB(sb)->s_group_desc = n_group_desc; |
| 936 | 945 | EXT4_SB(sb)->s_gdb_count++; |
| 937 | 946 | kvfree(o_group_desc); |
| 938 | − BUFFER_TRACE(gdb_bh, "get_write_access"); | |
| 939 | − err = ext4_journal_get_write_access(handle, gdb_bh); | |
| 940 | 947 | return err; |
| 941 | 948 | } |
| 942 | 949 | |
| @@ -2073,6 +2080,10 @@ out: · 1130 unmodified lines | ||
| 2073 | 2080 | free_flex_gd(flex_gd); |
| 2074 | 2081 | if (resize_inode != NULL) |
| 2075 | 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 | 2088 | return err; |
| 2078 | 2089 | } |
| @@ -430,6 +430,12 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) · 429 unmodified lines | ||
| 430 | 430 | spin_unlock(&sbi->s_md_lock); |
| 431 | 431 | } |
| 432 | 432 | |
| 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 | + | |
| 433 | 439 | /* Deal with the reporting of failure conditions on a filesystem such as |
| 434 | 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 | 466 | if (journal) |
| 461 | 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 | 475 | ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); |
| 465 | 476 | /* |
| 466 | 477 | * 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 | 480 | smp_wmb(); |
| 470 | 481 | sb->s_flags |= SB_RDONLY; |
| 471 | − } | |
| 472 | − if (test_opt(sb, ERRORS_PANIC)) { | |
| 482 | + } else if (test_opt(sb, ERRORS_PANIC)) { | |
| 473 | 483 | if (EXT4_SB(sb)->s_journal && |
| 474 | 484 | !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) |
| 475 | 485 | return; |