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>
This commit is contained in:
Родитель
493720a485
Коммит
b28f047b28
|
@ -260,6 +260,7 @@ compress_extension=%s Support adding specified extension, so that f2fs can enab
|
||||||
For other files, we can still enable compression via ioctl.
|
For other files, we can still enable compression via ioctl.
|
||||||
Note that, there is one reserved special extension '*', it
|
Note that, there is one reserved special extension '*', it
|
||||||
can be set to enable compression for all files.
|
can be set to enable compression for all files.
|
||||||
|
compress_chksum Support verifying chksum of raw data in compressed cluster.
|
||||||
inlinecrypt When possible, encrypt/decrypt the contents of encrypted
|
inlinecrypt When possible, encrypt/decrypt the contents of encrypted
|
||||||
files using the blk-crypto framework rather than
|
files using the blk-crypto framework rather than
|
||||||
filesystem-layer encryption. This allows the use of
|
filesystem-layer encryption. This allows the use of
|
||||||
|
|
|
@ -602,6 +602,7 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
|
||||||
f2fs_cops[fi->i_compress_algorithm];
|
f2fs_cops[fi->i_compress_algorithm];
|
||||||
unsigned int max_len, new_nr_cpages;
|
unsigned int max_len, new_nr_cpages;
|
||||||
struct page **new_cpages;
|
struct page **new_cpages;
|
||||||
|
u32 chksum = 0;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
trace_f2fs_compress_pages_start(cc->inode, cc->cluster_idx,
|
trace_f2fs_compress_pages_start(cc->inode, cc->cluster_idx,
|
||||||
|
@ -655,6 +656,11 @@ static int f2fs_compress_pages(struct compress_ctx *cc)
|
||||||
|
|
||||||
cc->cbuf->clen = cpu_to_le32(cc->clen);
|
cc->cbuf->clen = cpu_to_le32(cc->clen);
|
||||||
|
|
||||||
|
if (fi->i_compress_flag & 1 << COMPRESS_CHKSUM)
|
||||||
|
chksum = f2fs_crc32(F2FS_I_SB(cc->inode),
|
||||||
|
cc->cbuf->cdata, cc->clen);
|
||||||
|
cc->cbuf->chksum = cpu_to_le32(chksum);
|
||||||
|
|
||||||
for (i = 0; i < COMPRESS_DATA_RESERVED_SIZE; i++)
|
for (i = 0; i < COMPRESS_DATA_RESERVED_SIZE; i++)
|
||||||
cc->cbuf->reserved[i] = cpu_to_le32(0);
|
cc->cbuf->reserved[i] = cpu_to_le32(0);
|
||||||
|
|
||||||
|
@ -790,6 +796,23 @@ void f2fs_decompress_pages(struct bio *bio, struct page *page, bool verity)
|
||||||
|
|
||||||
ret = cops->decompress_pages(dic);
|
ret = cops->decompress_pages(dic);
|
||||||
|
|
||||||
|
if (!ret && fi->i_compress_flag & 1 << COMPRESS_CHKSUM) {
|
||||||
|
u32 provided = le32_to_cpu(dic->cbuf->chksum);
|
||||||
|
u32 calculated = f2fs_crc32(sbi, dic->cbuf->cdata, dic->clen);
|
||||||
|
|
||||||
|
if (provided != calculated) {
|
||||||
|
if (!is_inode_flag_set(dic->inode, FI_COMPRESS_CORRUPT)) {
|
||||||
|
set_inode_flag(dic->inode, FI_COMPRESS_CORRUPT);
|
||||||
|
printk_ratelimited(
|
||||||
|
"%sF2FS-fs (%s): checksum invalid, nid = %lu, %x vs %x",
|
||||||
|
KERN_INFO, sbi->sb->s_id, dic->inode->i_ino,
|
||||||
|
provided, calculated);
|
||||||
|
}
|
||||||
|
set_sbi_flag(sbi, SBI_NEED_FSCK);
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out_vunmap_cbuf:
|
out_vunmap_cbuf:
|
||||||
vm_unmap_ram(dic->cbuf, dic->nr_cpages);
|
vm_unmap_ram(dic->cbuf, dic->nr_cpages);
|
||||||
out_vunmap_rbuf:
|
out_vunmap_rbuf:
|
||||||
|
|
|
@ -147,7 +147,8 @@ struct f2fs_mount_info {
|
||||||
|
|
||||||
/* For compression */
|
/* For compression */
|
||||||
unsigned char compress_algorithm; /* algorithm type */
|
unsigned char compress_algorithm; /* algorithm type */
|
||||||
unsigned compress_log_size; /* cluster log size */
|
unsigned char compress_log_size; /* cluster log size */
|
||||||
|
bool compress_chksum; /* compressed data chksum */
|
||||||
unsigned char compress_ext_cnt; /* extension count */
|
unsigned char compress_ext_cnt; /* extension count */
|
||||||
unsigned char extensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */
|
unsigned char extensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */
|
||||||
};
|
};
|
||||||
|
@ -676,6 +677,7 @@ enum {
|
||||||
FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */
|
FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */
|
||||||
FI_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */
|
FI_VERITY_IN_PROGRESS, /* building fs-verity Merkle tree */
|
||||||
FI_COMPRESSED_FILE, /* indicate file's data can be compressed */
|
FI_COMPRESSED_FILE, /* indicate file's data can be compressed */
|
||||||
|
FI_COMPRESS_CORRUPT, /* indicate compressed cluster is corrupted */
|
||||||
FI_MMAP_FILE, /* indicate file was mmapped */
|
FI_MMAP_FILE, /* indicate file was mmapped */
|
||||||
FI_MAX, /* max flag, never be used */
|
FI_MAX, /* max flag, never be used */
|
||||||
};
|
};
|
||||||
|
@ -733,6 +735,7 @@ struct f2fs_inode_info {
|
||||||
atomic_t i_compr_blocks; /* # of compressed blocks */
|
atomic_t i_compr_blocks; /* # of compressed blocks */
|
||||||
unsigned char i_compress_algorithm; /* algorithm type */
|
unsigned char i_compress_algorithm; /* algorithm type */
|
||||||
unsigned char i_log_cluster_size; /* log of cluster size */
|
unsigned char i_log_cluster_size; /* log of cluster size */
|
||||||
|
unsigned short i_compress_flag; /* compress flag */
|
||||||
unsigned int i_cluster_size; /* cluster size */
|
unsigned int i_cluster_size; /* cluster size */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1272,9 +1275,15 @@ enum compress_algorithm_type {
|
||||||
COMPRESS_MAX,
|
COMPRESS_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define COMPRESS_DATA_RESERVED_SIZE 5
|
enum compress_flag {
|
||||||
|
COMPRESS_CHKSUM,
|
||||||
|
COMPRESS_MAX_FLAG,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define COMPRESS_DATA_RESERVED_SIZE 4
|
||||||
struct compress_data {
|
struct compress_data {
|
||||||
__le32 clen; /* compressed data size */
|
__le32 clen; /* compressed data size */
|
||||||
|
__le32 chksum; /* compressed data chksum */
|
||||||
__le32 reserved[COMPRESS_DATA_RESERVED_SIZE]; /* reserved */
|
__le32 reserved[COMPRESS_DATA_RESERVED_SIZE]; /* reserved */
|
||||||
u8 cdata[]; /* compressed data */
|
u8 cdata[]; /* compressed data */
|
||||||
};
|
};
|
||||||
|
@ -3888,6 +3897,9 @@ static inline void set_compress_context(struct inode *inode)
|
||||||
F2FS_OPTION(sbi).compress_algorithm;
|
F2FS_OPTION(sbi).compress_algorithm;
|
||||||
F2FS_I(inode)->i_log_cluster_size =
|
F2FS_I(inode)->i_log_cluster_size =
|
||||||
F2FS_OPTION(sbi).compress_log_size;
|
F2FS_OPTION(sbi).compress_log_size;
|
||||||
|
F2FS_I(inode)->i_compress_flag =
|
||||||
|
F2FS_OPTION(sbi).compress_chksum ?
|
||||||
|
1 << COMPRESS_CHKSUM : 0;
|
||||||
F2FS_I(inode)->i_cluster_size =
|
F2FS_I(inode)->i_cluster_size =
|
||||||
1 << F2FS_I(inode)->i_log_cluster_size;
|
1 << F2FS_I(inode)->i_log_cluster_size;
|
||||||
F2FS_I(inode)->i_flags |= F2FS_COMPR_FL;
|
F2FS_I(inode)->i_flags |= F2FS_COMPR_FL;
|
||||||
|
|
|
@ -456,6 +456,7 @@ static int do_read_inode(struct inode *inode)
|
||||||
le64_to_cpu(ri->i_compr_blocks));
|
le64_to_cpu(ri->i_compr_blocks));
|
||||||
fi->i_compress_algorithm = ri->i_compress_algorithm;
|
fi->i_compress_algorithm = ri->i_compress_algorithm;
|
||||||
fi->i_log_cluster_size = ri->i_log_cluster_size;
|
fi->i_log_cluster_size = ri->i_log_cluster_size;
|
||||||
|
fi->i_compress_flag = le16_to_cpu(ri->i_compress_flag);
|
||||||
fi->i_cluster_size = 1 << fi->i_log_cluster_size;
|
fi->i_cluster_size = 1 << fi->i_log_cluster_size;
|
||||||
set_inode_flag(inode, FI_COMPRESSED_FILE);
|
set_inode_flag(inode, FI_COMPRESSED_FILE);
|
||||||
}
|
}
|
||||||
|
@ -634,6 +635,8 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page)
|
||||||
&F2FS_I(inode)->i_compr_blocks));
|
&F2FS_I(inode)->i_compr_blocks));
|
||||||
ri->i_compress_algorithm =
|
ri->i_compress_algorithm =
|
||||||
F2FS_I(inode)->i_compress_algorithm;
|
F2FS_I(inode)->i_compress_algorithm;
|
||||||
|
ri->i_compress_flag =
|
||||||
|
cpu_to_le16(F2FS_I(inode)->i_compress_flag);
|
||||||
ri->i_log_cluster_size =
|
ri->i_log_cluster_size =
|
||||||
F2FS_I(inode)->i_log_cluster_size;
|
F2FS_I(inode)->i_log_cluster_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,7 @@ enum {
|
||||||
Opt_compress_algorithm,
|
Opt_compress_algorithm,
|
||||||
Opt_compress_log_size,
|
Opt_compress_log_size,
|
||||||
Opt_compress_extension,
|
Opt_compress_extension,
|
||||||
|
Opt_compress_chksum,
|
||||||
Opt_atgc,
|
Opt_atgc,
|
||||||
Opt_err,
|
Opt_err,
|
||||||
};
|
};
|
||||||
|
@ -214,6 +215,7 @@ static match_table_t f2fs_tokens = {
|
||||||
{Opt_compress_algorithm, "compress_algorithm=%s"},
|
{Opt_compress_algorithm, "compress_algorithm=%s"},
|
||||||
{Opt_compress_log_size, "compress_log_size=%u"},
|
{Opt_compress_log_size, "compress_log_size=%u"},
|
||||||
{Opt_compress_extension, "compress_extension=%s"},
|
{Opt_compress_extension, "compress_extension=%s"},
|
||||||
|
{Opt_compress_chksum, "compress_chksum"},
|
||||||
{Opt_atgc, "atgc"},
|
{Opt_atgc, "atgc"},
|
||||||
{Opt_err, NULL},
|
{Opt_err, NULL},
|
||||||
};
|
};
|
||||||
|
@ -934,10 +936,14 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
|
||||||
F2FS_OPTION(sbi).compress_ext_cnt++;
|
F2FS_OPTION(sbi).compress_ext_cnt++;
|
||||||
kfree(name);
|
kfree(name);
|
||||||
break;
|
break;
|
||||||
|
case Opt_compress_chksum:
|
||||||
|
F2FS_OPTION(sbi).compress_chksum = true;
|
||||||
|
break;
|
||||||
#else
|
#else
|
||||||
case Opt_compress_algorithm:
|
case Opt_compress_algorithm:
|
||||||
case Opt_compress_log_size:
|
case Opt_compress_log_size:
|
||||||
case Opt_compress_extension:
|
case Opt_compress_extension:
|
||||||
|
case Opt_compress_chksum:
|
||||||
f2fs_info(sbi, "compression options not supported");
|
f2fs_info(sbi, "compression options not supported");
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1523,6 +1529,9 @@ static inline void f2fs_show_compress_options(struct seq_file *seq,
|
||||||
seq_printf(seq, ",compress_extension=%s",
|
seq_printf(seq, ",compress_extension=%s",
|
||||||
F2FS_OPTION(sbi).extensions[i]);
|
F2FS_OPTION(sbi).extensions[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (F2FS_OPTION(sbi).compress_chksum)
|
||||||
|
seq_puts(seq, ",compress_chksum");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
||||||
|
|
|
@ -273,7 +273,7 @@ struct f2fs_inode {
|
||||||
__le64 i_compr_blocks; /* # of compressed blocks */
|
__le64 i_compr_blocks; /* # of compressed blocks */
|
||||||
__u8 i_compress_algorithm; /* compress algorithm */
|
__u8 i_compress_algorithm; /* compress algorithm */
|
||||||
__u8 i_log_cluster_size; /* log of cluster size */
|
__u8 i_log_cluster_size; /* log of cluster size */
|
||||||
__le16 i_padding; /* padding */
|
__le16 i_compress_flag; /* compress flag */
|
||||||
__le32 i_extra_end[0]; /* for attribute size calculation */
|
__le32 i_extra_end[0]; /* for attribute size calculation */
|
||||||
} __packed;
|
} __packed;
|
||||||
__le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */
|
__le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче