Skip to content

Commit 77292bb

Browse files
Barry Songherbertx
authored andcommitted
crypto: scomp - remove memcpy if sg_nents is 1 and pages are lowmem
while sg_nents is 1, which is always true for the current kernel as the only user - zswap is this case, we might have a chance to remove memcpy, thus improve the performance. Though sg_nents is 1, its buffer might cross two pages. If those pages are highmem, we have no cheap way to map them to contiguous virtual address because kmap doesn't support more than one page (kmap single higmem page could be still expensive for tlb) and vmap is expensive. So we also test and enure page is not highmem in order to safely use page_to_virt before removing the memcpy. The good news is that in the most majority of cases, we are lowmem, and we are always lowmem in those modern and popular hardware. Cc: Johannes Weiner <[email protected]> Cc: Nhat Pham <[email protected]> Cc: Yosry Ahmed <[email protected]> Signed-off-by: Barry Song <[email protected]> Tested-by: Chengming Zhou <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 43a7885 commit 77292bb

File tree

1 file changed

+29
-7
lines changed

1 file changed

+29
-7
lines changed

crypto/scompress.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
117117
struct crypto_scomp *scomp = *tfm_ctx;
118118
void **ctx = acomp_request_ctx(req);
119119
struct scomp_scratch *scratch;
120+
void *src, *dst;
120121
unsigned int dlen;
121122
int ret;
122123

@@ -134,13 +135,25 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
134135
scratch = raw_cpu_ptr(&scomp_scratch);
135136
spin_lock(&scratch->lock);
136137

137-
scatterwalk_map_and_copy(scratch->src, req->src, 0, req->slen, 0);
138+
if (sg_nents(req->src) == 1 && !PageHighMem(sg_page(req->src))) {
139+
src = page_to_virt(sg_page(req->src)) + req->src->offset;
140+
} else {
141+
scatterwalk_map_and_copy(scratch->src, req->src, 0,
142+
req->slen, 0);
143+
src = scratch->src;
144+
}
145+
146+
if (req->dst && sg_nents(req->dst) == 1 && !PageHighMem(sg_page(req->dst)))
147+
dst = page_to_virt(sg_page(req->dst)) + req->dst->offset;
148+
else
149+
dst = scratch->dst;
150+
138151
if (dir)
139-
ret = crypto_scomp_compress(scomp, scratch->src, req->slen,
140-
scratch->dst, &req->dlen, *ctx);
152+
ret = crypto_scomp_compress(scomp, src, req->slen,
153+
dst, &req->dlen, *ctx);
141154
else
142-
ret = crypto_scomp_decompress(scomp, scratch->src, req->slen,
143-
scratch->dst, &req->dlen, *ctx);
155+
ret = crypto_scomp_decompress(scomp, src, req->slen,
156+
dst, &req->dlen, *ctx);
144157
if (!ret) {
145158
if (!req->dst) {
146159
req->dst = sgl_alloc(req->dlen, GFP_ATOMIC, NULL);
@@ -152,8 +165,17 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
152165
ret = -ENOSPC;
153166
goto out;
154167
}
155-
scatterwalk_map_and_copy(scratch->dst, req->dst, 0, req->dlen,
156-
1);
168+
if (dst == scratch->dst) {
169+
scatterwalk_map_and_copy(scratch->dst, req->dst, 0,
170+
req->dlen, 1);
171+
} else {
172+
int nr_pages = DIV_ROUND_UP(req->dst->offset + req->dlen, PAGE_SIZE);
173+
int i;
174+
struct page *dst_page = sg_page(req->dst);
175+
176+
for (i = 0; i < nr_pages; i++)
177+
flush_dcache_page(dst_page + i);
178+
}
157179
}
158180
out:
159181
spin_unlock(&scratch->lock);

0 commit comments

Comments
 (0)