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

f2fs: compress: support chksum

This patch supports to store chksum value with compressed
data, and verify the integrality of compressed data while
reading the data.

The feature can be enabled through specifying mount option
'compress_chksum'.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Chao Yu and committed by
Jaegeuk Kim
b28f047b 493720a4

+51 -3
+1
Documentation/filesystems/f2fs.rst
··· 260 260 For other files, we can still enable compression via ioctl. 261 261 Note that, there is one reserved special extension '*', it 262 262 can be set to enable compression for all files. 263 + compress_chksum Support verifying chksum of raw data in compressed cluster. 263 264 inlinecrypt When possible, encrypt/decrypt the contents of encrypted 264 265 files using the blk-crypto framework rather than 265 266 filesystem-layer encryption. This allows the use of
+23
fs/f2fs/compress.c
··· 602 602 f2fs_cops[fi->i_compress_algorithm]; 603 603 unsigned int max_len, new_nr_cpages; 604 604 struct page **new_cpages; 605 + u32 chksum = 0; 605 606 int i, ret; 606 607 607 608 trace_f2fs_compress_pages_start(cc->inode, cc->cluster_idx, ··· 655 654 } 656 655 657 656 cc->cbuf->clen = cpu_to_le32(cc->clen); 657 + 658 + if (fi->i_compress_flag & 1 << COMPRESS_CHKSUM) 659 + chksum = f2fs_crc32(F2FS_I_SB(cc->inode), 660 + cc->cbuf->cdata, cc->clen); 661 + cc->cbuf->chksum = cpu_to_le32(chksum); 658 662 659 663 for (i = 0; i < COMPRESS_DATA_RESERVED_SIZE; i++) 660 664 cc->cbuf->reserved[i] = cpu_to_le32(0); ··· 795 789 } 796 790 797 791 ret = cops->decompress_pages(dic); 792 + 793 + if (!ret && fi->i_compress_flag & 1 << COMPRESS_CHKSUM) { 794 + u32 provided = le32_to_cpu(dic->cbuf->chksum); 795 + u32 calculated = f2fs_crc32(sbi, dic->cbuf->cdata, dic->clen); 796 + 797 + if (provided != calculated) { 798 + if (!is_inode_flag_set(dic->inode, FI_COMPRESS_CORRUPT)) { 799 + set_inode_flag(dic->inode, FI_COMPRESS_CORRUPT); 800 + printk_ratelimited( 801 + "%sF2FS-fs (%s): checksum invalid, nid = %lu, %x vs %x", 802 + KERN_INFO, sbi->sb->s_id, dic->inode->i_ino, 803 + provided, calculated); 804 + } 805 + set_sbi_flag(sbi, SBI_NEED_FSCK); 806 + WARN_ON_ONCE(1); 807 + } 808 + } 798 809 799 810 out_vunmap_cbuf: 800 811 vm_unmap_ram(dic->cbuf, dic->nr_cpages);
+14 -2
fs/f2fs/f2fs.h
··· 147 147 148 148 /* For compression */ 149 149 unsigned char compress_algorithm; /* algorithm type */ 150 - unsigned compress_log_size; /* cluster log size */ 150 + unsigned char compress_log_size; /* cluster log size */ 151 + bool compress_chksum; /* compressed data chksum */ 151 152 unsigned char compress_ext_cnt; /* extension count */ 152 153 unsigned char extensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */ 153 154 }; ··· 677 676 FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */ 678 677 FI_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */ 679 678 FI_COMPRESSED_FILE, /* indicate file's data can be compressed */ 679 + FI_COMPRESS_CORRUPT, /* indicate compressed cluster is corrupted */ 680 680 FI_MMAP_FILE, /* indicate file was mmapped */ 681 681 FI_MAX, /* max flag, never be used */ 682 682 }; ··· 735 733 atomic_t i_compr_blocks; /* # of compressed blocks */ 736 734 unsigned char i_compress_algorithm; /* algorithm type */ 737 735 unsigned char i_log_cluster_size; /* log of cluster size */ 736 + unsigned short i_compress_flag; /* compress flag */ 738 737 unsigned int i_cluster_size; /* cluster size */ 739 738 }; 740 739 ··· 1275 1272 COMPRESS_MAX, 1276 1273 }; 1277 1274 1278 - #define COMPRESS_DATA_RESERVED_SIZE 5 1275 + enum compress_flag { 1276 + COMPRESS_CHKSUM, 1277 + COMPRESS_MAX_FLAG, 1278 + }; 1279 + 1280 + #define COMPRESS_DATA_RESERVED_SIZE 4 1279 1281 struct compress_data { 1280 1282 __le32 clen; /* compressed data size */ 1283 + __le32 chksum; /* compressed data chksum */ 1281 1284 __le32 reserved[COMPRESS_DATA_RESERVED_SIZE]; /* reserved */ 1282 1285 u8 cdata[]; /* compressed data */ 1283 1286 }; ··· 3897 3888 F2FS_OPTION(sbi).compress_algorithm; 3898 3889 F2FS_I(inode)->i_log_cluster_size = 3899 3890 F2FS_OPTION(sbi).compress_log_size; 3891 + F2FS_I(inode)->i_compress_flag = 3892 + F2FS_OPTION(sbi).compress_chksum ? 3893 + 1 << COMPRESS_CHKSUM : 0; 3900 3894 F2FS_I(inode)->i_cluster_size = 3901 3895 1 << F2FS_I(inode)->i_log_cluster_size; 3902 3896 F2FS_I(inode)->i_flags |= F2FS_COMPR_FL;
+3
fs/f2fs/inode.c
··· 456 456 le64_to_cpu(ri->i_compr_blocks)); 457 457 fi->i_compress_algorithm = ri->i_compress_algorithm; 458 458 fi->i_log_cluster_size = ri->i_log_cluster_size; 459 + fi->i_compress_flag = le16_to_cpu(ri->i_compress_flag); 459 460 fi->i_cluster_size = 1 << fi->i_log_cluster_size; 460 461 set_inode_flag(inode, FI_COMPRESSED_FILE); 461 462 } ··· 635 634 &F2FS_I(inode)->i_compr_blocks)); 636 635 ri->i_compress_algorithm = 637 636 F2FS_I(inode)->i_compress_algorithm; 637 + ri->i_compress_flag = 638 + cpu_to_le16(F2FS_I(inode)->i_compress_flag); 638 639 ri->i_log_cluster_size = 639 640 F2FS_I(inode)->i_log_cluster_size; 640 641 }
+9
fs/f2fs/super.c
··· 146 146 Opt_compress_algorithm, 147 147 Opt_compress_log_size, 148 148 Opt_compress_extension, 149 + Opt_compress_chksum, 149 150 Opt_atgc, 150 151 Opt_err, 151 152 }; ··· 215 214 {Opt_compress_algorithm, "compress_algorithm=%s"}, 216 215 {Opt_compress_log_size, "compress_log_size=%u"}, 217 216 {Opt_compress_extension, "compress_extension=%s"}, 217 + {Opt_compress_chksum, "compress_chksum"}, 218 218 {Opt_atgc, "atgc"}, 219 219 {Opt_err, NULL}, 220 220 }; ··· 936 934 F2FS_OPTION(sbi).compress_ext_cnt++; 937 935 kfree(name); 938 936 break; 937 + case Opt_compress_chksum: 938 + F2FS_OPTION(sbi).compress_chksum = true; 939 + break; 939 940 #else 940 941 case Opt_compress_algorithm: 941 942 case Opt_compress_log_size: 942 943 case Opt_compress_extension: 944 + case Opt_compress_chksum: 943 945 f2fs_info(sbi, "compression options not supported"); 944 946 break; 945 947 #endif ··· 1529 1523 seq_printf(seq, ",compress_extension=%s", 1530 1524 F2FS_OPTION(sbi).extensions[i]); 1531 1525 } 1526 + 1527 + if (F2FS_OPTION(sbi).compress_chksum) 1528 + seq_puts(seq, ",compress_chksum"); 1532 1529 } 1533 1530 1534 1531 static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
+1 -1
include/linux/f2fs_fs.h
··· 273 273 __le64 i_compr_blocks; /* # of compressed blocks */ 274 274 __u8 i_compress_algorithm; /* compress algorithm */ 275 275 __u8 i_log_cluster_size; /* log of cluster size */ 276 - __le16 i_padding; /* padding */ 276 + __le16 i_compress_flag; /* compress flag */ 277 277 __le32 i_extra_end[0]; /* for attribute size calculation */ 278 278 } __packed; 279 279 __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */