Skip to content

Commit 7e0969b

Browse files
committed
ubifs: Pass folios to acomp
As the acomp interface supports folios, use that instead of mapping the data in ubifs. Signed-off-by: Herbert Xu <[email protected]> Tested-by: Zhihao Cheng <[email protected]> # For xfstests Signed-off-by: Herbert Xu <[email protected]>
1 parent 37b605f commit 7e0969b

File tree

4 files changed

+145
-55
lines changed

4 files changed

+145
-55
lines changed

fs/ubifs/compress.c

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
#include <crypto/acompress.h>
19+
#include <linux/highmem.h>
1920
#include "ubifs.h"
2021

2122
/* Fake description object for the "none" compressor */
@@ -126,7 +127,7 @@ void ubifs_compress(const struct ubifs_info *c, const void *in_buf,
126127
{
127128
ACOMP_REQUEST_ALLOC(req, compr->cc, GFP_NOFS | __GFP_NOWARN);
128129

129-
acomp_request_set_src_nondma(req, in_buf, in_len);
130+
acomp_request_set_src_dma(req, in_buf, in_len);
130131
err = ubifs_compress_req(c, req, out_buf, out_len, compr->name);
131132
}
132133

@@ -141,6 +142,58 @@ void ubifs_compress(const struct ubifs_info *c, const void *in_buf,
141142
*compr_type = UBIFS_COMPR_NONE;
142143
}
143144

145+
/**
146+
* ubifs_compress_folio - compress folio.
147+
* @c: UBIFS file-system description object
148+
* @in_folio: data to compress
149+
* @in_offset: offset into @in_folio
150+
* @in_len: length of the data to compress
151+
* @out_buf: output buffer where compressed data should be stored
152+
* @out_len: output buffer length is returned here
153+
* @compr_type: type of compression to use on enter, actually used compression
154+
* type on exit
155+
*
156+
* This function compresses input folio @in_folio of length @in_len and
157+
* stores the result in the output buffer @out_buf and the resulting length
158+
* in @out_len. If the input buffer does not compress, it is just copied
159+
* to the @out_buf. The same happens if @compr_type is %UBIFS_COMPR_NONE
160+
* or if compression error occurred.
161+
*
162+
* Note, if the input buffer was not compressed, it is copied to the output
163+
* buffer and %UBIFS_COMPR_NONE is returned in @compr_type.
164+
*/
165+
void ubifs_compress_folio(const struct ubifs_info *c, struct folio *in_folio,
166+
size_t in_offset, int in_len, void *out_buf,
167+
int *out_len, int *compr_type)
168+
{
169+
int err;
170+
struct ubifs_compressor *compr = ubifs_compressors[*compr_type];
171+
172+
if (*compr_type == UBIFS_COMPR_NONE)
173+
goto no_compr;
174+
175+
/* If the input data is small, do not even try to compress it */
176+
if (in_len < UBIFS_MIN_COMPR_LEN)
177+
goto no_compr;
178+
179+
{
180+
ACOMP_REQUEST_ALLOC(req, compr->cc, GFP_NOFS | __GFP_NOWARN);
181+
182+
acomp_request_set_src_folio(req, in_folio, in_offset, in_len);
183+
err = ubifs_compress_req(c, req, out_buf, out_len, compr->name);
184+
}
185+
186+
if (err)
187+
goto no_compr;
188+
189+
return;
190+
191+
no_compr:
192+
memcpy_from_folio(out_buf, in_folio, in_offset, in_len);
193+
*out_len = in_len;
194+
*compr_type = UBIFS_COMPR_NONE;
195+
}
196+
144197
static int ubifs_decompress_req(const struct ubifs_info *c,
145198
struct acomp_req *req,
146199
const void *in_buf, int in_len, int *out_len,
@@ -205,7 +258,56 @@ int ubifs_decompress(const struct ubifs_info *c, const void *in_buf,
205258
{
206259
ACOMP_REQUEST_ALLOC(req, compr->cc, GFP_NOFS | __GFP_NOWARN);
207260

208-
acomp_request_set_dst_nondma(req, out_buf, *out_len);
261+
acomp_request_set_dst_dma(req, out_buf, *out_len);
262+
return ubifs_decompress_req(c, req, in_buf, in_len, out_len,
263+
compr->name);
264+
}
265+
}
266+
267+
/**
268+
* ubifs_decompress_folio - decompress folio.
269+
* @c: UBIFS file-system description object
270+
* @in_buf: data to decompress
271+
* @in_len: length of the data to decompress
272+
* @out_folio: output folio where decompressed data should
273+
* @out_offset: offset into @out_folio
274+
* @out_len: output length is returned here
275+
* @compr_type: type of compression
276+
*
277+
* This function decompresses data from buffer @in_buf into folio
278+
* @out_folio. The length of the uncompressed data is returned in
279+
* @out_len. This functions returns %0 on success or a negative error
280+
* code on failure.
281+
*/
282+
int ubifs_decompress_folio(const struct ubifs_info *c, const void *in_buf,
283+
int in_len, struct folio *out_folio,
284+
size_t out_offset, int *out_len, int compr_type)
285+
{
286+
struct ubifs_compressor *compr;
287+
288+
if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
289+
ubifs_err(c, "invalid compression type %d", compr_type);
290+
return -EINVAL;
291+
}
292+
293+
compr = ubifs_compressors[compr_type];
294+
295+
if (unlikely(!compr->capi_name)) {
296+
ubifs_err(c, "%s compression is not compiled in", compr->name);
297+
return -EINVAL;
298+
}
299+
300+
if (compr_type == UBIFS_COMPR_NONE) {
301+
memcpy_to_folio(out_folio, out_offset, in_buf, in_len);
302+
*out_len = in_len;
303+
return 0;
304+
}
305+
306+
{
307+
ACOMP_REQUEST_ALLOC(req, compr->cc, GFP_NOFS | __GFP_NOWARN);
308+
309+
acomp_request_set_dst_folio(req, out_folio, out_offset,
310+
*out_len);
209311
return ubifs_decompress_req(c, req, in_buf, in_len, out_len,
210312
compr->name);
211313
}

fs/ubifs/file.c

Lines changed: 25 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
#include <linux/slab.h>
4343
#include <linux/migrate.h>
4444

45-
static int read_block(struct inode *inode, void *addr, unsigned int block,
46-
struct ubifs_data_node *dn)
45+
static int read_block(struct inode *inode, struct folio *folio, size_t offset,
46+
unsigned int block, struct ubifs_data_node *dn)
4747
{
4848
struct ubifs_info *c = inode->i_sb->s_fs_info;
4949
int err, len, out_len;
@@ -55,7 +55,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
5555
if (err) {
5656
if (err == -ENOENT)
5757
/* Not found, so it must be a hole */
58-
memset(addr, 0, UBIFS_BLOCK_SIZE);
58+
folio_zero_range(folio, offset, UBIFS_BLOCK_SIZE);
5959
return err;
6060
}
6161

@@ -74,8 +74,8 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
7474
}
7575

7676
out_len = UBIFS_BLOCK_SIZE;
77-
err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
78-
le16_to_cpu(dn->compr_type));
77+
err = ubifs_decompress_folio(c, &dn->data, dlen, folio, offset,
78+
&out_len, le16_to_cpu(dn->compr_type));
7979
if (err || len != out_len)
8080
goto dump;
8181

@@ -85,7 +85,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
8585
* appending data). Ensure that the remainder is zeroed out.
8686
*/
8787
if (len < UBIFS_BLOCK_SIZE)
88-
memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
88+
folio_zero_range(folio, offset + len, UBIFS_BLOCK_SIZE - len);
8989

