Commit fa61a33f authored by Gao Xiang's avatar Gao Xiang Committed by Greg Kroah-Hartman

staging: erofs: move per-CPU buffers implementation to utils.c

This patch moves per-CPU buffers to utils.c in order for
the upcoming generic decompression framework to use it.

Note that I tried to use generic per-CPU buffer or
per-CPU page approaches to clean up further, but obvious
performanace regression (about 2% for sequential read) was
observed.

Therefore let's leave it as it is instead, just move
to utils.c and I'll try to dig into the root cause later.
Signed-off-by: default avatarGao Xiang <gaoxiang25@huawei.com>
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 152a333a
...@@ -321,6 +321,16 @@ static inline void z_erofs_exit_zip_subsystem(void) {} ...@@ -321,6 +321,16 @@ static inline void z_erofs_exit_zip_subsystem(void) {}
/* page count of a compressed cluster */ /* page count of a compressed cluster */
#define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) #define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE)
#define Z_EROFS_NR_INLINE_PAGEVECS 3
#if (Z_EROFS_CLUSTER_MAX_PAGES > Z_EROFS_NR_INLINE_PAGEVECS)
#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES
#else
#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_NR_INLINE_PAGEVECS
#endif
#else
#define EROFS_PCPUBUF_NR_PAGES 0
#endif #endif
typedef u64 erofs_off_t; typedef u64 erofs_off_t;
...@@ -608,6 +618,22 @@ static inline void erofs_vunmap(const void *mem, unsigned int count) ...@@ -608,6 +618,22 @@ static inline void erofs_vunmap(const void *mem, unsigned int count)
extern struct shrinker erofs_shrinker_info; extern struct shrinker erofs_shrinker_info;
struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp);
#if (EROFS_PCPUBUF_NR_PAGES > 0)
void *erofs_get_pcpubuf(unsigned int pagenr);
#define erofs_put_pcpubuf(buf) do { \
(void)&(buf); \
preempt_enable(); \
} while (0)
#else
static inline void *erofs_get_pcpubuf(unsigned int pagenr)
{
return ERR_PTR(-ENOTSUPP);
}
#define erofs_put_pcpubuf(buf) do {} while (0)
#endif
void erofs_register_super(struct super_block *sb); void erofs_register_super(struct super_block *sb);
void erofs_unregister_super(struct super_block *sb); void erofs_unregister_super(struct super_block *sb);
......
...@@ -552,8 +552,7 @@ static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder, ...@@ -552,8 +552,7 @@ static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder,
if (IS_ERR(work)) if (IS_ERR(work))
return PTR_ERR(work); return PTR_ERR(work);
got_it: got_it:
z_erofs_pagevec_ctor_init(&builder->vector, z_erofs_pagevec_ctor_init(&builder->vector, Z_EROFS_NR_INLINE_PAGEVECS,
Z_EROFS_VLE_INLINE_PAGEVECS,
work->pagevec, work->vcnt); work->pagevec, work->vcnt);
if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY) { if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY) {
...@@ -936,7 +935,7 @@ static int z_erofs_vle_unzip(struct super_block *sb, ...@@ -936,7 +935,7 @@ static int z_erofs_vle_unzip(struct super_block *sb,
for (i = 0; i < nr_pages; ++i) for (i = 0; i < nr_pages; ++i)
pages[i] = NULL; pages[i] = NULL;
z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_VLE_INLINE_PAGEVECS, z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS,
work->pagevec, 0); work->pagevec, 0);
for (i = 0; i < work->vcnt; ++i) { for (i = 0; i < work->vcnt; ++i) {
......
...@@ -44,8 +44,6 @@ static inline bool z_erofs_gather_if_stagingpage(struct list_head *page_pool, ...@@ -44,8 +44,6 @@ static inline bool z_erofs_gather_if_stagingpage(struct list_head *page_pool,
* *
*/ */
#define Z_EROFS_VLE_INLINE_PAGEVECS 3
struct z_erofs_vle_work { struct z_erofs_vle_work {
struct mutex lock; struct mutex lock;
...@@ -58,7 +56,7 @@ struct z_erofs_vle_work { ...@@ -58,7 +56,7 @@ struct z_erofs_vle_work {
union { union {
/* L: pagevec */ /* L: pagevec */
erofs_vtptr_t pagevec[Z_EROFS_VLE_INLINE_PAGEVECS]; erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS];
struct rcu_head rcu; struct rcu_head rcu;
}; };
}; };
......
...@@ -34,16 +34,6 @@ static int z_erofs_unzip_lz4(void *in, void *out, size_t inlen, size_t outlen) ...@@ -34,16 +34,6 @@ static int z_erofs_unzip_lz4(void *in, void *out, size_t inlen, size_t outlen)
return -EIO; return -EIO;
} }
#if Z_EROFS_CLUSTER_MAX_PAGES > Z_EROFS_VLE_INLINE_PAGEVECS
#define EROFS_PERCPU_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES
#else
#define EROFS_PERCPU_NR_PAGES Z_EROFS_VLE_INLINE_PAGEVECS
#endif
static struct {
char data[PAGE_SIZE * EROFS_PERCPU_NR_PAGES];
} erofs_pcpubuf[NR_CPUS];
int z_erofs_vle_plain_copy(struct page **compressed_pages, int z_erofs_vle_plain_copy(struct page **compressed_pages,
unsigned int clusterpages, unsigned int clusterpages,
struct page **pages, struct page **pages,
...@@ -56,8 +46,9 @@ int z_erofs_vle_plain_copy(struct page **compressed_pages, ...@@ -56,8 +46,9 @@ int z_erofs_vle_plain_copy(struct page **compressed_pages,
char *percpu_data; char *percpu_data;
bool mirrored[Z_EROFS_CLUSTER_MAX_PAGES] = { 0 }; bool mirrored[Z_EROFS_CLUSTER_MAX_PAGES] = { 0 };
preempt_disable(); percpu_data = erofs_get_pcpubuf(0);
percpu_data = erofs_pcpubuf[smp_processor_id()].data; if (IS_ERR(percpu_data))
return PTR_ERR(percpu_data);
j = 0; j = 0;
for (i = 0; i < nr_pages; j = i++) { for (i = 0; i < nr_pages; j = i++) {
...@@ -117,7 +108,7 @@ int z_erofs_vle_plain_copy(struct page **compressed_pages, ...@@ -117,7 +108,7 @@ int z_erofs_vle_plain_copy(struct page **compressed_pages,
if (src && !mirrored[j]) if (src && !mirrored[j])
kunmap_atomic(src); kunmap_atomic(src);
preempt_enable(); erofs_put_pcpubuf(percpu_data);
return 0; return 0;
} }
...@@ -131,7 +122,7 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages, ...@@ -131,7 +122,7 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
unsigned int nr_pages, i, j; unsigned int nr_pages, i, j;
int ret; int ret;
if (outlen + pageofs > EROFS_PERCPU_NR_PAGES * PAGE_SIZE) if (outlen + pageofs > EROFS_PCPUBUF_NR_PAGES * PAGE_SIZE)
return -ENOTSUPP; return -ENOTSUPP;
nr_pages = DIV_ROUND_UP(outlen + pageofs, PAGE_SIZE); nr_pages = DIV_ROUND_UP(outlen + pageofs, PAGE_SIZE);
...@@ -144,8 +135,9 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages, ...@@ -144,8 +135,9 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
return -ENOMEM; return -ENOMEM;
} }
preempt_disable(); vout = erofs_get_pcpubuf(0);
vout = erofs_pcpubuf[smp_processor_id()].data; if (IS_ERR(vout))
return PTR_ERR(vout);
ret = z_erofs_unzip_lz4(vin, vout + pageofs, ret = z_erofs_unzip_lz4(vin, vout + pageofs,
clusterpages * PAGE_SIZE, outlen); clusterpages * PAGE_SIZE, outlen);
...@@ -174,7 +166,7 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages, ...@@ -174,7 +166,7 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
} }
out: out:
preempt_enable(); erofs_put_pcpubuf(vout);
if (clusterpages == 1) if (clusterpages == 1)
kunmap_atomic(vin); kunmap_atomic(vin);
...@@ -196,8 +188,9 @@ int z_erofs_vle_unzip_vmap(struct page **compressed_pages, ...@@ -196,8 +188,9 @@ int z_erofs_vle_unzip_vmap(struct page **compressed_pages,
int ret; int ret;
if (overlapped) { if (overlapped) {
preempt_disable(); vin = erofs_get_pcpubuf(0);
vin = erofs_pcpubuf[smp_processor_id()].data; if (IS_ERR(vin))
return PTR_ERR(vin);
for (i = 0; i < clusterpages; ++i) { for (i = 0; i < clusterpages; ++i) {
void *t = kmap_atomic(compressed_pages[i]); void *t = kmap_atomic(compressed_pages[i]);
...@@ -216,13 +209,13 @@ int z_erofs_vle_unzip_vmap(struct page **compressed_pages, ...@@ -216,13 +209,13 @@ int z_erofs_vle_unzip_vmap(struct page **compressed_pages,
if (ret > 0) if (ret > 0)
ret = 0; ret = 0;
if (!overlapped) { if (overlapped) {
erofs_put_pcpubuf(vin);
} else {
if (clusterpages == 1) if (clusterpages == 1)
kunmap_atomic(vin); kunmap_atomic(vin);
else else
erofs_vunmap(vin, clusterpages); erofs_vunmap(vin, clusterpages);
} else {
preempt_enable();
} }
return ret; return ret;
} }
......
...@@ -27,6 +27,18 @@ struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) ...@@ -27,6 +27,18 @@ struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp)
return page; return page;
} }
#if (EROFS_PCPUBUF_NR_PAGES > 0)
static struct {
u8 data[PAGE_SIZE * EROFS_PCPUBUF_NR_PAGES];
} ____cacheline_aligned_in_smp erofs_pcpubuf[NR_CPUS];
void *erofs_get_pcpubuf(unsigned int pagenr)
{
preempt_disable();
return &erofs_pcpubuf[smp_processor_id()].data[pagenr * PAGE_SIZE];
}
#endif
/* global shrink count (for all mounted EROFS instances) */ /* global shrink count (for all mounted EROFS instances) */
static atomic_long_t erofs_global_shrink_cnt; static atomic_long_t erofs_global_shrink_cnt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment