On Wed, Nov 16, 2016 at 01:52:08PM +0100, Christoph Hellwig wrote:
> Pass the full bio to the decompression routines and use bio iterators
> to iterate over the data in the bio.

One question below,

> 
> Signed-off-by: Christoph Hellwig <h...@lst.de>
> ---
>  fs/btrfs/compression.c | 122 
> +++++++++++++++++--------------------------------
>  fs/btrfs/compression.h |  12 ++---
>  fs/btrfs/lzo.c         |  17 ++-----
>  fs/btrfs/zlib.c        |  15 ++----
>  4 files changed, 54 insertions(+), 112 deletions(-)
> 
> diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
> index d4d8b7e..12a631d 100644
> --- a/fs/btrfs/compression.c
> +++ b/fs/btrfs/compression.c
> @@ -81,9 +81,9 @@ struct compressed_bio {
>       u32 sums;
>  };
>  
> -static int btrfs_decompress_biovec(int type, struct page **pages_in,
> -                                u64 disk_start, struct bio_vec *bvec,
> -                                int vcnt, size_t srclen);
> +static int btrfs_decompress_bio(int type, struct page **pages_in,
> +                                u64 disk_start, struct bio *orig_bio,
> +                                size_t srclen);
>  
>  static inline int compressed_bio_size(struct btrfs_root *root,
>                                     unsigned long disk_size)
> @@ -175,11 +175,10 @@ static void end_compressed_bio_read(struct bio *bio)
>       /* ok, we're the last bio for this extent, lets start
>        * the decompression.
>        */
> -     ret = btrfs_decompress_biovec(cb->compress_type,
> +     ret = btrfs_decompress_bio(cb->compress_type,
>                                     cb->compressed_pages,
>                                     cb->start,
> -                                   cb->orig_bio->bi_io_vec,
> -                                   cb->orig_bio->bi_vcnt,
> +                                   cb->orig_bio,
>                                     cb->compressed_len);
>  csum_failed:
>       if (ret)
> @@ -959,9 +958,7 @@ int btrfs_compress_pages(int type, struct address_space 
> *mapping,
>   *
>   * disk_start is the starting logical offset of this array in the file
>   *
> - * bvec is a bio_vec of pages from the file that we want to decompress into
> - *
> - * vcnt is the count of pages in the biovec
> + * orig_bio contains the pages from the file that we want to decompress into
>   *
>   * srclen is the number of bytes in pages_in
>   *
> @@ -970,18 +967,18 @@ int btrfs_compress_pages(int type, struct address_space 
> *mapping,
>   * be contiguous.  They all correspond to the range of bytes covered by
>   * the compressed extent.
>   */
> -static int btrfs_decompress_biovec(int type, struct page **pages_in,
> -                                u64 disk_start, struct bio_vec *bvec,
> -                                int vcnt, size_t srclen)
> +static int btrfs_decompress_bio(int type, struct page **pages_in,
> +                                u64 disk_start, struct bio *orig_bio,
> +                                size_t srclen)
>  {
>       struct list_head *workspace;
>       int ret;
>  
>       workspace = find_workspace(type);
>  
> -     ret = btrfs_compress_op[type-1]->decompress_biovec(workspace, pages_in,
> -                                                      disk_start,
> -                                                      bvec, vcnt, srclen);
> +     ret = btrfs_compress_op[type-1]->decompress_bio(workspace, pages_in,
> +                                                      disk_start, orig_bio,
> +                                                      srclen);
>       free_workspace(type, workspace);
>       return ret;
>  }
> @@ -1021,9 +1018,7 @@ void btrfs_exit_compress(void)
>   */
>  int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
>                             unsigned long total_out, u64 disk_start,
> -                           struct bio_vec *bvec, int vcnt,
> -                           unsigned long *pg_index,
> -                           unsigned long *pg_offset)
> +                           struct bio *bio)
>  {
>       unsigned long buf_offset;
>       unsigned long current_buf_start;
> @@ -1031,13 +1026,13 @@ int btrfs_decompress_buf2page(char *buf, unsigned 
> long buf_start,
>       unsigned long working_bytes = total_out - buf_start;
>       unsigned long bytes;
>       char *kaddr;
> -     struct page *page_out = bvec[*pg_index].bv_page;
> +     struct bio_vec bvec = bio_iter_iovec(bio, bio->bi_iter);
>  
>       /*
>        * start byte is the first byte of the page we're currently
>        * copying into relative to the start of the compressed data.
>        */
> -     start_byte = page_offset(page_out) - disk_start;
> +     start_byte = page_offset(bvec.bv_page) - disk_start;
>  
>       /* we haven't yet hit data corresponding to this page */
>       if (total_out <= start_byte)
> @@ -1057,80 +1052,45 @@ int btrfs_decompress_buf2page(char *buf, unsigned 
> long buf_start,
>  
>       /* copy bytes from the working buffer into the pages */
>       while (working_bytes > 0) {
> -             bytes = min(PAGE_SIZE - *pg_offset,
> -                         PAGE_SIZE - buf_offset);
> +             bytes = min_t(unsigned long, bvec.bv_len,
> +                             PAGE_SIZE - buf_offset);
>               bytes = min(bytes, working_bytes);
> -             kaddr = kmap_atomic(page_out);
> -             memcpy(kaddr + *pg_offset, buf + buf_offset, bytes);
> +
> +             kaddr = kmap_atomic(bvec.bv_page);
> +             memcpy(kaddr + bvec.bv_offset, buf + buf_offset, bytes);

This doesn't seem to be right, 'bvec.bv_offset' is not updated in the
following bio_advance(bio, bytes), shouldn't it be 
'kaddr + bvec.bv_offset + bio->bi_iter.bi_bvec_done'?

Others look good.

Thanks,

-liubo
>               kunmap_atomic(kaddr);
> -             flush_dcache_page(page_out);
> +             flush_dcache_page(bvec.bv_page);
>  
> -             *pg_offset += bytes;
>               buf_offset += bytes;
>               working_bytes -= bytes;
>               current_buf_start += bytes;
>  
>               /* check if we need to pick another page */
> -             if (*pg_offset == PAGE_SIZE) {
> -                     (*pg_index)++;
> -                     if (*pg_index >= vcnt)
> -                             return 0;
> +             bio_advance(bio, bytes);
> +             if (!bio->bi_iter.bi_size)
> +                     return 0;
>  
> -                     page_out = bvec[*pg_index].bv_page;
> -                     *pg_offset = 0;
> -                     start_byte = page_offset(page_out) - disk_start;
> +             start_byte = page_offset(bvec.bv_page) - disk_start;
>  
> -                     /*
> -                      * make sure our new page is covered by this
> -                      * working buffer
> -                      */
> -                     if (total_out <= start_byte)
> -                             return 1;
> +             /*
> +              * make sure our new page is covered by this
> +              * working buffer
> +              */
> +             if (total_out <= start_byte)
> +                     return 1;
>  
> -                     /*
> -                      * the next page in the biovec might not be adjacent
> -                      * to the last page, but it might still be found
> -                      * inside this working buffer. bump our offset pointer
> -                      */
> -                     if (total_out > start_byte &&
> -                         current_buf_start < start_byte) {
> -                             buf_offset = start_byte - buf_start;
> -                             working_bytes = total_out - start_byte;
> -                             current_buf_start = buf_start + buf_offset;
> -                     }
> +             /*
> +              * the next page in the biovec might not be adjacent
> +              * to the last page, but it might still be found
> +              * inside this working buffer. bump our offset pointer
> +              */
> +             if (total_out > start_byte &&
> +                 current_buf_start < start_byte) {
> +                     buf_offset = start_byte - buf_start;
> +                     working_bytes = total_out - start_byte;
> +                     current_buf_start = buf_start + buf_offset;
>               }
>       }
>  
>       return 1;
>  }
> -
> -/*
> - * When uncompressing data, we need to make sure and zero any parts of
> - * the biovec that were not filled in by the decompression code.  pg_index
> - * and pg_offset indicate the last page and the last offset of that page
> - * that have been filled in.  This will zero everything remaining in the
> - * biovec.
> - */
> -void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt,
> -                                unsigned long pg_index,
> -                                unsigned long pg_offset)
> -{
> -     while (pg_index < vcnt) {
> -             struct page *page = bvec[pg_index].bv_page;
> -             unsigned long off = bvec[pg_index].bv_offset;
> -             unsigned long len = bvec[pg_index].bv_len;
> -
> -             if (pg_offset < off)
> -                     pg_offset = off;
> -             if (pg_offset < off + len) {
> -                     unsigned long bytes = off + len - pg_offset;
> -                     char *kaddr;
> -
> -                     kaddr = kmap_atomic(page);
> -                     memset(kaddr + pg_offset, 0, bytes);
> -                     kunmap_atomic(kaddr);
> -             }
> -             pg_index++;
> -             pg_offset = 0;
> -     }
> -}
> diff --git a/fs/btrfs/compression.h b/fs/btrfs/compression.h
> index f49d8b8..0987957 100644
> --- a/fs/btrfs/compression.h
> +++ b/fs/btrfs/compression.h
> @@ -34,9 +34,7 @@ int btrfs_decompress(int type, unsigned char *data_in, 
> struct page *dest_page,
>                    unsigned long start_byte, size_t srclen, size_t destlen);
>  int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
>                             unsigned long total_out, u64 disk_start,
> -                           struct bio_vec *bvec, int vcnt,
> -                           unsigned long *pg_index,
> -                           unsigned long *pg_offset);
> +                           struct bio *bio);
>  
>  int btrfs_submit_compressed_write(struct inode *inode, u64 start,
>                                 unsigned long len, u64 disk_start,
> @@ -45,9 +43,6 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 
> start,
>                                 unsigned long nr_pages);
>  int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
>                                int mirror_num, unsigned long bio_flags);
> -void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt,
> -                                unsigned long pg_index,
> -                                unsigned long pg_offset);
>  
>  enum btrfs_compression_type {
>       BTRFS_COMPRESS_NONE  = 0,
> @@ -72,11 +67,10 @@ struct btrfs_compress_op {
>                             unsigned long *total_out,
>                             unsigned long max_out);
>  
> -     int (*decompress_biovec)(struct list_head *workspace,
> +     int (*decompress_bio)(struct list_head *workspace,
>                                struct page **pages_in,
>                                u64 disk_start,
> -                              struct bio_vec *bvec,
> -                              int vcnt,
> +                              struct bio *orig_bio,
>                                size_t srclen);
>  
>       int (*decompress)(struct list_head *workspace,
> diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
> index 48655da..45d2698 100644
> --- a/fs/btrfs/lzo.c
> +++ b/fs/btrfs/lzo.c
> @@ -254,25 +254,21 @@ static int lzo_compress_pages(struct list_head *ws,
>       return ret;
>  }
>  
> -static int lzo_decompress_biovec(struct list_head *ws,
> +static int lzo_decompress_bio(struct list_head *ws,
>                                struct page **pages_in,
>                                u64 disk_start,
> -                              struct bio_vec *bvec,
> -                              int vcnt,
> +                              struct bio *orig_bio,
>                                size_t srclen)
>  {
>       struct workspace *workspace = list_entry(ws, struct workspace, list);
>       int ret = 0, ret2;
>       char *data_in;
>       unsigned long page_in_index = 0;
> -     unsigned long page_out_index = 0;
>       unsigned long total_pages_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
>       unsigned long buf_start;
>       unsigned long buf_offset = 0;
>       unsigned long bytes;
>       unsigned long working_bytes;
> -     unsigned long pg_offset;
> -
>       size_t in_len;
>       size_t out_len;
>       unsigned long in_offset;
> @@ -292,7 +288,6 @@ static int lzo_decompress_biovec(struct list_head *ws,
>       in_page_bytes_left = PAGE_SIZE - LZO_LEN;
>  
>       tot_out = 0;
> -     pg_offset = 0;
>  
>       while (tot_in < tot_len) {
>               in_len = read_compress_length(data_in + in_offset);
> @@ -365,16 +360,14 @@ static int lzo_decompress_biovec(struct list_head *ws,
>               tot_out += out_len;
>  
>               ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
> -                                              tot_out, disk_start,
> -                                              bvec, vcnt,
> -                                              &page_out_index, &pg_offset);
> +                                              tot_out, disk_start, orig_bio);
>               if (ret2 == 0)
>                       break;
>       }
>  done:
>       kunmap(pages_in[page_in_index]);
>       if (!ret)
> -             btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset);
> +             zero_fill_bio(orig_bio);
>       return ret;
>  }
>  
> @@ -438,6 +431,6 @@ const struct btrfs_compress_op btrfs_lzo_compress = {
>       .alloc_workspace        = lzo_alloc_workspace,
>       .free_workspace         = lzo_free_workspace,
>       .compress_pages         = lzo_compress_pages,
> -     .decompress_biovec      = lzo_decompress_biovec,
> +     .decompress_bio         = lzo_decompress_bio,
>       .decompress             = lzo_decompress,
>  };
> diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c
> index 441b81a..0d5f28e 100644
> --- a/fs/btrfs/zlib.c
> +++ b/fs/btrfs/zlib.c
> @@ -210,10 +210,9 @@ static int zlib_compress_pages(struct list_head *ws,
>       return ret;
>  }
>  
> -static int zlib_decompress_biovec(struct list_head *ws, struct page 
> **pages_in,
> +static int zlib_decompress_bio(struct list_head *ws, struct page **pages_in,
>                                 u64 disk_start,
> -                               struct bio_vec *bvec,
> -                               int vcnt,
> +                               struct bio *orig_bio,
>                                 size_t srclen)
>  {
>       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,
>       char *data_in;
>       size_t total_out = 0;
>       unsigned long page_in_index = 0;
> -     unsigned long page_out_index = 0;
>       unsigned long total_pages_in = DIV_ROUND_UP(srclen, PAGE_SIZE);
>       unsigned long buf_start;
> -     unsigned long pg_offset;
>  
>       data_in = kmap(pages_in[page_in_index]);
>       workspace->strm.next_in = data_in;
> @@ -235,7 +232,6 @@ static int zlib_decompress_biovec(struct list_head *ws, 
> struct page **pages_in,
>       workspace->strm.total_out = 0;
>       workspace->strm.next_out = workspace->buf;
>       workspace->strm.avail_out = PAGE_SIZE;
> -     pg_offset = 0;
>  
>       /* If it's deflate, and it's got no preset dictionary, then
>          we can tell zlib to skip the adler32 check. */
> @@ -266,8 +262,7 @@ static int zlib_decompress_biovec(struct list_head *ws, 
> struct page **pages_in,
>  
>               ret2 = btrfs_decompress_buf2page(workspace->buf, buf_start,
>                                                total_out, disk_start,
> -                                              bvec, vcnt,
> -                                              &page_out_index, &pg_offset);
> +                                              orig_bio);
>               if (ret2 == 0) {
>                       ret = 0;
>                       goto done;
> @@ -300,7 +295,7 @@ static int zlib_decompress_biovec(struct list_head *ws, 
> struct page **pages_in,
>       if (data_in)
>               kunmap(pages_in[page_in_index]);
>       if (!ret)
> -             btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset);
> +             zero_fill_bio(orig_bio);
>       return ret;
>  }
>  
> @@ -407,6 +402,6 @@ const struct btrfs_compress_op btrfs_zlib_compress = {
>       .alloc_workspace        = zlib_alloc_workspace,
>       .free_workspace         = zlib_free_workspace,
>       .compress_pages         = zlib_compress_pages,
> -     .decompress_biovec      = zlib_decompress_biovec,
> +     .decompress_bio         = zlib_decompress_bio,
>       .decompress             = zlib_decompress,
>  };
> -- 
> 2.1.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to