9090
return 0;
9191

@@ -98,27 +98,25 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
9898

9999
static int do_readpage(struct folio *folio)
100100
{
101-
void *addr;
102101
int err = 0, i;
103102
unsigned int block, beyond;
104103
struct ubifs_data_node *dn = NULL;
105104
struct inode *inode = folio->mapping->host;
106105
struct ubifs_info *c = inode->i_sb->s_fs_info;
107106
loff_t i_size = i_size_read(inode);
107+
size_t offset = 0;
108108

109109
dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx",
110110
inode->i_ino, folio->index, i_size, folio->flags);
111111
ubifs_assert(c, !folio_test_checked(folio));
112112
ubifs_assert(c, !folio->private);
113113

114-
addr = kmap_local_folio(folio, 0);
115-
116114
block = folio->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
117115
beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
118116
if (block >= beyond) {
119117
/* Reading beyond inode */
120118
folio_set_checked(folio);
121-
addr = folio_zero_tail(folio, 0, addr);
119+
folio_zero_range(folio, 0, folio_size(folio));
122120
goto out;
123121
}
124122

@@ -135,9 +133,9 @@ static int do_readpage(struct folio *folio)
135133
if (block >= beyond) {
136134
/* Reading beyond inode */
137135
err = -ENOENT;
138-
memset(addr, 0, UBIFS_BLOCK_SIZE);
136+
folio_zero_range(folio, offset, UBIFS_BLOCK_SIZE);
139137
} else {
140-
ret = read_block(inode, addr, block, dn);
138+
ret = read_block(inode, folio, offset, block, dn);
141139
if (ret) {
142140
err = ret;
143141
if (err != -ENOENT)
@@ -147,17 +145,13 @@ static int do_readpage(struct folio *folio)
147145
int ilen = i_size & (UBIFS_BLOCK_SIZE - 1);
148146

149147
if (ilen && ilen < dlen)
150-
memset(addr + ilen, 0, dlen - ilen);
148+
folio_zero_range(folio, offset + ilen, dlen - ilen);
151149
}
152150
}
153151
if (++i >= (UBIFS_BLOCKS_PER_PAGE << folio_order(folio)))
154152
break;
155153
block += 1;
156-
addr += UBIFS_BLOCK_SIZE;
157-
if (folio_test_highmem(folio) && (offset_in_page(addr) == 0)) {
158-
kunmap_local(addr - UBIFS_BLOCK_SIZE);
159-
addr = kmap_local_folio(folio, i * UBIFS_BLOCK_SIZE);
160-
}
154+
offset += UBIFS_BLOCK_SIZE;
161155
}
162156

