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; |
