staging: erofs: turn cache strategies into mount options

Kill all kconfig cache strategies and turn them into mount options
"cache_strategy={disable|readahead|readaround}".

As the first step, cached pages can still be usable after cache
is disabled by remounting, and these pages will be fallen out
over time, which can be refined in the later version if some
requirement is needed. Update related document as well.

Suggested-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
Link: https://lore.kernel.org/r/20190731155752.210602-20-gaoxiang25@huawei.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Gao Xiang 2019-07-31 23:57:49 +08:00 коммит произвёл Greg Kroah-Hartman
Родитель eace994a11
Коммит 4279f3f988
7 изменённых файлов: 87 добавлений и 142 удалений

Просмотреть файл

@ -65,6 +65,16 @@ fault_injection=%d Enable fault injection in all supported types with
by default if CONFIG_EROFS_FS_XATTR is selected.
(no)acl Setup POSIX Access Control List. Note: acl is enabled
by default if CONFIG_EROFS_FS_POSIX_ACL is selected.
cache_strategy=%s Select a strategy for cached decompression from now on:
disabled: In-place I/O decompression only;
readahead: Cache the last incomplete compressed physical
cluster for further reading. It still does
in-place I/O decompression for the rest
compressed physical clusters;
readaround: Cache the both ends of incomplete compressed
physical clusters for further reading.
It still does in-place I/O decompression
for the rest compressed physical clusters.
Module parameters
=================

Просмотреть файл

@ -94,41 +94,3 @@ config EROFS_FS_CLUSTER_PAGE_LIMIT
than 2. Otherwise, the image cannot be mounted
correctly on this kernel.
choice
prompt "EROFS VLE Data Decompression mode"
depends on EROFS_FS_ZIP
default EROFS_FS_ZIP_CACHE_BIPOLAR
help
EROFS supports three options for VLE decompression.
"In-place Decompression Only" consumes the minimum memory
with lowest random read.
"Bipolar Cached Decompression" consumes the maximum memory
with highest random read.
If unsure, select "Bipolar Cached Decompression"
config EROFS_FS_ZIP_NO_CACHE
bool "In-place Decompression Only"
help
Read compressed data into page cache and do in-place
decompression directly.
config EROFS_FS_ZIP_CACHE_UNIPOLAR
bool "Unipolar Cached Decompression"
help
For each request, it caches the last compressed page
for further reading.
It still decompresses in place for the rest compressed pages.
config EROFS_FS_ZIP_CACHE_BIPOLAR
bool "Bipolar Cached Decompression"
help
For each request, it caches the both end compressed pages
for further reading.
It still decompresses in place for the rest compressed pages.
Recommended for performance priority.
endchoice

Просмотреть файл

