aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChao Yu2020-11-26 04:32:09 -0600
committerJaegeuk Kim2020-12-21 15:33:14 -0600
commit1f004d62f8511630201b3f20f46e3d8864f877c6 (patch)
treed2e834f060fb6390dd398bfc74ee9eb8d6646218
parent34315f887206f21d03674d7e8dcbf50053154689 (diff)
downloadkernel-1f004d62f8511630201b3f20f46e3d8864f877c6.tar.gz
kernel-1f004d62f8511630201b3f20f46e3d8864f877c6.tar.xz
kernel-1f004d62f8511630201b3f20f46e3d8864f877c6.zip
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>
-rw-r--r--Documentation/filesystems/f2fs.rst1
-rw-r--r--fs/f2fs/compress.c23
-rw-r--r--fs/f2fs/f2fs.h16
-rw-r--r--fs/f2fs/inode.c3
-rw-r--r--fs/f2fs/super.c9
-rw-r--r--include/linux/f2fs_fs.h2
6 files changed, 51 insertions, 3 deletions
diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index b8ee761c9922..985ae7d35066 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -260,6 +260,7 @@ compress_extension=%s Support adding specified extension, so that f2fs can enab
260 For other files, we can still enable compression via ioctl. 260 For other files, we can still enable compression via ioctl.
261 Note that, there is one reserved special extension '*', it 261 Note that, there is one reserved special extension '*', it
262 can be set to enable compression for all files. 262 can be set to enable compression for all files.
263compress_chksum Support verifying chksum of raw data in compressed cluster.
263inlinecrypt When possible, encrypt/decrypt the contents of encrypted 264inlinecrypt When possible, encrypt/decrypt the contents of encrypted
264 files using the blk-crypto framework rather than 265 files using the blk-crypto framework rather than
265 filesystem-layer encryption. This allows the use of 266 filesystem-layer encryption. This allows the use of
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 14262e0f1cd6..7ec1592a0973 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -602,6 +602,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
602 f2fs_cops[fi->i_compress_algorithm]; 602 f2fs_cops[fi->i_compress_algorithm];
603 unsigned int max_len, new_nr_cpages; 603 unsigned int max_len, new_nr_cpages;
604 struct page **new_cpages; 604 struct page **new_cpages;
605 u32 chksum = 0;
605 int i, ret; 606 int i, ret;
606 607
607 trace_f2fs_compress_pages_start(cc->inode, cc->cluster_idx, 608 trace_f2fs_compress_pages_start(cc->inode, cc->cluster_idx,
@@ -655,6 +656,11 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
655 656
656 cc->cbuf->clen = cpu_to_le32(cc->clen); 657 cc->cbuf->clen = cpu_to_le32(cc->clen);
657 658
659 if (fi->i_compress_flag & 1 << COMPRESS_CHKSUM)
660 chksum = f2fs_crc32(F2FS_I_SB(cc->inode),
661 cc->cbuf->cdata, cc->clen);
662 cc->cbuf->chksum = cpu_to_le32(chksum);
663
658 for (i = 0; i < COMPRESS_DATA_RESERVED_SIZE; i++) 664 for (i = 0; i < COMPRESS_DATA_RESERVED_SIZE; i++)
659 cc->cbuf->reserved[i] = cpu_to_le32(0); 665 cc->cbuf->reserved[i] = cpu_to_le32(0);
660 666
@@ -790,6 +796,23 @@ void f2fs_decompress_pages(struct bio *bio, struct page *page, bool verity)
790 796
791 ret = cops->decompress_pages(dic); 797 ret = cops->decompress_pages(dic);
792 798
799 if (!ret && fi->i_compress_flag & 1 << COMPRESS_CHKSUM) {
800 u32 provided = le32_to_cpu(dic->cbuf->chksum);
801 u32 calculated = f2fs_crc32(sbi, dic->cbuf->cdata, dic->clen);
802
803 if (provided != calculated) {
804 if (!is_inode_flag_set(dic->inode, FI_COMPRESS_CORRUPT)) {
805 set_inode_flag(dic->inode, FI_COMPRESS_CORRUPT);
806 printk_ratelimited(
807 "%sF2FS-fs (%s): checksum invalid, nid = %lu, %x vs %x",
808 KERN_INFO, sbi->sb->s_id, dic->inode->i_ino,
809 provided, calculated);
810 }
811 set_sbi_flag(sbi, SBI_NEED_FSCK);
812 WARN_ON_ONCE(1);
813 }
814 }
815
793out_vunmap_cbuf: 816out_vunmap_cbuf:
794 vm_unmap_ram(dic->cbuf, dic->nr_cpages); 817 vm_unmap_ram(dic->cbuf, dic->nr_cpages);
795out_vunmap_rbuf: 818out_vunmap_rbuf:
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 0d25f5ca5618..0b314b2034d8 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -147,7 +147,8 @@ struct f2fs_mount_info {
147 147
148 /* For compression */ 148 /* For compression */
149 unsigned char compress_algorithm; /* algorithm type */ 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 unsigned char compress_ext_cnt; /* extension count */ 152 unsigned char compress_ext_cnt; /* extension count */
152 unsigned char extensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */ 153 unsigned char extensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */
153}; 154};
@@ -676,6 +677,7 @@ enum {
676 FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */ 677 FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */
677 FI_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */ 678 FI_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */
678 FI_COMPRESSED_FILE, /* indicate file's data can be compressed */ 679 FI_COMPRESSED_FILE, /* indicate file's data can be compressed */
680 FI_COMPRESS_CORRUPT, /* indicate compressed cluster is corrupted */
679 FI_MMAP_FILE, /* indicate file was mmapped */ 681 FI_MMAP_FILE, /* indicate file was mmapped */
680 FI_MAX, /* max flag, never be used */ 682 FI_MAX, /* max flag, never be used */
681}; 683};
@@ -733,6 +735,7 @@ struct f2fs_inode_info {
733 atomic_t i_compr_blocks; /* # of compressed blocks */ 735 atomic_t i_compr_blocks; /* # of compressed blocks */
734 unsigned char i_compress_algorithm; /* algorithm type */ 736 unsigned char i_compress_algorithm; /* algorithm type */
735 unsigned char i_log_cluster_size; /* log of cluster size */ 737 unsigned char i_log_cluster_size; /* log of cluster size */
738 unsigned short i_compress_flag; /* compress flag */
736 unsigned int i_cluster_size; /* cluster size */ 739 unsigned int i_cluster_size; /* cluster size */
737}; 740};
738 741
@@ -1272,9 +1275,15 @@ enum compress_algorithm_type {
1272 COMPRESS_MAX, 1275 COMPRESS_MAX,
1273}; 1276};
1274 1277
1275#define COMPRESS_DATA_RESERVED_SIZE 5 1278enum compress_flag {
1279 COMPRESS_CHKSUM,
1280 COMPRESS_MAX_FLAG,
1281};
1282
1283#define COMPRESS_DATA_RESERVED_SIZE 4
1276struct compress_data { 1284struct compress_data {
1277 __le32 clen; /* compressed data size */ 1285 __le32 clen; /* compressed data size */
1286 __le32 chksum; /* compressed data chksum */
1278 __le32 reserved[COMPRESS_DATA_RESERVED_SIZE]; /* reserved */ 1287 __le32 reserved[COMPRESS_DATA_RESERVED_SIZE]; /* reserved */
1279 u8 cdata[]; /* compressed data */ 1288 u8 cdata[]; /* compressed data */
1280}; 1289};
@@ -3888,6 +3897,9 @@ static inline void set_compress_context(struct inode *inode)
3888 F2FS_OPTION(sbi).compress_algorithm; 3897 F2FS_OPTION(sbi).compress_algorithm;
3889 F2FS_I(inode)->i_log_cluster_size = 3898 F2FS_I(inode)->i_log_cluster_size =
3890 F2FS_OPTION(sbi).compress_log_size; 3899 F2FS_OPTION(sbi).compress_log_size;
3900 F2FS_I(inode)->i_compress_flag =
3901 F2FS_OPTION(sbi).compress_chksum ?
3902 1 << COMPRESS_CHKSUM : 0;
3891 F2FS_I(inode)->i_cluster_size = 3903 F2FS_I(inode)->i_cluster_size =
3892 1 << F2FS_I(inode)->i_log_cluster_size; 3904 1 << F2FS_I(inode)->i_log_cluster_size;
3893 F2FS_I(inode)->i_flags |= F2FS_COMPR_FL; 3905 F2FS_I(inode)->i_flags |= F2FS_COMPR_FL;
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 657db2fb6739..349d9cb933ee 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -456,6 +456,7 @@ static int do_read_inode(struct inode *inode)
456 le64_to_cpu(ri->i_compr_blocks)); 456 le64_to_cpu(ri->i_compr_blocks));
457 fi->i_compress_algorithm = ri->i_compress_algorithm; 457 fi->i_compress_algorithm = ri->i_compress_algorithm;
458 fi->i_log_cluster_size = ri->i_log_cluster_size; 458 fi->i_log_cluster_size = ri->i_log_cluster_size;
459 fi->i_compress_flag = le16_to_cpu(ri->i_compress_flag);
459 fi->i_cluster_size = 1 << fi->i_log_cluster_size; 460 fi->i_cluster_size = 1 << fi->i_log_cluster_size;
460 set_inode_flag(inode, FI_COMPRESSED_FILE); 461 set_inode_flag(inode, FI_COMPRESSED_FILE);
461 } 462 }
@@ -634,6 +635,8 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page)
634 &F2FS_I(inode)->i_compr_blocks)); 635 &F2FS_I(inode)->i_compr_blocks));
635 ri->i_compress_algorithm = 636 ri->i_compress_algorithm =
636 F2FS_I(inode)->i_compress_algorithm; 637 F2FS_I(inode)->i_compress_algorithm;
638 ri->i_compress_flag =
639 cpu_to_le16(F2FS_I(inode)->i_compress_flag);
637 ri->i_log_cluster_size = 640 ri->i_log_cluster_size =
638 F2FS_I(inode)->i_log_cluster_size; 641 F2FS_I(inode)->i_log_cluster_size;
639 } 642 }
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 82baaa89c893..f3d919ee4dee 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -146,6 +146,7 @@ enum {
146 Opt_compress_algorithm, 146 Opt_compress_algorithm,
147 Opt_compress_log_size, 147 Opt_compress_log_size,
148 Opt_compress_extension, 148 Opt_compress_extension,
149 Opt_compress_chksum,
149 Opt_atgc, 150 Opt_atgc,
150 Opt_err, 151 Opt_err,
151}; 152};
@@ -214,6 +215,7 @@ static match_table_t f2fs_tokens = {
214 {Opt_compress_algorithm, "compress_algorithm=%s"}, 215 {Opt_compress_algorithm, "compress_algorithm=%s"},
215 {Opt_compress_log_size, "compress_log_size=%u"}, 216 {Opt_compress_log_size, "compress_log_size=%u"},
216 {Opt_compress_extension, "compress_extension=%s"}, 217 {Opt_compress_extension, "compress_extension=%s"},
218 {Opt_compress_chksum, "compress_chksum"},
217 {Opt_atgc, "atgc"}, 219 {Opt_atgc, "atgc"},
218 {Opt_err, NULL}, 220 {Opt_err, NULL},
219}; 221};
@@ -934,10 +936,14 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
934 F2FS_OPTION(sbi).compress_ext_cnt++; 936 F2FS_OPTION(sbi).compress_ext_cnt++;
935 kfree(name); 937 kfree(name);
936 break; 938 break;
939 case Opt_compress_chksum:
940 F2FS_OPTION(sbi).compress_chksum = true;
941 break;
937#else 942#else
938 case Opt_compress_algorithm: 943 case Opt_compress_algorithm:
939 case Opt_compress_log_size: 944 case Opt_compress_log_size:
940 case Opt_compress_extension: 945 case Opt_compress_extension:
946 case Opt_compress_chksum:
941 f2fs_info(sbi, "compression options not supported"); 947 f2fs_info(sbi, "compression options not supported");
942 break; 948 break;
943#endif 949#endif
@@ -1523,6 +1529,9 @@ static inline void f2fs_show_compress_options(struct seq_file *seq,
1523 seq_printf(seq, ",compress_extension=%s", 1529 seq_printf(seq, ",compress_extension=%s",
1524 F2FS_OPTION(sbi).extensions[i]); 1530 F2FS_OPTION(sbi).extensions[i]);
1525 } 1531 }
1532
1533 if (F2FS_OPTION(sbi).compress_chksum)
1534 seq_puts(seq, ",compress_chksum");
1526} 1535}
1527 1536
1528static int f2fs_show_options(struct seq_file *seq, struct dentry *root) 1537static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index a5dbb57a687f..7dc2a06cf19a 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -273,7 +273,7 @@ struct f2fs_inode {
273 __le64 i_compr_blocks; /* # of compressed blocks */ 273 __le64 i_compr_blocks; /* # of compressed blocks */
274 __u8 i_compress_algorithm; /* compress algorithm */ 274 __u8 i_compress_algorithm; /* compress algorithm */
275 __u8 i_log_cluster_size; /* log of cluster size */ 275 __u8 i_log_cluster_size; /* log of cluster size */
276 __le16 i_padding; /* padding */ 276 __le16 i_compress_flag; /* compress flag */
277 __le32 i_extra_end[0]; /* for attribute size calculation */ 277 __le32 i_extra_end[0]; /* for attribute size calculation */
278 } __packed; 278 } __packed;
279 __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ 279 __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */