diff options
-rw-r--r-- | fs/ext4/ext4_jbd2.h | 2 | ||||
-rw-r--r-- | fs/ext4/file.c | 2 | ||||
-rw-r--r-- | fs/ext4/indirect.c | 43 | ||||
-rw-r--r-- | fs/ext4/inode.c | 30 | ||||
-rw-r--r-- | fs/ext4/ioctl.c | 7 | ||||
-rw-r--r-- | fs/ext4/resize.c | 17 | ||||
-rw-r--r-- | fs/ext4/super.c | 16 |
7 files changed, 58 insertions, 59 deletions
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index a1ac7e9245ec..75a5309f2231 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
@@ -384,7 +384,7 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle, | |||
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; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 69d65d49837b..98ec11f69cd4 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -125,7 +125,7 @@ ext4_unaligned_aio(struct inode *inode, struct iov_iter *from, loff_t pos) | |||
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) |
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index c2225f0d31b5..2024d3fa5504 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c | |||
@@ -1222,6 +1222,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode, | |||
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, | |||
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, | |||
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 | ||
1296 | end_range: | 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 | if (nr2) { | 1297 | if (nr2) { |
1299 | if (partial2 == chain2) { | 1298 | if (partial2 == chain2) { |
1300 | /* | 1299 | /* |
@@ -1324,16 +1323,14 @@ end_range: | |||
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: | |||
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: | |||
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: | |||
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 | |||
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 | return 0; | 1427 | return 0; |
1427 | 1428 | ||
1428 | do_indirects: | 1429 | do_indirects: |
@@ -1430,7 +1431,7 @@ do_indirects: | |||
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: | |||
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: | |||
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: | |||
1458 | case EXT4_TIND_BLOCK: | 1459 | case EXT4_TIND_BLOCK: |
1459 | ; | 1460 | ; |
1460 | } | 1461 | } |
1461 | return 0; | 1462 | goto cleanup; |
1462 | } | 1463 | } |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b54b261ded36..b32a57bc5d5d 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -6080,36 +6080,6 @@ out: | |||
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 | */ | ||
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 | int ext4_change_inode_journal_flag(struct inode *inode, int val) | 6083 | int ext4_change_inode_journal_flag(struct inode *inode, int val) |
6114 | { | 6084 | { |
6115 | journal_t *journal; | 6085 | journal_t *journal; |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 3c4f8bb59f8a..bab3da4f1e0d 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -1000,6 +1000,13 @@ resizefs_out: | |||
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; |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 3d9b18505c0c..e7ae26e36c9c 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -932,11 +932,18 @@ static int add_new_gdb_meta_bg(struct super_block *sb, | |||
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: | |||
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 | } |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f5b828bf1299..6ed4eb81e674 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -430,6 +430,12 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) | |||
430 | spin_unlock(&sbi->s_md_lock); | 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 | /* Deal with the reporting of failure conditions on a filesystem such as | 439 | /* 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) | |||
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 visible | 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) | |||
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; |