163157
if (err) {
@@ -177,8 +171,6 @@ static int do_readpage(struct folio *folio)
177171
kfree(dn);
178172
if (!err)
179173
folio_mark_uptodate(folio);
180-
flush_dcache_folio(folio);
181-
kunmap_local(addr);
182174
return err;
183175
}
184176

@@ -602,18 +594,16 @@ static int populate_page(struct ubifs_info *c, struct folio *folio,
602594
struct inode *inode = folio->mapping->host;
603595
loff_t i_size = i_size_read(inode);
604596
unsigned int page_block;
605-
void *addr, *zaddr;
597+
size_t offset = 0;
606598
pgoff_t end_index;
607599

608600
dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx",
609601
inode->i_ino, folio->index, i_size, folio->flags);
610602

611-
addr = zaddr = kmap_local_folio(folio, 0);
612-
613603
end_index = (i_size - 1) >> PAGE_SHIFT;
614604
if (!i_size || folio->index > end_index) {
615605
hole = 1;
616-
addr = folio_zero_tail(folio, 0, addr);
606+
folio_zero_range(folio, 0, folio_size(folio));
617607
goto out_hole;
618608
}
619609

@@ -623,7 +613,7 @@ static int populate_page(struct ubifs_info *c, struct folio *folio,
623613

624614
if (nn >= bu->cnt) {
625615
hole = 1;
626-
memset(addr, 0, UBIFS_BLOCK_SIZE);
616+
folio_zero_range(folio, offset, UBIFS_BLOCK_SIZE);
627617
} else if (key_block(c, &bu->zbranch[nn].key) == page_block) {
628618
struct ubifs_data_node *dn;
629619

@@ -645,13 +635,15 @@ static int populate_page(struct ubifs_info *c, struct folio *folio,
645635
goto out_err;
646636
}
647637

648-
err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
649-
le16_to_cpu(dn->compr_type));
638+
err = ubifs_decompress_folio(
639+
c, &dn->data, dlen, folio, offset, &out_len,
640+
le16_to_cpu(dn->compr_type));
650641
if (err || len != out_len)
651642
goto out_err;
652643

653644
if (len < UBIFS_BLOCK_SIZE)
654-
memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
645+
folio_zero_range(folio, offset + len,
646+
UBIFS_BLOCK_SIZE - len);
655647

656648
nn += 1;
657649
read = (i << UBIFS_BLOCK_SHIFT) + len;
@@ -660,23 +652,19 @@ static int populate_page(struct ubifs_info *c, struct folio *folio,
660652
continue;
661653
} else {
662654
hole = 1;
663-
memset(addr, 0, UBIFS_BLOCK_SIZE);
655+
folio_zero_range(folio, offset, UBIFS_BLOCK_SIZE);
664656
}
665657
if (++i >= UBIFS_BLOCKS_PER_PAGE)
666658
break;
667-
addr += UBIFS_BLOCK_SIZE;
659+
offset += UBIFS_BLOCK_SIZE;
668660
page_block += 1;
669-
if (folio_test_highmem(folio) && (offset_in_page(addr) == 0)) {
670-
kunmap_local(addr - UBIFS_BLOCK_SIZE);
671-
addr = kmap_local_folio(folio, i * UBIFS_BLOCK_SIZE);
672-
}
673661
}
674662

