On Tue, Feb 01, 2022 at 01:32:29PM -0500, Mikulas Patocka wrote: > +int blkdev_issue_copy(struct block_device *bdev1, sector_t sector1, > + struct block_device *bdev2, sector_t sector2, > + sector_t nr_sects, sector_t *copied, gfp_t gfp_mask) > +{ > + struct page *token; > + sector_t m; > + int r = 0; > + struct completion comp; > + > + *copied = 0; > + > + m = min(bdev_max_copy_sectors(bdev1), bdev_max_copy_sectors(bdev2)); > + if (!m) > + return -EOPNOTSUPP; > + m = min(m, (sector_t)round_down(UINT_MAX, PAGE_SIZE) >> 9); > + > + if (unlikely(bdev_read_only(bdev2))) > + return -EPERM; > + > + token = alloc_page(gfp_mask); > + if (unlikely(!token)) > + return -ENOMEM; > + > + while (nr_sects) { > + struct bio *read_bio, *write_bio; > + sector_t this_step = min(nr_sects, m); > + > + read_bio = bio_alloc(gfp_mask, 1); > + if (unlikely(!read_bio)) { > + r = -ENOMEM; > + break; > + } > + bio_set_op_attrs(read_bio, REQ_OP_COPY_READ_TOKEN, REQ_NOMERGE); > + bio_set_dev(read_bio, bdev1); > + __bio_add_page(read_bio, token, PAGE_SIZE, 0); You have this "token" payload as driver specific data, but there's no check that bdev1 and bdev2 subscribe to the same driver specific format. I thought we discussed defining something like a "copy domain" that establishes which block devices can offload copy operations to/from each other, and that should be checked before proceeding with the copy operation.