Note that, there is one reserved special extension '*', it
can be set to enable compression for all files.
compress_chksum Support verifying chksum of raw data in compressed cluster.
+compress_mode=%s Control file compression mode. This supports "fs" and "user"
+ modes. In "fs" mode (default), f2fs does automatic compression
+ on the compression enabled files. In "user" mode, f2fs disables
+ the automaic compression and gives the user discretion of
+ choosing the target file and the timing. The user can do manual
+ compression/decompression on the compression enabled files using
+ ioctls.
inlinecrypt When possible, encrypt/decrypt the contents of encrypted
files using the blk-crypto framework rather than
filesystem-layer encryption. This allows the use of
| data length | data chksum | reserved | compressed data |
+-------------+-------------+----------+----------------------------+
+Compression mode
+--------------------------
+
+f2fs supports "fs" and "user" compression modes with "compression_mode" mount option.
+With this option, f2fs provides a choice to select the way how to compress the
+compression enabled files (refer to "Compression implementation" section for how to
+enable compression on a regular inode).
+
+1) compress_mode=fs
+This is the default option. f2fs does automatic compression in the writeback of the
+compression enabled files.
+
+2) compress_mode=user
+This disables the automaic compression and gives the user discretion of choosing the
+target file and the timing. The user can do manual compression/decompression on the
+compression enabled files using F2FS_IOC_DECOMPRESS_FILE and F2FS_IOC_COMPRESS_FILE
+ioctls like the below.
+
+To decompress a file,
+
+fd = open(filename, O_WRONLY, 0);
+ret = ioctl(fd, F2FS_IOC_DECOMPRESS_FILE);
+
+To compress a file,
+
+fd = open(filename, O_WRONLY, 0);
+ret = ioctl(fd, F2FS_IOC_COMPRESS_FILE);
+
NVMe Zoned Namespace devices
----------------------------
static bool cluster_may_compress(struct compress_ctx *cc)
{
- if (!f2fs_compressed_file(cc->inode))
+ if (!f2fs_need_compress_data(cc->inode))
return false;
if (f2fs_is_atomic_file(cc->inode))
return false;
if (IS_NOQUOTA(inode))
return false;
- if (f2fs_compressed_file(inode))
+ if (f2fs_need_compress_data(inode))
return true;
if (wbc->sync_mode != WB_SYNC_ALL)
return true;
unsigned char compress_log_size; /* cluster log size */
bool compress_chksum; /* compressed data chksum */
unsigned char compress_ext_cnt; /* extension count */
+ int compress_mode; /* compression mode */
unsigned char extensions[COMPRESS_EXT_NUM][F2FS_EXTENSION_LEN]; /* extensions */
};
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_ENABLE_COMPRESS, /* enable compression in "user" compression mode */
FI_MAX, /* max flag, never be used */
};
FSYNC_MODE_NOBARRIER, /* fsync behaves nobarrier based on posix */
};
+enum {
+ COMPR_MODE_FS, /*
+ * automatically compress compression
+ * enabled files
+ */
+ COMPR_MODE_USER, /*
+ * automatical compression is disabled.
+ * user can control the file compression
+ * using ioctls
+ */
+};
+
/*
* this value is set in page as a private data which indicate that
* the page is atomically written, and it is in inmem_pages list.
is_inode_flag_set(inode, FI_COMPRESSED_FILE);
}
+static inline bool f2fs_need_compress_data(struct inode *inode)
+{
+ int compress_mode = F2FS_OPTION(F2FS_I_SB(inode)).compress_mode;
+
+ if (!f2fs_compressed_file(inode))
+ return false;
+
+ if (compress_mode == COMPR_MODE_FS)
+ return true;
+ else if (compress_mode == COMPR_MODE_USER &&
+ is_inode_flag_set(inode, FI_ENABLE_COMPRESS))
+ return true;
+
+ return false;
+}
+
static inline unsigned int addrs_per_inode(struct inode *inode)
{
unsigned int addrs = CUR_ADDRS_PER_INODE(inode) -
else
return CURSEG_COLD_DATA;
}
- if (file_is_cold(inode) || f2fs_compressed_file(inode))
+ if (file_is_cold(inode) || f2fs_need_compress_data(inode))
return CURSEG_COLD_DATA;
if (file_is_hot(inode) ||
is_inode_flag_set(inode, FI_HOT_DATA) ||
Opt_compress_log_size,
Opt_compress_extension,
Opt_compress_chksum,
+ Opt_compress_mode,
Opt_atgc,
Opt_err,
};
{Opt_compress_log_size, "compress_log_size=%u"},
{Opt_compress_extension, "compress_extension=%s"},
{Opt_compress_chksum, "compress_chksum"},
+ {Opt_compress_mode, "compress_mode=%s"},
{Opt_atgc, "atgc"},
{Opt_err, NULL},
};
case Opt_compress_chksum:
F2FS_OPTION(sbi).compress_chksum = true;
break;
+ case Opt_compress_mode:
+ name = match_strdup(&args[0]);
+ if (!name)
+ return -ENOMEM;
+ if (!strcmp(name, "fs")) {
+ F2FS_OPTION(sbi).compress_mode = COMPR_MODE_FS;
+ } else if (!strcmp(name, "user")) {
+ F2FS_OPTION(sbi).compress_mode = COMPR_MODE_USER;
+ } else {
+ kfree(name);
+ return -EINVAL;
+ }
+ kfree(name);
+ break;
#else
case Opt_compress_algorithm:
case Opt_compress_log_size:
case Opt_compress_extension:
case Opt_compress_chksum:
+ case Opt_compress_mode:
f2fs_info(sbi, "compression options not supported");
break;
#endif
if (F2FS_OPTION(sbi).compress_chksum)
seq_puts(seq, ",compress_chksum");
+
+ if (F2FS_OPTION(sbi).compress_mode == COMPR_MODE_FS)
+ seq_printf(seq, ",compress_mode=%s", "fs");
+ else if (F2FS_OPTION(sbi).compress_mode == COMPR_MODE_USER)
+ seq_printf(seq, ",compress_mode=%s", "user");
}
static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4;
F2FS_OPTION(sbi).compress_log_size = MIN_COMPRESS_LOG_SIZE;
F2FS_OPTION(sbi).compress_ext_cnt = 0;
+ F2FS_OPTION(sbi).compress_mode = COMPR_MODE_FS;
F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
sbi->sb->s_flags &= ~SB_INLINECRYPT;