Skip to content

Commit 974b1ad

Browse files
Christoph Hellwigkdave
authored andcommitted
btrfs: use bio iterators for the decompression handlers
Pass the full bio to the decompression routines and use bio iterators to iterate over the data in the bio. Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 0c476a5 commit 974b1ad

File tree

4 files changed

+55
-112
lines changed

4 files changed

+55
-112
lines changed

fs/btrfs/compression.c

Lines changed: 42 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ struct compressed_bio {
8181
u32 sums;
8282
};
8383

84-
static int btrfs_decompress_biovec(int type, struct page **pages_in,
85-
u64 disk_start, struct bio_vec *bvec,
86-
int vcnt, size_t srclen);
84+
static int btrfs_decompress_bio(int type, struct page **pages_in,
85+
u64 disk_start, struct bio *orig_bio,
86+
size_t srclen);
8787

8888
static inline int compressed_bio_size(struct btrfs_root *root,
8989
unsigned long disk_size)
@@ -175,11 +175,10 @@ static void end_compressed_bio_read(struct bio *bio)
175175
/* ok, we're the last bio for this extent, lets start
176176
* the decompression.
177177
*/
178-
ret = btrfs_decompress_biovec(cb->compress_type,
178+
ret = btrfs_decompress_bio(cb->compress_type,
179179
cb->compressed_pages,
180180
cb->start,
181-
cb->orig_bio->bi_io_vec,
182-
cb->orig_bio->bi_vcnt,
181+
cb->orig_bio,
183182
cb->compressed_len);
184183
csum_failed:
185184
if (ret)
@@ -959,9 +958,7 @@ int btrfs_compress_pages(int type, struct address_space *mapping,
959958
*
960959
* disk_start is the starting logical offset of this array in the file
961960
*
962-
* bvec is a bio_vec of pages from the file that we want to decompress into
963-
*
964-
* vcnt is the count of pages in the biovec
961+
* orig_bio contains the pages from the file that we want to decompress into
965962
*
966963
* srclen is the number of bytes in pages_in
967964
*
@@ -970,18 +967,18 @@ int btrfs_compress_pages(int type, struct address_space *mapping,
970967
* be contiguous. They all correspond to the range of bytes covered by
971968
* the compressed extent.
972969
*/
973-
static int btrfs_decompress_biovec(int type, struct page **pages_in,
974-
u64 disk_start, struct bio_vec *bvec,
975-
int vcnt, size_t srclen)
970+
static int btrfs_decompress_bio(int type, struct page **pages_in,
971+
u64 disk_start, struct bio *orig_bio,
972+
size_t srclen)
976973
{
977974
struct list_head *workspace;
978975
int ret;
979976

980977
workspace = find_workspace(type);
981978

982-
ret = btrfs_compress_op[type-1]->decompress_biovec(workspace, pages_in,
983-
disk_start,
984-
bvec, vcnt, srclen);
979+
ret = btrfs_compress_op[type-1]->decompress_bio(workspace, pages_in,
980+
disk_start, orig_bio,
981+
srclen);
985982
free_workspace(type, workspace);
986983
return ret;
987984
}
@@ -1021,23 +1018,21 @@ void btrfs_exit_compress(void)
10211018
*/
10221019
int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
10231020
unsigned long total_out, u64 disk_start,
1024-
struct bio_vec *bvec, int vcnt,
1025-
unsigned long *pg_index,
1026-
unsigned long *pg_offset)
1021+
struct bio *bio)
10271022
{
10281023
unsigned long buf_offset;
10291024
unsigned long current_buf_start;
10301025
unsigned long start_byte;
10311026
unsigned long working_bytes = total_out - buf_start;
10321027
unsigned long bytes;
10331028
char *kaddr;
1034-
struct page *page_out = bvec[*pg_index].bv_page;
1029+
struct bio_vec bvec = bio_iter_iovec(bio, bio->bi_iter);
10351030

10361031
/*
10371032
* start byte is the first byte of the page we're currently
10381033
* copying into relative to the start of the compressed data.
10391034
*/
1040-
start_byte = page_offset(page_out) - disk_start;
1035+
start_byte = page_offset(bvec.bv_page) - disk_start;
10411036

10421037
/* we haven't yet hit data corresponding to this page */
10431038
if (total_out <= start_byte)
@@ -1057,80 +1052,46 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
10571052

10581053
/* copy bytes from the working buffer into the pages */
10591054
while (working_bytes > 0) {
1060-
bytes = min(PAGE_SIZE - *pg_offset,
1061-
PAGE_SIZE - buf_offset);
1055+
bytes = min_t(unsigned long, bvec.bv_len,
1056+
PAGE_SIZE - buf_offset);
10621057
bytes = min(bytes, working_bytes);
1063-
kaddr = kmap_atomic(page_out);
1064-
memcpy(kaddr + *pg_offset, buf + buf_offset, bytes);
1058+
1059+
kaddr = kmap_atomic(bvec.bv_page);
1060+
memcpy(kaddr + bvec.bv_offset, buf + buf_offset, bytes);
10651061
kunmap_atomic(kaddr);
1066-
flush_dcache_page(page_out);
1062+
flush_dcache_page(bvec.bv_page);
10671063

1068-
*pg_offset += bytes;
10691064
buf_offset += bytes;
10701065
working_bytes -= bytes;
10711066
current_buf_start += bytes;
10721067

10731068
/* check if we need to pick another page */
1074-
if (*pg_offset == PAGE_SIZE) {
1075-
(*pg_index)++;
1076-
if (*pg_index >= vcnt)
1077-
return 0;
1069+
bio_advance(bio, bytes);
1070+
if (!bio->bi_iter.bi_size)
1071+
return 0;
1072+
bvec = bio_iter_iovec(bio, bio->bi_iter);
10781073

1079-
page_out = bvec[*pg_index].bv_page;
1080-
*pg_offset = 0;
1081-
start_byte = page_offset(page_out) - disk_start;
1074+
start_byte = page_offset(bvec.bv_page) - disk_start;
10821075

1083-
/*
1084-
* make sure our new page is covered by this
1085-
* working buffer
1086-
*/
1087-
if (total_out <= start_byte)
1088-
return 1;
1076+
/*
1077+
* make sure our new page is covered by this
1078+
* working buffer
1079+
*/
1080+
if (total_out <= start_byte)
1081+
return 1;
10891082

1090-
/*
1091-
* the next page in the biovec might not be adjacent
1092-
* to the last page, but it might still be found
1093-
* inside this working buffer. bump our offset pointer
1094-
*/
1095-
if (total_out > start_byte &&
1096-
current_buf_start < start_byte) {
1097-
buf_offset = start_byte - buf_start;
1098-
working_bytes = total_out - start_byte;
1099-
current_buf_start = buf_start + buf_offset;
1100-
}
1083+
/*
1084+
* the next page in the biovec might not be adjacent
1085+
* to the last page, but it might still be found
1086+
* inside this working buffer. bump our offset pointer
1087+
*/
1088+
if (total_out > start_byte &&
1089+
current_buf_start < start_byte) {
1090+
buf_offset = start_byte - buf_start;
1091+
working_bytes = total_out - start_byte;
1092+
current_buf_start = buf_start + buf_offset;
11011093
}
11021094
}
11031095

11041096
return 1;
11051097
}
1106-
1107-
/*
1108-
* When uncompressing data, we need to make sure and zero any parts of
1109-
* the biovec that were not filled in by the decompression code. pg_index
1110-
* and pg_offset indicate the last page and the last offset of that page
1111-
* that have been filled in. This will zero everything remaining in the
1112-
* biovec.
1113-
*/
1114-
void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt,
1115-
unsigned long pg_index,
1116-
unsigned long pg_offset)
1117-
{
1118-
while (pg_index < vcnt) {
1119-
struct page *page = bvec[pg_index].bv_page;
1120-
unsigned long off = bvec[pg_index].bv_offset;
1121-
unsigned long len = bvec[pg_index].bv_len;
1122-
1123-
if (pg_offset < off)
1124-
pg_offset = off;
1125-
if (pg_offset < off + len) {
1126-
unsigned long bytes = off + len - pg_offset;
1127-
char *kaddr;
1128-
1129-
kaddr = kmap_atomic(page);
1130-
memset(kaddr + pg_offset, 0, bytes);
1131-
kunmap_atomic(kaddr);
1132-
}
1133-
pg_index++;
1134-
pg_offset = 0;
1135-
}
1136-
}

fs/btrfs/compression.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ int btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page,
3434
unsigned long start_byte, size_t srclen, size_t destlen);
3535
int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
3636
unsigned long total_out, u64 disk_start,
37-
struct bio_vec *bvec, int vcnt,
38-
unsigned long *pg_index,
39-
unsigned long *pg_offset);
37+
struct bio *bio);
4038