675663
if (end_index == folio->index) {
676664
int len = i_size & (PAGE_SIZE - 1);
677665

678666
if (len && len < read)
679-
memset(zaddr + len, 0, read - len);
667+
folio_zero_range(folio, len, read - len);
680668
}
681669

682670
out_hole:
@@ -686,14 +674,10 @@ static int populate_page(struct ubifs_info *c, struct folio *folio,
686674
}
687675

688676
folio_mark_uptodate(folio);
689-
flush_dcache_folio(folio);
690-
kunmap_local(addr);
691677
*n = nn;
692678
return 0;
693679

694680
out_err:
695-
flush_dcache_folio(folio);
696-
kunmap_local(addr);
697681
ubifs_err(c, "bad data node (block %u, inode %lu)",
698682
page_block, inode->i_ino);
699683
return -EINVAL;
@@ -898,7 +882,6 @@ static int do_writepage(struct folio *folio, size_t len)
898882
{
899883
int err = 0, blen;
900884
unsigned int block;
901-
void *addr;
902885
size_t offset = 0;
903886
union ubifs_key key;
904887
struct inode *inode = folio->mapping->host;
@@ -913,26 +896,19 @@ static int do_writepage(struct folio *folio, size_t len)
913896

914897
folio_start_writeback(folio);
915898

916-
addr = kmap_local_folio(folio, offset);
917899
block = folio->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
918900
for (;;) {
919901
blen = min_t(size_t, len, UBIFS_BLOCK_SIZE);
920902
data_key_init(c, &key, inode->i_ino, block);
921-
err = ubifs_jnl_write_data(c, inode, &key, addr, blen);
903+
err = ubifs_jnl_write_data(c, inode, &key, folio, offset, blen);
922904
if (err)
923905
break;
924906
len -= blen;
925907
if (!len)
926908
break;
927909
block += 1;
928-
addr += blen;
929-
if (folio_test_highmem(folio) && !offset_in_page(addr)) {
930-
kunmap_local(addr - blen);
931-
offset += PAGE_SIZE;
932-
addr = kmap_local_folio(folio, offset);
933-
}
910+
offset += blen;
934911
}
935-
kunmap_local(addr);
936912
if (err) {
937913
mapping_set_error(folio->mapping, err);
938914
ubifs_err(c, "cannot write folio %lu of inode %lu, error %d",

0 commit comments

Comments
 (0)