Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 fixes from Ted Ts'o:
"Ext4 bug fixes.

We also reserved code points for encryption and read-only images (for
which the implementation is mostly just the reserved code point for a
read-only feature :-)"

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: fix indirect punch hole corruption
ext4: ignore journal checksum on remount; don't fail
ext4: remove duplicate remount check for JOURNAL_CHECKSUM change
ext4: fix mmap data corruption in nodelalloc mode when blocksize < pagesize
ext4: support read-only images
ext4: change to use setup_timer() instead of init_timer()
ext4: reserve codepoints used by the ext4 encryption feature
jbd2: complain about descriptor block checksum errors

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