Re: [PATCH 0/5] block: another block copy offload

Niklas Cassel
2025-07-03T14:47:45Z

Hello Keith,

On Wed, May 21, 2025 at 03:31:02PM -0700, Keith Busch wrote:
> From: Keith Busch <kbusch@kernel.org>
>
> I was never happy with previous block copy offload attempts, so I had to
> take a stab at it. And I was recently asked to take a look at this, so
> here goes.
>
> Some key implementation differences from previous approaches:
>
> 1. Only one bio is needed to describe a copy request, so no plugging
> or dispatch tricks required. Like read and write requests, these
> can be artbitrarily large and will be split as needed based on the
> request_queue's limits. The bio's are mergeable with other copy
> commands on adjacent destination sectors.
>
> 2. You can describe as many source sectors as you want in a vector in
> a single bio. This aligns with the nvme protocol's Copy implementation,
> which can be used to efficiently defragment scattered blocks into a
> contiguous destination with a single command.
>
> Oh, and the nvme-target support was included with this patchset too, so
> there's a purely in-kernel way to test out the code paths if you don't
> have otherwise capable hardware. I also used qemu since that nvme device
> supports copy offload too.

In order to test this series, I wrote a simple user space program to test
that does:

1) open() on the raw block device, without O_DIRECT.
2) pwrite() to a few sectors with some non-zero data.
3) pread() to those sectors, to make sure that the data was written, it was.

Since I haven't done any fsync(), both the read and the write will from/to
the page cache.

4) ioctl(.., BLKCPY_VEC, ..)

5) pread() on destination sector.

In step 5, I will read zero data.
I understand that BLKCPY_VEC is a copy offload command.

However, if I simply add an fsync() after the pwrite()s, then I will read
non-zero data in step 5, as expecting.

My question: is it expected that ioctl(.., BLKCPY_VEC, ..) will bypass/ignore
the page cache?

Because, as far as I understand, the most common thing for BLK* operations
is to do take the page cache into account, e.g. while BLKRESETZONE sends
down a command to the device, it also invalidates the corresponding pages
from the page cache.

With that logic, should ioctl(.., BLKCPY_VEC, ..) make sure that the src
pages are flushed down to the devices, before sending down the actual
copy command to the device?

I think that it is fine that the command ignores the data in the page cache,
since I guess in most cases, you will have a file system that is responsible
for the sectors being in sync, but perhaps we should document BLKCPY_VEC and
BLKCPY to more clearly highlight that they will bypass the page cache?

Which also makes me think, for storage devices that do not have a copy
command, blkdev_copy_range() will fall back to __blkdev_copy().
So in that case, I assume that the copy ioctl actually will take the page
cache into account?

Kind regards,
Niklas