Re: [PATCH 1/5] block: new sector copy api

Bart Van Assche
2025-05-22T19:29:14Z

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.