Message ID | 20210817101423.12367-6-selvakuma.s1@samsung.com |
---|---|
State | New |
Headers | show |
Series | add simple copy support | expand |
Hi SelvaKumar, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on block/for-next] [also build test WARNING on dm/for-next next-20210817] [cannot apply to linus/master linux-nvme/for-next v5.14-rc6] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/SelvaKumar-S/block-make-bio_map_kern-non-static/20210817-193111 base: https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next config: hexagon-randconfig-r013-20210816 (attached as .config) compiler: clang version 12.0.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/c307f1051a72122d636502c6885df8b2b25ed697 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review SelvaKumar-S/block-make-bio_map_kern-non-static/20210817-193111 git checkout c307f1051a72122d636502c6885df8b2b25ed697 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=hexagon If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): block/blk-lib.c:197:5: warning: no previous prototype for function 'blk_copy_offload_submit_bio' [-Wmissing-prototypes] int blk_copy_offload_submit_bio(struct block_device *bdev, ^ block/blk-lib.c:197:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int blk_copy_offload_submit_bio(struct block_device *bdev, ^ static block/blk-lib.c:250:5: warning: no previous prototype for function 'blk_copy_offload_scc' [-Wmissing-prototypes] int blk_copy_offload_scc(struct block_device *src_bdev, int nr_srcs, ^ block/blk-lib.c:250:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int blk_copy_offload_scc(struct block_device *src_bdev, int nr_srcs, ^ static >> block/blk-lib.c:336:5: warning: no previous prototype for function 'blk_submit_rw_buf' [-Wmissing-prototypes] int blk_submit_rw_buf(struct block_device *bdev, void *buf, sector_t buf_len, ^ block/blk-lib.c:336:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int blk_submit_rw_buf(struct block_device *bdev, void *buf, sector_t buf_len, ^ static 3 warnings generated. vim +/blk_submit_rw_buf +336 block/blk-lib.c 335 > 336 int blk_submit_rw_buf(struct block_device *bdev, void *buf, sector_t buf_len, 337 sector_t sector, unsigned int op, gfp_t gfp_mask) 338 { 339 struct request_queue *q = bdev_get_queue(bdev); 340 struct bio *bio, *parent = NULL; 341 sector_t max_hw_len = min_t(unsigned int, queue_max_hw_sectors(q), 342 queue_max_segments(q) << (PAGE_SHIFT - SECTOR_SHIFT)); 343 sector_t len, remaining; 344 int ret; 345 346 for (remaining = buf_len; remaining > 0; remaining -= len) { 347 len = min_t(int, max_hw_len, remaining); 348 retry: 349 bio = bio_map_kern(q, buf, len << SECTOR_SHIFT, gfp_mask); 350 if (IS_ERR(bio)) { 351 len >>= 1; 352 if (len) 353 goto retry; 354 return PTR_ERR(bio); 355 } 356 357 bio->bi_iter.bi_sector = sector; 358 bio->bi_opf = op; 359 bio_set_dev(bio, bdev); 360 bio->bi_end_io = NULL; 361 bio->bi_private = NULL; 362 363 if (parent) { 364 bio_chain(parent, bio); 365 submit_bio(parent); 366 } 367 parent = bio; 368 sector += len; 369 } 370 ret = submit_bio_wait(bio); 371 bio_put(bio); 372 373 return ret; 374 } 375 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/block/blk-lib.c b/block/blk-lib.c index 7fee0ae95c44..d29c52b90dcf 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -333,6 +333,64 @@ int blk_copy_offload_scc(struct block_device *src_bdev, int nr_srcs, return ret; } +int blk_submit_rw_buf(struct block_device *bdev, void *buf, sector_t buf_len, + sector_t sector, unsigned int op, gfp_t gfp_mask) +{ + struct request_queue *q = bdev_get_queue(bdev); + struct bio *bio, *parent = NULL; + sector_t max_hw_len = min_t(unsigned int, queue_max_hw_sectors(q), + queue_max_segments(q) << (PAGE_SHIFT - SECTOR_SHIFT)); + sector_t len, remaining; + int ret; + + for (remaining = buf_len; remaining > 0; remaining -= len) { + len = min_t(int, max_hw_len, remaining); +retry: + bio = bio_map_kern(q, buf, len << SECTOR_SHIFT, gfp_mask); + if (IS_ERR(bio)) { + len >>= 1; + if (len) + goto retry; + return PTR_ERR(bio); + } + + bio->bi_iter.bi_sector = sector; + bio->bi_opf = op; + bio_set_dev(bio, bdev); + bio->bi_end_io = NULL; + bio->bi_private = NULL; + + if (parent) { + bio_chain(parent, bio); + submit_bio(parent); + } + parent = bio; + sector += len; + } + ret = submit_bio_wait(bio); + bio_put(bio); + + return ret; +} + +static void *blk_alloc_buf(sector_t req_size, sector_t *alloc_size, gfp_t gfp_mask) +{ + int min_size = PAGE_SIZE; + void *buf; + + while (req_size >= min_size) { + buf = kvmalloc(req_size, gfp_mask); + if (buf) { + *alloc_size = (req_size >> SECTOR_SHIFT); + return buf; + } + /* retry half the requested size */ + req_size >>= 1; + } + + return NULL; +} + static inline sector_t blk_copy_len(struct range_entry *rlist, int nr_srcs) { int i; @@ -348,6 +406,46 @@ static inline sector_t blk_copy_len(struct range_entry *rlist, int nr_srcs) return len; } +/* + * If native copy offload feature is absent, this function tries to emulate, + * by copying data from source to a temporary buffer and from buffer to + * destination device. + */ +static int blk_copy_emulate(struct block_device *src_bdev, int nr_srcs, + struct range_entry *rlist, struct block_device *dest_bdev, + sector_t dest, gfp_t gfp_mask) +{ + void *buf = NULL; + int ret, nr_i = 0; + sector_t src_blk, copy_len, buf_len, read_len, copied_len, remaining = 0; + + copy_len = blk_copy_len(rlist, nr_srcs); + buf = blk_alloc_buf(copy_len << SECTOR_SHIFT, &buf_len, gfp_mask); + if (!buf) + return -ENOMEM; + + for (copied_len = 0; copied_len < copy_len; copied_len += read_len) { + if (!remaining) { + src_blk = rlist[nr_i].src; + remaining = rlist[nr_i++].len; + } + + read_len = min_t(sector_t, remaining, buf_len); + ret = blk_submit_rw_buf(src_bdev, buf, read_len, src_blk, REQ_OP_READ, gfp_mask); + if (ret) + goto out; + src_blk += read_len; + remaining -= read_len; + ret = blk_submit_rw_buf(dest_bdev, buf, read_len, dest + copied_len, REQ_OP_WRITE, + gfp_mask); + if (ret) + goto out; + } +out: + kvfree(buf); + return ret; +} + static inline bool blk_check_offload_scc(struct request_queue *src_q, struct request_queue *dest_q) { @@ -398,6 +496,8 @@ int blkdev_issue_copy(struct block_device *src_bdev, int nr_srcs, if (blk_check_offload_scc(src_q, dest_q)) ret = blk_copy_offload_scc(src_bdev, nr_srcs, src_rlist, dest_bdev, dest, gfp_mask); + else + ret = blk_copy_emulate(src_bdev, nr_srcs, src_rlist, dest_bdev, dest, gfp_mask); return ret; }