@ -51,18 +51,6 @@ struct erofs_fault_info {
};
#endif /* CONFIG_EROFS_FAULT_INJECTION */
#ifdef CONFIG_EROFS_FS_ZIP_CACHE_BIPOLAR
#define EROFS_FS_ZIP_CACHE_LVL (2)
#elif defined(EROFS_FS_ZIP_CACHE_UNIPOLAR)
#define EROFS_FS_ZIP_CACHE_LVL (1)
#else
#define EROFS_FS_ZIP_CACHE_LVL (0)
#endif
#if (!defined(EROFS_FS_HAS_MANAGED_CACHE) && (EROFS_FS_ZIP_CACHE_LVL > 0))
#define EROFS_FS_HAS_MANAGED_CACHE
#endif
/* EROFS_SUPER_MAGIC_V1 to represent the whole file system */
#define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1
@ -85,10 +73,11 @@ struct erofs_sb_info {
unsigned int shrinker_run_no;
#ifdef EROFS_FS_HAS_MANAGED_CACHE
struct inode *managed_cache;
#endif
/* current strategy of how to use managed cache */
unsigned char cache_strategy;
/* pseudo inode to manage cached pages */
struct inode *managed_cache;
#endif /* CONFIG_EROFS_FS_ZIP */
u32 blocks;
u32 meta_blkaddr;
@ -174,6 +163,12 @@ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi,
#define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option)
#ifdef CONFIG_EROFS_FS_ZIP
enum {
EROFS_ZIP_CACHE_DISABLED,
EROFS_ZIP_CACHE_READAHEAD,
EROFS_ZIP_CACHE_READAROUND
};
#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL)
/* basic unit of the workstation of a super_block */

Просмотреть файл

@ -197,17 +197,50 @@ static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi)
}
#endif
static void default_options(struct erofs_sb_info *sbi)
{
/* set up some FS parameters */
#ifdef CONFIG_EROFS_FS_ZIP
sbi->max_sync_decompress_pages = 3;
static int erofs_build_cache_strategy(struct erofs_sb_info *sbi,
substring_t *args)
{
const char *cs = match_strdup(args);
int err = 0;
if (!cs) {
errln("Not enough memory to store cache strategy");
return -ENOMEM;
}
if (!strcmp(cs, "disabled")) {
sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED;
} else if (!strcmp(cs, "readahead")) {
sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD;
} else if (!strcmp(cs, "readaround")) {
sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND;
} else {
errln("Unrecognized cache strategy \"%s\"", cs);
err = -EINVAL;
}
kfree(cs);
return err;
}
#else
static int erofs_build_cache_strategy(struct erofs_sb_info *sbi,
substring_t *args)
{
infoln("EROFS compression is disabled, so cache strategy is ignored");
return 0;
}
#endif
/* set up default EROFS parameters */
static void default_options(struct erofs_sb_info *sbi)
{
#ifdef CONFIG_EROFS_FS_ZIP
sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND;
sbi->max_sync_decompress_pages = 3;
#endif
#ifdef CONFIG_EROFS_FS_XATTR
set_opt(sbi, XATTR_USER);
#endif
#ifdef CONFIG_EROFS_FS_POSIX_ACL
set_opt(sbi, POSIX_ACL);
#endif
@ -219,6 +252,7 @@ enum {
Opt_acl,
Opt_noacl,
Opt_fault_injection,
Opt_cache_strategy,
Opt_err
};
@ -228,6 +262,7 @@ static match_table_t erofs_tokens = {
{Opt_acl, "acl"},
{Opt_noacl, "noacl"},
{Opt_fault_injection, "fault_injection=%u"},
{Opt_cache_strategy, "cache_strategy=%s"},
{Opt_err, NULL}
};
@ -285,7 +320,11 @@ static int parse_options(struct super_block *sb, char *options)
if (err)
return err;
break;
case Opt_cache_strategy:
err = erofs_build_cache_strategy(EROFS_SB(sb), args);
if (err)
return err;
break;
default:
errln("Unrecognized mount option \"%s\" "
"or missing value", p);
@ -295,8 +334,7 @@ static int parse_options(struct super_block *sb, char *options)
return 0;
}
#ifdef EROFS_FS_HAS_MANAGED_CACHE
#ifdef CONFIG_EROFS_FS_ZIP
static const struct address_space_operations managed_cache_aops;
static int managed_cache_releasepage(struct page *page, gfp_t gfp_mask)
@ -469,7 +507,7 @@ static void erofs_put_super(struct super_block *sb)
DBG_BUGON(!sbi);
erofs_shrinker_unregister(sb);
#ifdef EROFS_FS_HAS_MANAGED_CACHE
#ifdef CONFIG_EROFS_FS_ZIP
iput(sbi->managed_cache);
sbi->managed_cache = NULL;
#endif
@ -570,6 +608,18 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root)
if (test_opt(sbi, FAULT_INJECTION))
seq_printf(seq, ",fault_injection=%u",
erofs_get_fault_rate(sbi));
#ifdef CONFIG_EROFS_FS_ZIP
if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) {
seq_puts(seq, ",cache_strategy=disabled");
} else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) {
seq_puts(seq, ",cache_strategy=readahead");
} else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) {
seq_puts(seq, ",cache_strategy=readaround");
} else {
seq_puts(seq, ",cache_strategy=(unknown)");
DBG_BUGON(1);
}
#endif
return 0;
}

Просмотреть файл

@ -145,8 +145,6 @@ int erofs_workgroup_put(struct erofs_workgroup *grp)
return count;
}
#ifdef EROFS_FS_HAS_MANAGED_CACHE
/* for cache-managed case, customized reclaim paths exist */
static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp)
{
erofs_workgroup_unfreeze(grp, 0);
@ -192,30 +190,6 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
return true;
}
#else
/* for nocache case, no customized reclaim path at all */
static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi,
struct erofs_workgroup *grp,
bool cleanup)
{
int cnt = atomic_read(&grp->refcount);
DBG_BUGON(cnt <= 0);
DBG_BUGON(cleanup && cnt != 1);
if (cnt > 1)
return false;
DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree,
grp->index)) != grp);
/* (rarely) could be grabbed again when freeing */
erofs_workgroup_put(grp);
return true;
}
#endif
static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi,
unsigned long nr_shrink,
bool cleanup)