4139
int btrfs_submit_compressed_write(struct inode *inode, u64 start,
4240
unsigned long len, u64 disk_start,
@@ -45,9 +43,6 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
4543
unsigned long nr_pages);
4644
int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
4745
int mirror_num, unsigned long bio_flags);
48-
void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt,
49-
unsigned long pg_index,
50-
unsigned long pg_offset);
5146

5247
enum btrfs_compression_type {
5348
BTRFS_COMPRESS_NONE = 0,
@@ -72,11 +67,10 @@ struct btrfs_compress_op {
7267
unsigned long *total_out,
7368
unsigned long max_out);
7469

75-
int (*decompress_biovec)(struct list_head *workspace,
70+
int (*decompress_bio)(struct list_head *workspace,
7671
struct page **pages_in,
7772
u64 disk_start,
78-
struct bio_vec *bvec,
79-
int vcnt,
73+
struct bio *orig_bio,
8074
size_t srclen);
8175

8276
int (*decompress)(struct list_head *workspace,

fs/btrfs/lzo.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -254,25 +254,21 @@ static int lzo_compress_pages(struct list_head *ws,
254254
return ret;
255255
}
256256

257-
static int lzo_decompress_biovec(struct list_head *ws,
257+
static int lzo_decompress_bio(struct list_head *ws,
258258
struct page **pages_in,
259259
u64 disk_start,
260-
struct bio_vec *bvec,
261-
int vcnt,
260+
struct bio *orig_bio,
262261
size_t srclen)
263262
{
264263
struct workspace *workspace = list_entry(ws, struct workspace, list);
265264
int ret = 0, ret2;
266265
char *data_in;
267266
unsigned long page_in_index = 0;
268-
unsigned long page_out_index = 0;
269267
unsigned long total_pages_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
270268
unsigned long buf_start;
271269
unsigned long buf_offset = 0;
272270
unsigned long bytes;
273271
unsigned long working_bytes;
274-
unsigned long pg_offset;
275-
276272
size_t in_len;
277273
size_t out_len;
278274
unsigned long in_offset;
@@ -292,7 +288,6 @@ static int lzo_decompress_biovec(struct list_head *ws,
292288
in_page_bytes_left = PAGE_SIZE - LZO_LEN;
293289

294290
tot_out = 0;
295-
pg_offset = 0;
296291

297292
while (tot_in < tot_len) {
298293
in_len = read_compress_length(data_in + in_offset);
@@ -365,16 +360,14 @@ static int lzo_decompress_biovec(struct list_head *ws,
365360
tot_out += out_len;
366361

367362
ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
368-
tot_out, disk_start,
369-
bvec, vcnt,
370-
&page_out_index, &pg_offset);
363+
tot_out, disk_start, orig_bio);
371364
if (ret2 == 0)
372365
break;
373366
}
374367
done:
375368
kunmap(pages_in[page_in_index]);
376369
if (!ret)
377-
btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset);
370+
zero_fill_bio(orig_bio);
378371
return ret;
379372
}
380373

@@ -438,6 +431,6 @@ const struct btrfs_compress_op btrfs_lzo_compress = {
438431
.alloc_workspace = lzo_alloc_workspace,
439432
.free_workspace = lzo_free_workspace,
440433
.compress_pages = lzo_compress_pages,
441-
.decompress_biovec = lzo_decompress_biovec,
434+
.decompress_bio = lzo_decompress_bio,
442435
.decompress = lzo_decompress,
443436
};

fs/btrfs/zlib.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,9 @@ static int zlib_compress_pages(struct list_head *ws,
210210
return ret;
211211
}
212212

213-
static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
213+
static int zlib_decompress_bio(struct list_head *ws, struct page **pages_in,
214214
u64 disk_start,
215-
struct bio_vec *bvec,
216-
int vcnt,
215+
struct bio *orig_bio,
217216
size_t srclen)
218217
{
219218
struct workspace *workspace = list_entry(ws, struct workspace, list);
@@ -222,10 +221,8 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
222221
char *data_in;
223222
size_t total_out = 0;
224223
unsigned long page_in_index = 0;
225-
unsigned long page_out_index = 0;
226224
unsigned long total_pages_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
227225
unsigned long buf_start;
228-
unsigned long pg_offset;
229226

230227
data_in = kmap(pages_in[page_in_index]);
231228
workspace->strm.next_in = data_in;
@@ -235,7 +232,6 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
235232
workspace->strm.total_out = 0;
236233
workspace->strm.next_out = workspace->buf;
237234
workspace->strm.avail_out = PAGE_SIZE;
238-
pg_offset = 0;
239235

240236
/* If it's deflate, and it's got no preset dictionary, then
241237
we can tell zlib to skip the adler32 check. */
@@ -267,8 +263,7 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
267263

268264
ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
269265
total_out, disk_start,
270-
bvec, vcnt,
271-
&page_out_index, &pg_offset);
266+
orig_bio);
272267
if (ret2 == 0) {
273268
ret = 0;
274269
goto done;
@@ -301,7 +296,7 @@ static int zlib_decompress_biovec(struct list_head *ws, struct page **pages_in,
301296
if (data_in)
302297
kunmap(pages_in[page_in_index]);
303298
if (!ret)
304-
btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset);
299+
zero_fill_bio(orig_bio);
305300
return ret;
306301
}
307302

@@ -408,6 +403,6 @@ const struct btrfs_compress_op btrfs_zlib_compress = {
408403
.alloc_workspace = zlib_alloc_workspace,
409404
.free_workspace = zlib_free_workspace,
410405
.compress_pages = zlib_compress_pages,
411-
.decompress_biovec = zlib_decompress_biovec,
406+
.decompress_bio = zlib_decompress_bio,
412407
.decompress = zlib_decompress,
413408
};

0 commit comments

Comments
 (0)