On 5/21/25 3:31 PM, Keith Busch wrote:
+/** + * blkdev_copy - copy source sectors to a destination on the same block device + * @dst_sector: start sector of the destination to copy to + * @src_sector: start sector of the source to copy from + * @nr_sects: number of sectors to copy + * @gfp: allocation flags to use + */ +int blkdev_copy(struct block_device *bdev, sector_t dst_sector, + sector_t src_sector, sector_t nr_sects, gfp_t gfp) +{ + unsigned int nr_vecs = __blkdev_sectors_to_bio_pages(nr_sects); + unsigned int len = (unsigned int)nr_sects << SECTOR_SHIFT; + unsigned int size = min(len, nr_vecs * PAGE_SIZE); + struct bio *bio; + int ret = 0; + void *buf; + + if (nr_sects > UINT_MAX >> SECTOR_SHIFT) + return -EINVAL; + + buf = kvmalloc(size, gfp); + if (!buf) + return -ENOMEM; + + nr_vecs = bio_add_max_vecs(buf, size); + bio = bio_alloc(bdev, nr_vecs, 0, gfp); + + if (is_vmalloc_addr(buf)) + bio_add_vmalloc(bio, buf, size); + else + bio_add_virt_nofail(bio, buf, size); + + while (len) { + size = min(len, size); + + bio_reset(bio, bdev, REQ_OP_READ); + bio->bi_iter.bi_sector = src_sector; + bio->bi_iter.bi_size = size; + + ret = submit_bio_wait(bio); + if (ret) + break; + + bio_reset(bio, bdev, REQ_OP_WRITE); + bio->bi_iter.bi_sector = dst_sector; + bio->bi_iter.bi_size = size; + + ret = submit_bio_wait(bio); + if (ret) + break; + + src_sector += size >> SECTOR_SHIFT; + dst_sector += size >> SECTOR_SHIFT; + len -= size; + } + + bio_put(bio); + kvfree(buf); + return ret; +}
Is avoiding code duplication still a goal in the Linux kernel project? If so, should the above code be consolidated with kcopyd into a single implementation? Thanks, Bart.