aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4.h18
-rw-r--r--fs/ext4/indirect.c105
-rw-r--r--fs/ext4/inode.c7
-rw-r--r--fs/ext4/super.c31
-rw-r--r--fs/jbd2/recovery.c3
5 files changed, 108 insertions, 56 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 982d934fd9ac..f63c3d5805c4 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -364,7 +364,8 @@ struct flex_groups {
364#define EXT4_DIRTY_FL 0x00000100 364#define EXT4_DIRTY_FL 0x00000100
365#define EXT4_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ 365#define EXT4_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
366#define EXT4_NOCOMPR_FL 0x00000400 /* Don't compress */ 366#define EXT4_NOCOMPR_FL 0x00000400 /* Don't compress */
367#define EXT4_ECOMPR_FL 0x00000800 /* Compression error */ 367 /* nb: was previously EXT2_ECOMPR_FL */
368#define EXT4_ENCRYPT_FL 0x00000800 /* encrypted file */
368/* End compression flags --- maybe not all used */ 369/* End compression flags --- maybe not all used */
369#define EXT4_INDEX_FL 0x00001000 /* hash-indexed directory */ 370#define EXT4_INDEX_FL 0x00001000 /* hash-indexed directory */
370#define EXT4_IMAGIC_FL 0x00002000 /* AFS directory */ 371#define EXT4_IMAGIC_FL 0x00002000 /* AFS directory */
@@ -421,7 +422,7 @@ enum {
421 EXT4_INODE_DIRTY = 8, 422 EXT4_INODE_DIRTY = 8,
422 EXT4_INODE_COMPRBLK = 9, /* One or more compressed clusters */ 423 EXT4_INODE_COMPRBLK = 9, /* One or more compressed clusters */
423 EXT4_INODE_NOCOMPR = 10, /* Don't compress */ 424 EXT4_INODE_NOCOMPR = 10, /* Don't compress */
424 EXT4_INODE_ECOMPR = 11, /* Compression error */ 425 EXT4_INODE_ENCRYPT = 11, /* Compression error */
425/* End compression flags --- maybe not all used */ 426/* End compression flags --- maybe not all used */
426 EXT4_INODE_INDEX = 12, /* hash-indexed directory */ 427 EXT4_INODE_INDEX = 12, /* hash-indexed directory */
427 EXT4_INODE_IMAGIC = 13, /* AFS directory */ 428 EXT4_INODE_IMAGIC = 13, /* AFS directory */
@@ -466,7 +467,7 @@ static inline void ext4_check_flag_values(void)
466 CHECK_FLAG_VALUE(DIRTY); 467 CHECK_FLAG_VALUE(DIRTY);
467 CHECK_FLAG_VALUE(COMPRBLK); 468 CHECK_FLAG_VALUE(COMPRBLK);
468 CHECK_FLAG_VALUE(NOCOMPR); 469 CHECK_FLAG_VALUE(NOCOMPR);
469 CHECK_FLAG_VALUE(ECOMPR); 470 CHECK_FLAG_VALUE(ENCRYPT);
470 CHECK_FLAG_VALUE(INDEX); 471 CHECK_FLAG_VALUE(INDEX);
471 CHECK_FLAG_VALUE(IMAGIC); 472 CHECK_FLAG_VALUE(IMAGIC);
472 CHECK_FLAG_VALUE(JOURNAL_DATA); 473 CHECK_FLAG_VALUE(JOURNAL_DATA);
@@ -1048,6 +1049,12 @@ extern void ext4_set_bits(void *bm, int cur, int len);
1048/* Metadata checksum algorithm codes */ 1049/* Metadata checksum algorithm codes */
1049#define EXT4_CRC32C_CHKSUM 1 1050#define EXT4_CRC32C_CHKSUM 1
1050 1051
1052/* Encryption algorithms */
1053#define EXT4_ENCRYPTION_MODE_INVALID 0
1054#define EXT4_ENCRYPTION_MODE_AES_256_XTS 1
1055#define EXT4_ENCRYPTION_MODE_AES_256_GCM 2
1056#define EXT4_ENCRYPTION_MODE_AES_256_CBC 3
1057
1051/* 1058/*
1052 * Structure of the super block 1059 * Structure of the super block
1053 */ 1060 */
@@ -1161,7 +1168,8 @@ struct ext4_super_block {
1161 __le32 s_grp_quota_inum; /* inode for tracking group quota */ 1168 __le32 s_grp_quota_inum; /* inode for tracking group quota */
1162 __le32 s_overhead_clusters; /* overhead blocks/clusters in fs */ 1169 __le32 s_overhead_clusters; /* overhead blocks/clusters in fs */
1163 __le32 s_backup_bgs[2]; /* groups with sparse_super2 SBs */ 1170 __le32 s_backup_bgs[2]; /* groups with sparse_super2 SBs */
1164 __le32 s_reserved[106]; /* Padding to the end of the block */ 1171 __u8 s_encrypt_algos[4]; /* Encryption algorithms in use */
1172 __le32 s_reserved[105]; /* Padding to the end of the block */
1165 __le32 s_checksum; /* crc32c(superblock) */ 1173 __le32 s_checksum; /* crc32c(superblock) */
1166}; 1174};
1167 1175
@@ -1527,6 +1535,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
1527 * GDT_CSUM bits are mutually exclusive. 1535 * GDT_CSUM bits are mutually exclusive.
1528 */ 1536 */
1529#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 1537#define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400
1538#define EXT4_FEATURE_RO_COMPAT_READONLY 0x1000
1530 1539
1531#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001 1540#define EXT4_FEATURE_INCOMPAT_COMPRESSION 0x0001
1532#define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002 1541#define EXT4_FEATURE_INCOMPAT_FILETYPE 0x0002
@@ -1542,6 +1551,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
1542#define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM 0x2000 /* use crc32c for bg */ 1551#define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM 0x2000 /* use crc32c for bg */
1543#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */ 1552#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */
1544#define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */ 1553#define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */
1554#define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000
1545 1555
1546#define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR 1556#define EXT2_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_EXT_ATTR
1547#define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \ 1557#define EXT2_FEATURE_INCOMPAT_SUPP (EXT4_FEATURE_INCOMPAT_FILETYPE| \
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 6b9878a24182..45fe924f82bc 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -1401,10 +1401,7 @@ end_range:
1401 * to free. Everything was covered by the start 1401 * to free. Everything was covered by the start
1402 * of the range. 1402 * of the range.
1403 */ 1403 */
1404 return 0; 1404 goto do_indirects;
1405 } else {
1406 /* Shared branch grows from an indirect block */
1407 partial2--;
1408 } 1405 }
1409 } else { 1406 } else {
1410 /* 1407 /*
@@ -1435,56 +1432,96 @@ end_range:
1435 /* Punch happened within the same level (n == n2) */ 1432 /* Punch happened within the same level (n == n2) */
1436 partial = ext4_find_shared(inode, n, offsets, chain, &nr); 1433 partial = ext4_find_shared(inode, n, offsets, chain, &nr);
1437 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2); 1434 partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
1438 /* 1435
1439 * ext4_find_shared returns Indirect structure which 1436 /* Free top, but only if partial2 isn't its subtree. */
1440 * points to the last element which should not be 1437 if (nr) {
1441 * removed by truncate. But this is end of the range 1438 int level = min(partial - chain, partial2 - chain2);
1442 * in punch_hole so we need to point to the next element 1439 int i;
1443 */ 1440 int subtree = 1;
1444 partial2->p++; 1441
1445 while ((partial > chain) || (partial2 > chain2)) { 1442 for (i = 0; i <= level; i++) {
1446 /* We're at the same block, so we're almost finished */ 1443 if (offsets[i] != offsets2[i]) {
1447 if ((partial->bh && partial2->bh) && 1444 subtree = 0;
1448 (partial->bh->b_blocknr == partial2->bh->b_blocknr)) { 1445 break;
1449 if ((partial > chain) && (partial2 > chain2)) { 1446 }
1447 }
1448
1449 if (!subtree) {
1450 if (partial == chain) {
1451 /* Shared branch grows from the inode */
1452 ext4_free_branches(handle, inode, NULL,
1453 &nr, &nr+1,
1454 (chain+n-1) - partial);
1455 *partial->p = 0;
1456 } else {
1457 /* Shared branch grows from an indirect block */
1458 BUFFER_TRACE(partial->bh, "get_write_access");
1450 ext4_free_branches(handle, inode, partial->bh, 1459 ext4_free_branches(handle, inode, partial->bh,
1451 partial->p + 1, 1460 partial->p,
1452 partial2->p, 1461 partial->p+1,
1453 (chain+n-1) - partial); 1462 (chain+n-1) - partial);
1454 BUFFER_TRACE(partial->bh, "call brelse");
1455 brelse(partial->bh);
1456 BUFFER_TRACE(partial2->bh, "call brelse");
1457 brelse(partial2->bh);
1458 } 1463 }
1459 return 0;
1460 } 1464 }
1465 }
1466
1467 if (!nr2) {
1461 /* 1468 /*
1462 * Clear the ends of indirect blocks on the shared branch 1469 * ext4_find_shared returns Indirect structure which
1463 * at the start of the range 1470 * points to the last element which should not be
1471 * removed by truncate. But this is end of the range
1472 * in punch_hole so we need to point to the next element
1464 */ 1473 */
1465 if (partial > chain) { 1474 partial2->p++;
1475 }
1476
1477 while (partial > chain || partial2 > chain2) {
1478 int depth = (chain+n-1) - partial;
1479 int depth2 = (chain2+n2-1) - partial2;
1480
1481 if (partial > chain && partial2 > chain2 &&
1482 partial->bh->b_blocknr == partial2->bh->b_blocknr) {
1483 /*
1484 * We've converged on the same block. Clear the range,
1485 * then we're done.
1486 */
1466 ext4_free_branches(handle, inode, partial->bh, 1487 ext4_free_branches(handle, inode, partial->bh,
1467 partial->p + 1, 1488 partial->p + 1,
1468 (__le32 *)partial->bh->b_data+addr_per_block, 1489 partial2->p,
1469 (chain+n-1) - partial); 1490 (chain+n-1) - partial);
1470 BUFFER_TRACE(partial->bh, "call brelse"); 1491 BUFFER_TRACE(partial->bh, "call brelse");
1471 brelse(partial->bh); 1492 brelse(partial->bh);
1472 partial--; 1493 BUFFER_TRACE(partial2->bh, "call brelse");
1494 brelse(partial2->bh);
1495 return 0;
1473 } 1496 }
1497
1474 /* 1498 /*
1475 * Clear the ends of indirect blocks on the shared branch 1499 * The start and end partial branches may not be at the same
1476 * at the end of the range 1500 * level even though the punch happened within one level. So, we
1501 * give them a chance to arrive at the same level, then walk
1502 * them in step with each other until we converge on the same
1503 * block.
1477 */ 1504 */
1478 if (partial2 > chain2) { 1505 if (partial > chain && depth <= depth2) {
1506 ext4_free_branches(handle, inode, partial->bh,
1507 partial->p + 1,
1508 (__le32 *)partial->bh->b_data+addr_per_block,
1509 (chain+n-1) - partial);
1510 BUFFER_TRACE(partial->bh, "call brelse");
1511 brelse(partial->bh);
1512 partial--;
1513 }
1514 if (partial2 > chain2 && depth2 <= depth) {
1479 ext4_free_branches(handle, inode, partial2->bh, 1515 ext4_free_branches(handle, inode, partial2->bh,
1480 (__le32 *)partial2->bh->b_data, 1516 (__le32 *)partial2->bh->b_data,
1481 partial2->p, 1517 partial2->p,
1482 (chain2+n-1) - partial2); 1518 (chain2+n2-1) - partial2);
1483 BUFFER_TRACE(partial2->bh, "call brelse"); 1519 BUFFER_TRACE(partial2->bh, "call brelse");
1484 brelse(partial2->bh); 1520 brelse(partial2->bh);
1485 partial2--; 1521 partial2--;
1486 } 1522 }
1487 } 1523 }
1524 return 0;
1488 1525
1489do_indirects: 1526do_indirects:
1490 /* Kill the remaining (whole) subtrees */ 1527 /* Kill the remaining (whole) subtrees */
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 85404f15e53a..5cb9a212b86f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1024,6 +1024,7 @@ static int ext4_write_end(struct file *file,
1024{ 1024{
1025 handle_t *handle = ext4_journal_current_handle(); 1025 handle_t *handle = ext4_journal_current_handle();
1026 struct inode *inode = mapping->host; 1026 struct inode *inode = mapping->host;
1027 loff_t old_size = inode->i_size;
1027 int ret = 0, ret2; 1028 int ret = 0, ret2;
1028 int i_size_changed = 0; 1029 int i_size_changed = 0;
1029 1030
@@ -1054,6 +1055,8 @@ static int ext4_write_end(struct file *file,
1054 unlock_page(page); 1055 unlock_page(page);
1055 page_cache_release(page); 1056 page_cache_release(page);
1056 1057
1058 if (old_size < pos)
1059 pagecache_isize_extended(inode, old_size, pos);
1057 /* 1060 /*
1058 * Don't mark the inode dirty under page lock. First, it unnecessarily 1061 * Don't mark the inode dirty under page lock. First, it unnecessarily
1059 * makes the holding time of page lock longer. Second, it forces lock 1062 * makes the holding time of page lock longer. Second, it forces lock
@@ -1095,6 +1098,7 @@ static int ext4_journalled_write_end(struct file *file,
1095{ 1098{
1096 handle_t *handle = ext4_journal_current_handle(); 1099 handle_t *handle = ext4_journal_current_handle();
1097 struct inode *inode = mapping->host; 1100 struct inode *inode = mapping->host;
1101 loff_t old_size = inode->i_size;
1098 int ret = 0, ret2; 1102 int ret = 0, ret2;
1099 int partial = 0; 1103 int partial = 0;
1100 unsigned from, to; 1104 unsigned from, to;
@@ -1127,6 +1131,9 @@ static int ext4_journalled_write_end(struct file *file,
1127 unlock_page(page); 1131 unlock_page(page);
1128 page_cache_release(page); 1132 page_cache_release(page);
1129 1133
1134 if (old_size < pos)
1135 pagecache_isize_extended(inode, old_size, pos);
1136
1130 if (size_changed) { 1137 if (size_changed) {
1131 ret2 = ext4_mark_inode_dirty(handle, inode); 1138 ret2 = ext4_mark_inode_dirty(handle, inode);
1132 if (!ret) 1139 if (!ret)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 1adac6868e6f..e061e66c8280 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2779,6 +2779,12 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
2779 if (readonly) 2779 if (readonly)
2780 return 1; 2780 return 1;
2781 2781
2782 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_READONLY)) {
2783 ext4_msg(sb, KERN_INFO, "filesystem is read-only");
2784 sb->s_flags |= MS_RDONLY;
2785 return 1;
2786 }
2787
2782 /* Check that feature set is OK for a read-write mount */ 2788 /* Check that feature set is OK for a read-write mount */
2783 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP)) { 2789 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP)) {
2784 ext4_msg(sb, KERN_ERR, "couldn't mount RDWR because of " 2790 ext4_msg(sb, KERN_ERR, "couldn't mount RDWR because of "
@@ -3936,9 +3942,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3936 get_random_bytes(&sbi->s_next_generation, sizeof(u32)); 3942 get_random_bytes(&sbi->s_next_generation, sizeof(u32));
3937 spin_lock_init(&sbi->s_next_gen_lock); 3943 spin_lock_init(&sbi->s_next_gen_lock);
3938 3944
3939 init_timer(&sbi->s_err_report); 3945 setup_timer(&sbi->s_err_report, print_daily_error_info,
3940 sbi->s_err_report.function = print_daily_error_info; 3946 (unsigned long) sb);
3941 sbi->s_err_report.data = (unsigned long) sb;
3942 3947
3943 /* Register extent status tree shrinker */ 3948 /* Register extent status tree shrinker */
3944 if (ext4_es_register_shrinker(sbi)) 3949 if (ext4_es_register_shrinker(sbi))
@@ -4866,9 +4871,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
4866 if (sbi->s_journal && sbi->s_journal->j_task->io_context) 4871 if (sbi->s_journal && sbi->s_journal->j_task->io_context)
4867 journal_ioprio = sbi->s_journal->j_task->io_context->ioprio; 4872 journal_ioprio = sbi->s_journal->j_task->io_context->ioprio;
4868 4873
4869 /*
4870 * Allow the "check" option to be passed as a remount option.
4871 */
4872 if (!parse_options(data, sb, NULL, &journal_ioprio, 1)) { 4874 if (!parse_options(data, sb, NULL, &journal_ioprio, 1)) {
4873 err = -EINVAL; 4875 err = -EINVAL;
4874 goto restore_opts; 4876 goto restore_opts;
@@ -4877,17 +4879,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
4877 if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^ 4879 if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
4878 test_opt(sb, JOURNAL_CHECKSUM)) { 4880 test_opt(sb, JOURNAL_CHECKSUM)) {
4879 ext4_msg(sb, KERN_ERR, "changing journal_checksum " 4881 ext4_msg(sb, KERN_ERR, "changing journal_checksum "
4880 "during remount not supported"); 4882 "during remount not supported; ignoring");
4881 err = -EINVAL; 4883 sbi->s_mount_opt ^= EXT4_MOUNT_JOURNAL_CHECKSUM;
4882 goto restore_opts;
4883 }
4884
4885 if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
4886 test_opt(sb, JOURNAL_CHECKSUM)) {
4887 ext4_msg(sb, KERN_ERR, "changing journal_checksum "
4888 "during remount not supported");
4889 err = -EINVAL;
4890 goto restore_opts;
4891 } 4884 }
4892 4885
4893 if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) { 4886 if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
@@ -4963,7 +4956,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
4963 ext4_mark_recovery_complete(sb, es); 4956 ext4_mark_recovery_complete(sb, es);
4964 } else { 4957 } else {
4965 /* Make sure we can mount this feature set readwrite */ 4958 /* Make sure we can mount this feature set readwrite */
4966 if (!ext4_feature_set_ok(sb, 0)) { 4959 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
4960 EXT4_FEATURE_RO_COMPAT_READONLY) ||
4961 !ext4_feature_set_ok(sb, 0)) {
4967 err = -EROFS; 4962 err = -EROFS;
4968 goto restore_opts; 4963 goto restore_opts;
4969 } 4964 }
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index bcbef08a4d8f..b5128c6e63ad 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -524,6 +524,9 @@ static int do_one_pass(journal_t *journal,
524 if (descr_csum_size > 0 && 524 if (descr_csum_size > 0 &&
525 !jbd2_descr_block_csum_verify(journal, 525 !jbd2_descr_block_csum_verify(journal,
526 bh->b_data)) { 526 bh->b_data)) {
527 printk(KERN_ERR "JBD2: Invalid checksum "
528 "recovering block %lu in log\n",
529 next_log_block);
527 err = -EIO; 530 err = -EIO;
528 brelse(bh); 531 brelse(bh);
529 goto failed; 532 goto failed;