Просмотреть файл

@ -162,7 +162,6 @@ struct z_erofs_decompress_frontend {
static struct page *z_pagemap_global[Z_EROFS_VMAP_GLOBAL_PAGES];
static DEFINE_MUTEX(z_pagemap_global_lock);
#ifdef EROFS_FS_HAS_MANAGED_CACHE
static void preload_compressed_pages(struct z_erofs_collector *clt,
struct address_space *mc,
enum z_erofs_cache_alloctype type,
@ -273,15 +272,6 @@ int erofs_try_to_free_cached_page(struct address_space *mapping,
}
return ret;
}
#else
static void preload_compressed_pages(struct z_erofs_collector *clt,
struct address_space *mc,
enum z_erofs_cache_alloctype type,
struct list_head *pagepool)
{
/* nowhere to load compressed pages from */
}
#endif
/* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */
static inline bool try_inplace_io(struct z_erofs_collector *clt,
@ -547,25 +537,19 @@ static inline struct page *__stagingpage_alloc(struct list_head *pagepool,
return page;
}
#ifdef EROFS_FS_HAS_MANAGED_CACHE
static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe,
unsigned int cachestrategy,
erofs_off_t la)
{
if (cachestrategy <= EROFS_ZIP_CACHE_DISABLED)
return false;
if (fe->backmost)
return true;
if (EROFS_FS_ZIP_CACHE_LVL >= 2)
return la < fe->headoffset;
return false;
return cachestrategy >= EROFS_ZIP_CACHE_READAROUND &&
la < fe->headoffset;
}
#else
static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe,
erofs_off_t la)
{
return false;
}
#endif
static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe,
struct page *page,
@ -621,7 +605,7 @@ restart_now:
goto err_out;
/* preload all compressed pages (maybe downgrade role if necessary) */
if (should_alloc_managed_pages(fe, map->m_la))
if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la))
cache_strategy = DELAYEDALLOC;
else
cache_strategy = DONTALLOC;
@ -1126,9 +1110,7 @@ out:
/* define decompression jobqueue types */
enum {
#ifdef EROFS_FS_HAS_MANAGED_CACHE
JQ_BYPASS,
#endif
JQ_SUBMIT,
NR_JOBQUEUES,
};
@ -1139,14 +1121,12 @@ static void *jobqueueset_init(struct super_block *sb,
struct z_erofs_unzip_io *fgq,
bool forcefg)
{
#ifdef EROFS_FS_HAS_MANAGED_CACHE
/*
* if managed cache is enabled, bypass jobqueue is needed,
* no need to read from device for all pclusters in this queue.
*/
q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true);
qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head;
#endif
q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg);
qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head;
@ -1154,7 +1134,6 @@ static void *jobqueueset_init(struct super_block *sb,
return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg));
}
#ifdef EROFS_FS_HAS_MANAGED_CACHE
static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl,
z_erofs_next_pcluster_t qtail[],
z_erofs_next_pcluster_t owned_head)
@ -1188,24 +1167,6 @@ static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[],
kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io));
return true;
}
#else
static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl,
z_erofs_next_pcluster_t qtail[],
z_erofs_next_pcluster_t owned_head)
{
/* impossible to bypass submission for managed cache disabled */
DBG_BUGON(1);
}
static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[],
unsigned int nr_bios,
bool force_fg)
{
/* bios should be >0 if managed cache is disabled */
DBG_BUGON(!nr_bios);
return false;
}
#endif
static bool z_erofs_vle_submit_all(struct super_block *sb,
z_erofs_next_pcluster_t owned_head,
@ -1317,10 +1278,9 @@ static void z_erofs_submit_and_unzip(struct super_block *sb,
pagepool, io, force_fg))
return;
#ifdef EROFS_FS_HAS_MANAGED_CACHE
/* decompress no I/O pclusters immediately */
z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool);
#endif
if (!force_fg)
return;

Просмотреть файл

@ -101,18 +101,12 @@ struct z_erofs_unzip_io_sb {
struct super_block *sb;
};
#ifdef EROFS_FS_HAS_MANAGED_CACHE
#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping)
static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi,
struct page *page)
{
return page->mapping == MNGD_MAPPING(sbi);
}
#else
#define MNGD_MAPPING(sbi) (NULL)
static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi,
struct page *page) { return false; }
#endif /* !EROFS_FS_HAS_MANAGED_CACHE */
#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2
#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1)