mbox series

[PATCHv10,0/9] write hints with nvme fdp, scsi streams

Message ID 20241029151922.459139-1-kbusch@meta.com (mailing list archive)
Headers show
Series write hints with nvme fdp, scsi streams | expand

Message

Keith Busch Oct. 29, 2024, 3:19 p.m. UTC
From: Keith Busch <kbusch@kernel.org>

Changes from v9:

  Document the partition hint mask

  Use bitmap_alloc API

  Fixup bitmap memory leak

  Return invalid value if user requests an invalid write hint

  Added and exported a block device feature flag for indicating generic
  placement hint support

  Added statx write hint max field

  Added BUILD_BUG_ON check for new io_uring SQE fields.

  Added reviews

Kanchan Joshi (2):
  io_uring: enable per-io hinting capability
  nvme: enable FDP support

Keith Busch (7):
  block: use generic u16 for write hints
  block: introduce max_write_hints queue limit
  statx: add write hint information
  block: allow ability to limit partition write hints
  block, fs: add write hint to kiocb
  block: export placement hint feature
  scsi: set permanent stream count in block limits

 Documentation/ABI/stable/sysfs-block | 13 +++++
 block/bdev.c                         | 18 ++++++
 block/blk-settings.c                 |  5 ++
 block/blk-sysfs.c                    |  6 ++
 block/fops.c                         | 31 +++++++++-
 block/partitions/core.c              | 44 ++++++++++++++-
 drivers/nvme/host/core.c             | 84 ++++++++++++++++++++++++++++
 drivers/nvme/host/nvme.h             |  5 ++
 drivers/scsi/sd.c                    |  2 +
 fs/stat.c                            |  1 +
 include/linux/blk-mq.h               |  3 +-
 include/linux/blk_types.h            |  4 +-
 include/linux/blkdev.h               | 15 +++++
 include/linux/fs.h                   |  1 +
 include/linux/nvme.h                 | 19 +++++++
 include/linux/stat.h                 |  1 +
 include/uapi/linux/io_uring.h        |  4 ++
 include/uapi/linux/stat.h            |  3 +-
 io_uring/io_uring.c                  |  2 +
 io_uring/rw.c                        |  3 +-
 20 files changed, 253 insertions(+), 11 deletions(-)

Comments

Christoph Hellwig Oct. 29, 2024, 3:24 p.m. UTC | #1
On Tue, Oct 29, 2024 at 08:19:13AM -0700, Keith Busch wrote:
>   Return invalid value if user requests an invalid write hint
> 
>   Added and exported a block device feature flag for indicating generic
>   placement hint support

But it still talks of write hints everywhere and conflates the write
streams with the temperature hints which are completely different
beasts.
Christoph Hellwig Nov. 5, 2024, 3:50 p.m. UTC | #2
I've pushed my branch that tries to make this work with the XFS
data separation here:

http://git.infradead.org/?p=users/hch/xfs.git;a=shortlog;h=refs/heads/xfs-zoned-streams

This is basically my current WIP xfs zoned (aka always write out place)
work optimistically destined for 6.14 + the patch set in this thread +
a little fix to make it work for nvme-multipath plus the tiny patch to
wire it up.

The good news is that the API from Keith mostly works.  I don't really
know how to cope with the streams per partition bitmap, and I suspect
this will need to be dealt with a bit better.  One option might be
to always have a bitmap, which would also support discontiguous
write stream numbers as actually supported by the underlying NVMe
implementation, another option would be to always map to consecutive
numbers.

The bad news is that for file systems or applications to make full use
of the API we also really need an API to expose how much space is left
in a write stream, as otherwise they can easily get out of sync on
a power fail.  I've left that code in as a TODO, it should not affect
basic testing.

We get the same kind of performance numbers as the ZNS support on
comparable hardware platforms, which is expected.  Testing on an
actual state of the art non-prototype hardware will take more time
as the capacities are big enough that getting serious numbers will
take a lot more time.
Keith Busch Nov. 6, 2024, 6:36 p.m. UTC | #3
On Tue, Nov 05, 2024 at 04:50:14PM +0100, Christoph Hellwig wrote:
> I've pushed my branch that tries to make this work with the XFS
> data separation here:
> 
> http://git.infradead.org/?p=users/hch/xfs.git;a=shortlog;h=refs/heads/xfs-zoned-streams
> 
> This is basically my current WIP xfs zoned (aka always write out place)
> work optimistically destined for 6.14 + the patch set in this thread +
> a little fix to make it work for nvme-multipath plus the tiny patch to
> wire it up.
> 
> The good news is that the API from Keith mostly works.  I don't really
> know how to cope with the streams per partition bitmap, and I suspect
> this will need to be dealt with a bit better.  One option might be
> to always have a bitmap, which would also support discontiguous
> write stream numbers as actually supported by the underlying NVMe
> implementation, another option would be to always map to consecutive
> numbers.

Thanks for sharing that. Seeing the code makes it much easier to
understand where you're trying to steer this. I'll take a look and
probably have some feedback after a couple days going through it.
Keith Busch Nov. 7, 2024, 8:36 p.m. UTC | #4
On Tue, Nov 05, 2024 at 04:50:14PM +0100, Christoph Hellwig wrote:
> I've pushed my branch that tries to make this work with the XFS
> data separation here:
> 
> http://git.infradead.org/?p=users/hch/xfs.git;a=shortlog;h=refs/heads/xfs-zoned-streams

The zone block support all looks pretty neat, but I think you're making
this harder than necessary to support streams. You don't need to treat
these like a sequential write device. The controller side does its own
garbage collection, so no need to duplicate the effort on the host. And
it looks like the host side gc potentially merges multiple streams into
a single gc stream, so that's probably not desirable.
Christoph Hellwig Nov. 8, 2024, 2:18 p.m. UTC | #5
On Thu, Nov 07, 2024 at 01:36:35PM -0700, Keith Busch wrote:
> The zone block support all looks pretty neat, but I think you're making
> this harder than necessary to support streams. You don't need to treat
> these like a sequential write device. The controller side does its own
> garbage collection, so no need to duplicate the effort on the host. And
> it looks like the host side gc potentially merges multiple streams into
> a single gc stream, so that's probably not desirable.

We're not really duplicating much.  Writing sequential is pretty easy,
and tracking reclaim units separately means you need another tracking
data structure, and either that or the LBA one is always going to be
badly fragmented if they aren't the same.
Keith Busch Nov. 8, 2024, 3:51 p.m. UTC | #6
On Fri, Nov 08, 2024 at 03:18:52PM +0100, Christoph Hellwig wrote:
> On Thu, Nov 07, 2024 at 01:36:35PM -0700, Keith Busch wrote:
> > The zone block support all looks pretty neat, but I think you're making
> > this harder than necessary to support streams. You don't need to treat
> > these like a sequential write device. The controller side does its own
> > garbage collection, so no need to duplicate the effort on the host. And
> > it looks like the host side gc potentially merges multiple streams into
> > a single gc stream, so that's probably not desirable.
> 
> We're not really duplicating much.  Writing sequential is pretty easy,
> and tracking reclaim units separately means you need another tracking
> data structure, and either that or the LBA one is always going to be
> badly fragmented if they aren't the same.

You're getting fragmentation anyway, which is why you had to implement
gc. You're just shifting who gets to deal with it from the controller to
the host. The host is further from the media, so you're starting from a
disadvantage. The host gc implementation would have to be quite a bit
better to justify the link and memory usage necessary for the copies
(...queue a copy-offload discussion? oom?).

This xfs implementation also has logic to recover from a power fail. The
device already does that if you use the LBA abstraction instead of
tracking sequential write pointers and free blocks.

I think you are underestimating the duplication of efforts going on
here.
Matthew Wilcox Nov. 8, 2024, 4:54 p.m. UTC | #7
On Fri, Nov 08, 2024 at 08:51:31AM -0700, Keith Busch wrote:
> On Fri, Nov 08, 2024 at 03:18:52PM +0100, Christoph Hellwig wrote:
> > We're not really duplicating much.  Writing sequential is pretty easy,
> > and tracking reclaim units separately means you need another tracking
> > data structure, and either that or the LBA one is always going to be
> > badly fragmented if they aren't the same.
> 
> You're getting fragmentation anyway, which is why you had to implement
> gc. You're just shifting who gets to deal with it from the controller to
> the host. The host is further from the media, so you're starting from a
> disadvantage. The host gc implementation would have to be quite a bit
> better to justify the link and memory usage necessary for the copies
> (...queue a copy-offload discussion? oom?).

But the filesystem knows which blocks are actually in use.  Sending
TRIM/DISCARD information to the drive at block-level granularity hasn't
worked out so well in the past.  So the drive is the one at a disadvantage
because it has to copy blocks which aren't actually in use.

I like the idea of using copy-offload though.
Javier Gonzalez Nov. 8, 2024, 5:43 p.m. UTC | #8
> -----Original Message-----
> From: Matthew Wilcox <willy@infradead.org>
> Sent: Friday, November 8, 2024 5:55 PM
> To: Keith Busch <kbusch@kernel.org>
> Cc: Christoph Hellwig <hch@lst.de>; Keith Busch <kbusch@meta.com>; linux-
> block@vger.kernel.org; linux-nvme@lists.infradead.org; linux-scsi@vger.kernel.org;
> io-uring@vger.kernel.org; linux-fsdevel@vger.kernel.org; joshi.k@samsung.com;
> Javier Gonzalez <javier.gonz@samsung.com>; bvanassche@acm.org
> Subject: Re: [PATCHv10 0/9] write hints with nvme fdp, scsi streams
> 
> On Fri, Nov 08, 2024 at 08:51:31AM -0700, Keith Busch wrote:
> > On Fri, Nov 08, 2024 at 03:18:52PM +0100, Christoph Hellwig wrote:
> > > We're not really duplicating much.  Writing sequential is pretty easy,
> > > and tracking reclaim units separately means you need another tracking
> > > data structure, and either that or the LBA one is always going to be
> > > badly fragmented if they aren't the same.
> >
> > You're getting fragmentation anyway, which is why you had to implement
> > gc. You're just shifting who gets to deal with it from the controller to
> > the host. The host is further from the media, so you're starting from a
> > disadvantage. The host gc implementation would have to be quite a bit
> > better to justify the link and memory usage necessary for the copies
> > (...queue a copy-offload discussion? oom?).
> 
> But the filesystem knows which blocks are actually in use.  Sending
> TRIM/DISCARD information to the drive at block-level granularity hasn't
> worked out so well in the past.  So the drive is the one at a disadvantage
> because it has to copy blocks which aren't actually in use.

It is true that trim has not been great. I would say that at least enterprise
SSDs have fixed this in general. For FDP, DSM Deallocate is respected, which
Provides a good "erase" interface to the host.

It is true though that this is not properly described in the spec and we should
fix it.

> 
> I like the idea of using copy-offload though.

We have been iterating in the patches for years, but it is unfortunately
one of these series that go in circles forever. I don't think it is due
to any specific problem, but mostly due to unaligned requests form
different folks reviewing. Last time I talked to Damien he asked me to 
send the patches again; we have not followed through due to bandwidth.

If there is an interest, we can re-spin this again...
Bart Van Assche Nov. 8, 2024, 6:51 p.m. UTC | #9
On 11/8/24 9:43 AM, Javier Gonzalez wrote:
> If there is an interest, we can re-spin this again...

I'm interested. Work is ongoing in JEDEC on support for copy offloading
for UFS devices. This work involves standardizing which SCSI copy
offloading features should be supported and which features are not
required. Implementations are expected to be available soon.

Thanks,

Bart.
Christoph Hellwig Nov. 11, 2024, 6:48 a.m. UTC | #10
On Fri, Nov 08, 2024 at 08:51:31AM -0700, Keith Busch wrote:
> You're getting fragmentation anyway, which is why you had to implement
> gc.

A general purpose file system always has fragmentation of some kind,
even it manages to avoid those for certain workloads with cooperative
applications.

If there was magic pixies dust to ensure freespace never fragments file
system development would be solved problem :)

> You're just shifting who gets to deal with it from the controller to
> the host. The host is further from the media, so you're starting from a
> disadvantage.

And the controller is further from the application and misses a lot of
information like say the file structure, so it inherently is at a
disadvantage.

> The host gc implementation would have to be quite a bit
> better to justify the link and memory usage necessary for the copies

That assumes you still have to device GC.  If you do align to the
zone/erase (super)block/reclaim unit boundaries you don't.

> This xfs implementation also has logic to recover from a power fail. The
> device already does that if you use the LBA abstraction instead of
> tracking sequential write pointers and free blocks.

Every file system has logic to recover from a power fail.  I'm not sure
what kind of discussion you're trying to kick off here.

> I think you are underestimating the duplication of efforts going on
> here.

I'm still not sure what discussion you're trying to to start here.
There is very little work in here, and it is work required to support
SMR drives.  It turns out for a fair amount of workloads it actually
works really well on SSDs as well beating everything else we've tried.
Christoph Hellwig Nov. 11, 2024, 6:49 a.m. UTC | #11
On Fri, Nov 08, 2024 at 04:54:34PM +0000, Matthew Wilcox wrote:
> I like the idea of using copy-offload though.

FYI, the XFS GC code is written so that copy offload can be easily
plugged into it.  We'll have to see how beneficial it actually is,
but at least it should give us a good test platform.
Christoph Hellwig Nov. 11, 2024, 6:51 a.m. UTC | #12
On Fri, Nov 08, 2024 at 05:43:44PM +0000, Javier Gonzalez wrote:
> We have been iterating in the patches for years, but it is unfortunately
> one of these series that go in circles forever. I don't think it is due
> to any specific problem, but mostly due to unaligned requests form
> different folks reviewing. Last time I talked to Damien he asked me to 
> send the patches again; we have not followed through due to bandwidth.

A big problem is that it actually lacks a killer use case.  If you'd
actually manage to plug it into an in-kernel user and show a real
speedup people might actually be interested in it and help optimizing
for it.
Javier Gonzalez Nov. 11, 2024, 9:30 a.m. UTC | #13
On 11.11.2024 07:51, Christoph Hellwig wrote:
>On Fri, Nov 08, 2024 at 05:43:44PM +0000, Javier Gonzalez wrote:
>> We have been iterating in the patches for years, but it is unfortunately
>> one of these series that go in circles forever. I don't think it is due
>> to any specific problem, but mostly due to unaligned requests form
>> different folks reviewing. Last time I talked to Damien he asked me to
>> send the patches again; we have not followed through due to bandwidth.
>
>A big problem is that it actually lacks a killer use case.  If you'd
>actually manage to plug it into an in-kernel user and show a real
>speedup people might actually be interested in it and help optimizing
>for it.
>

Agree. Initially it was all about ZNS. Seems ZUFS can use it.

Then we saw good results in offload to target on NVMe-OF, similar to
copy_file_range, but that does not seem to be enough. You seem to
indicacte too that XFS can use it for GC.

We can try putting a new series out to see where we are...
Javier Gonzalez Nov. 11, 2024, 9:31 a.m. UTC | #14
On 08.11.2024 10:51, Bart Van Assche wrote:
>On 11/8/24 9:43 AM, Javier Gonzalez wrote:
>>If there is an interest, we can re-spin this again...
>
>I'm interested. Work is ongoing in JEDEC on support for copy offloading
>for UFS devices. This work involves standardizing which SCSI copy
>offloading features should be supported and which features are not
>required. Implementations are expected to be available soon.
>

Do you have any specific blockers on the last series? I know you have
left comments in many of the patches already, but I think we are all a
bit confused on where we are ATM.
Johannes Thumshirn Nov. 11, 2024, 9:37 a.m. UTC | #15
On 11.11.24 10:31, Javier Gonzalez wrote:
> On 11.11.2024 07:51, Christoph Hellwig wrote:
>> On Fri, Nov 08, 2024 at 05:43:44PM +0000, Javier Gonzalez wrote:
>>> We have been iterating in the patches for years, but it is unfortunately
>>> one of these series that go in circles forever. I don't think it is due
>>> to any specific problem, but mostly due to unaligned requests form
>>> different folks reviewing. Last time I talked to Damien he asked me to
>>> send the patches again; we have not followed through due to bandwidth.
>>
>> A big problem is that it actually lacks a killer use case.  If you'd
>> actually manage to plug it into an in-kernel user and show a real
>> speedup people might actually be interested in it and help optimizing
>> for it.
>>
> 
> Agree. Initially it was all about ZNS. Seems ZUFS can use it.
> 
> Then we saw good results in offload to target on NVMe-OF, similar to
> copy_file_range, but that does not seem to be enough. You seem to
> indicacte too that XFS can use it for GC.
> 
> We can try putting a new series out to see where we are...

I don't want to sound like a broken record, but I've said more than 
once, that btrfs (regardless of zoned or non-zoned) would be very 
interested in that as well and I'd be willing to help with the code or 
even do it myself once the block bits are in.

But apparently my voice doesn't count here
Javier Gonzalez Nov. 11, 2024, 9:41 a.m. UTC | #16
On 11.11.2024 09:37, Johannes Thumshirn wrote:
>On 11.11.24 10:31, Javier Gonzalez wrote:
>> On 11.11.2024 07:51, Christoph Hellwig wrote:
>>> On Fri, Nov 08, 2024 at 05:43:44PM +0000, Javier Gonzalez wrote:
>>>> We have been iterating in the patches for years, but it is unfortunately
>>>> one of these series that go in circles forever. I don't think it is due
>>>> to any specific problem, but mostly due to unaligned requests form
>>>> different folks reviewing. Last time I talked to Damien he asked me to
>>>> send the patches again; we have not followed through due to bandwidth.
>>>
>>> A big problem is that it actually lacks a killer use case.  If you'd
>>> actually manage to plug it into an in-kernel user and show a real
>>> speedup people might actually be interested in it and help optimizing
>>> for it.
>>>
>>
>> Agree. Initially it was all about ZNS. Seems ZUFS can use it.
>>
>> Then we saw good results in offload to target on NVMe-OF, similar to
>> copy_file_range, but that does not seem to be enough. You seem to
>> indicacte too that XFS can use it for GC.
>>
>> We can try putting a new series out to see where we are...
>
>I don't want to sound like a broken record, but I've said more than
>once, that btrfs (regardless of zoned or non-zoned) would be very
>interested in that as well and I'd be willing to help with the code or
>even do it myself once the block bits are in.
>
>But apparently my voice doesn't count here

You are right. Sorry I forgot.

Would this be through copy_file_range or something different?
Christoph Hellwig Nov. 11, 2024, 9:42 a.m. UTC | #17
On Mon, Nov 11, 2024 at 10:41:33AM +0100, Javier Gonzalez wrote:
> You are right. Sorry I forgot.
>
> Would this be through copy_file_range or something different?

Just like for f2fs, nilfs2, or the upcoming zoned xfs the prime user
would be the file system GC code.
Johannes Thumshirn Nov. 11, 2024, 9:43 a.m. UTC | #18
On 11.11.24 10:41, Javier Gonzalez wrote:
> On 11.11.2024 09:37, Johannes Thumshirn wrote:
>> On 11.11.24 10:31, Javier Gonzalez wrote:
>>> On 11.11.2024 07:51, Christoph Hellwig wrote:
>>>> On Fri, Nov 08, 2024 at 05:43:44PM +0000, Javier Gonzalez wrote:
>>>>> We have been iterating in the patches for years, but it is unfortunately
>>>>> one of these series that go in circles forever. I don't think it is due
>>>>> to any specific problem, but mostly due to unaligned requests form
>>>>> different folks reviewing. Last time I talked to Damien he asked me to
>>>>> send the patches again; we have not followed through due to bandwidth.
>>>>
>>>> A big problem is that it actually lacks a killer use case.  If you'd
>>>> actually manage to plug it into an in-kernel user and show a real
>>>> speedup people might actually be interested in it and help optimizing
>>>> for it.
>>>>
>>>
>>> Agree. Initially it was all about ZNS. Seems ZUFS can use it.
>>>
>>> Then we saw good results in offload to target on NVMe-OF, similar to
>>> copy_file_range, but that does not seem to be enough. You seem to
>>> indicacte too that XFS can use it for GC.
>>>
>>> We can try putting a new series out to see where we are...
>>
>> I don't want to sound like a broken record, but I've said more than
>> once, that btrfs (regardless of zoned or non-zoned) would be very
>> interested in that as well and I'd be willing to help with the code or
>> even do it myself once the block bits are in.
>>
>> But apparently my voice doesn't count here
> 
> You are right. Sorry I forgot.
> 
> Would this be through copy_file_range or something different?
> 

Unfortunately not, brtfs' reclaim/balance path is a wrapper on top of 
buffered read and write (plus some extra things). _BUT_ this makes it 
possible to switch the read/write part and do copy offload (where possible).
Javier Gonzalez Nov. 11, 2024, 10:37 a.m. UTC | #19
On 11.11.2024 09:43, Johannes Thumshirn wrote:
>On 11.11.24 10:41, Javier Gonzalez wrote:
>> On 11.11.2024 09:37, Johannes Thumshirn wrote:
>>> On 11.11.24 10:31, Javier Gonzalez wrote:
>>>> On 11.11.2024 07:51, Christoph Hellwig wrote:
>>>>> On Fri, Nov 08, 2024 at 05:43:44PM +0000, Javier Gonzalez wrote:
>>>>>> We have been iterating in the patches for years, but it is unfortunately
>>>>>> one of these series that go in circles forever. I don't think it is due
>>>>>> to any specific problem, but mostly due to unaligned requests form
>>>>>> different folks reviewing. Last time I talked to Damien he asked me to
>>>>>> send the patches again; we have not followed through due to bandwidth.
>>>>>
>>>>> A big problem is that it actually lacks a killer use case.  If you'd
>>>>> actually manage to plug it into an in-kernel user and show a real
>>>>> speedup people might actually be interested in it and help optimizing
>>>>> for it.
>>>>>
>>>>
>>>> Agree. Initially it was all about ZNS. Seems ZUFS can use it.
>>>>
>>>> Then we saw good results in offload to target on NVMe-OF, similar to
>>>> copy_file_range, but that does not seem to be enough. You seem to
>>>> indicacte too that XFS can use it for GC.
>>>>
>>>> We can try putting a new series out to see where we are...
>>>
>>> I don't want to sound like a broken record, but I've said more than
>>> once, that btrfs (regardless of zoned or non-zoned) would be very
>>> interested in that as well and I'd be willing to help with the code or
>>> even do it myself once the block bits are in.
>>>
>>> But apparently my voice doesn't count here
>>
>> You are right. Sorry I forgot.
>>
>> Would this be through copy_file_range or something different?
>>
>
>Unfortunately not, brtfs' reclaim/balance path is a wrapper on top of
>buffered read and write (plus some extra things). _BUT_ this makes it
>possible to switch the read/write part and do copy offload (where possible).

On 11.11.2024 10:42, hch wrote:
>On Mon, Nov 11, 2024 at 10:41:33AM +0100, Javier Gonzalez wrote:
>> You are right. Sorry I forgot.
>>
>> Would this be through copy_file_range or something different?
>
>Just like for f2fs, nilfs2, or the upcoming zoned xfs the prime user
>would be the file system GC code.

Replying to both.

Thanks. Makes sense. Now that we can talke a look at your branch, we can
think how this would look like.
Bart Van Assche Nov. 11, 2024, 5:45 p.m. UTC | #20
On 11/11/24 1:31 AM, Javier Gonzalez wrote:
> On 08.11.2024 10:51, Bart Van Assche wrote:
>> On 11/8/24 9:43 AM, Javier Gonzalez wrote:
>>> If there is an interest, we can re-spin this again...
>>
>> I'm interested. Work is ongoing in JEDEC on support for copy offloading
>> for UFS devices. This work involves standardizing which SCSI copy
>> offloading features should be supported and which features are not
>> required. Implementations are expected to be available soon.
> 
> Do you have any specific blockers on the last series? I know you have
> left comments in many of the patches already, but I think we are all a
> bit confused on where we are ATM.

Nobody replied to this question that was raised 4 months ago:
https://lore.kernel.org/linux-block/4c7f30af-9fbc-4f19-8f48-ad741aa557c4@acm.org/

I think we need to agree about the answer to that question before we can
continue with implementing copy offloading.

Thanks,

Bart.
Nitesh Shetty Nov. 12, 2024, 1:52 p.m. UTC | #21
On 11/11/24 09:45AM, Bart Van Assche wrote:
>On 11/11/24 1:31 AM, Javier Gonzalez wrote:
>>On 08.11.2024 10:51, Bart Van Assche wrote:
>>>On 11/8/24 9:43 AM, Javier Gonzalez wrote:
>>>>If there is an interest, we can re-spin this again...
>>>
>>>I'm interested. Work is ongoing in JEDEC on support for copy offloading
>>>for UFS devices. This work involves standardizing which SCSI copy
>>>offloading features should be supported and which features are not
>>>required. Implementations are expected to be available soon.
>>
>>Do you have any specific blockers on the last series? I know you have
>>left comments in many of the patches already, but I think we are all a
>>bit confused on where we are ATM.
>
>Nobody replied to this question that was raised 4 months ago:
>https://lore.kernel.org/linux-block/4c7f30af-9fbc-4f19-8f48-ad741aa557c4@acm.org/
>
>I think we need to agree about the answer to that question before we can
>continue with implementing copy offloading.
>
Yes, even I feel the same.
Blocker with copy has been how we should plumb things in block layer.
A couple of approaches we tried in the past[1].
Restating for reference,

1.payload based approach:
   a. Based on Mikulas patch, here a common payload is used for both source
     and destination bio. 
   b. Initially we send source bio, upon reaching driver we update payload
     and complete the bio.
   c. Send destination bio, in driver layer we recover the source info
     from the payload and send the copy command to device.

   Drawback:
   Request payload contains IO information rather than data.
   Based on past experience Christoph and Bart suggested not a good way
   forward.
   Alternate suggestion from Christoph was to used separate BIOs for src
   and destination and match them using token/id.
   As Bart pointed, I find it hard how to match when the IO split happens.

2. Plug based approach:
   a. Take a plug, send destination bio, form request and wait for src bio
   b. send source bio, merge with destination bio
   c. Upon release of plug send request down to driver.

   Drawback:
   Doesn't work for stacked devices which has async submission.
   Bart suggested this is not good solution overall.
   Alternate suggestion was to use list based approach.
   But we observed lifetime management problems, especially in
   failure handling.

3. Single bio approach:
   a. Use single bio to represent both src and dst info.
   b. Use abnormal IO handling similar to discard.
   Drawback:
   Christoph pointed out that, this will have issue of payload containing
   information for both IO stack and wire.


I am really torn on how to proceed further ?
-- Nitesh Shetty


[1] https://lore.kernel.org/linux-block/20240624103212.2donuac5apwwqaor@nj.shetty@samsung.com/
Martin K. Petersen Nov. 19, 2024, 2:03 a.m. UTC | #22
Nitesh,

> 1.payload based approach:
>   a. Based on Mikulas patch, here a common payload is used for both source
>     and destination bio.
>   b. Initially we send source bio, upon reaching driver we update payload
>     and complete the bio.
>   c. Send destination bio, in driver layer we recover the source info
>     from the payload and send the copy command to device.
>
>   Drawback:
>   Request payload contains IO information rather than data.
>   Based on past experience Christoph and Bart suggested not a good way
>   forward.
>   Alternate suggestion from Christoph was to used separate BIOs for src
>   and destination and match them using token/id.
>   As Bart pointed, I find it hard how to match when the IO split happens.

In my experience the payload-based approach was what made things work. I
tried many things before settling on that. Also note that to support
token-based SCSI devices, you inevitably need to separate the
read/copy_in operation from the write/copy_out ditto and carry the token
in the payload.

For "single copy command" devices, you can just synthesize the token in
the driver. Although I don't really know what the point of the token is
in that case because as far as I'm concerned, the only interesting
information is that the read/copy_in operation made it down the stack
without being split.

Handling splits made things way too complicated for my taste. Especially
with a potential many-to-many mapping. Better to just fall back to
regular read/writes if either the copy_in or the copy_out operation
needs to be split. If your stacked storage is configured with a
prohibitively small stripe chunk size, then your copy performance is
just going to be approaching that of a regular read/write data movement.
Not a big deal as far as I'm concerned...
Bart Van Assche Nov. 25, 2024, 11:21 p.m. UTC | #23
On 11/18/24 6:03 PM, Martin K. Petersen wrote:
> In my experience the payload-based approach was what made things work. I
> tried many things before settling on that. Also note that to support
> token-based SCSI devices, you inevitably need to separate the
> read/copy_in operation from the write/copy_out ditto and carry the token
> in the payload.
> 
> For "single copy command" devices, you can just synthesize the token in
> the driver. Although I don't really know what the point of the token is
> in that case because as far as I'm concerned, the only interesting
> information is that the read/copy_in operation made it down the stack
> without being split.
Hi Martin,

There are some strong arguments in this thread from May 2024 in favor of
representing the entire copy operation as a single REQ_OP_ operation:
https://lore.kernel.org/linux-block/20240520102033.9361-1-nj.shetty@samsung.com/

Token-based copy offloading (called ODX by Microsoft) could be
implemented by maintaining a state machine in the SCSI sd driver and
using a single block layer request to submit the four following SCSI
commands:
* POPULATE TOKEN
* RECEIVE ROD TOKEN INFORMATION
* WRITE USING TOKEN

I'm assuming that the IMMED bit will be set to zero in the WRITE USING
TOKEN command. Otherwise one or more additional RECEIVE ROD TOKEN
INFORMATION commands would be required to poll for the WRITE USING TOKEN
completion status.

I guess that the block layer maintainer wouldn't be happy if all block
drivers would have to deal with three or four phases for copy offloading
just because ODX is this complicated.

Thanks,

Bart.
Martin K. Petersen Nov. 27, 2024, 2:54 a.m. UTC | #24
Bart,

> There are some strong arguments in this thread from May 2024 in favor of
> representing the entire copy operation as a single REQ_OP_ operation:
> https://lore.kernel.org/linux-block/20240520102033.9361-1-nj.shetty@samsung.com/

As has been discussed many times, a copy operation is semantically a
read operation followed by a write operation. And, based on my
experience implementing support for both types of copy offload in Linux,
what made things elegant was treating the operation as a read followed
by a write throughout the stack. Exactly like the token-based offload
specification describes.

> Token-based copy offloading (called ODX by Microsoft) could be
> implemented by maintaining a state machine in the SCSI sd driver

I suspect the SCSI maintainer would object strongly to the idea of
maintaining cross-device copy offload state and associated object
lifetime issues in the sd driver.

> I'm assuming that the IMMED bit will be set to zero in the WRITE USING
> TOKEN command. Otherwise one or more additional RECEIVE ROD TOKEN
> INFORMATION commands would be required to poll for the WRITE USING TOKEN
> completion status.

What would the benefit of making WRITE USING TOKEN be a background
operation? That seems like a completely unnecessary complication.

> I guess that the block layer maintainer wouldn't be happy if all block
> drivers would have to deal with three or four phases for copy
> offloading just because ODX is this complicated.

Last I looked, EXTENDED COPY consumed something like 70 pages in the
spec. Token-based copy is trivially simple and elegant by comparison.
Bart Van Assche Nov. 27, 2024, 6:42 p.m. UTC | #25
On 11/26/24 6:54 PM, Martin K. Petersen wrote:
> Bart wrote:
>> There are some strong arguments in this thread from May 2024 in favor of
>> representing the entire copy operation as a single REQ_OP_ operation:
>> https://lore.kernel.org/linux-block/20240520102033.9361-1-nj.shetty@samsung.com/
> 
> As has been discussed many times, a copy operation is semantically a
> read operation followed by a write operation. And, based on my
> experience implementing support for both types of copy offload in Linux,
> what made things elegant was treating the operation as a read followed
> by a write throughout the stack. Exactly like the token-based offload
> specification describes.

Submitting a copy operation as two bios or two requests means that there 
is a risk that one of the two operations never reaches the block driver
at the bottom of the storage stack and hence that a deadlock occurs. I
prefer not to introduce any mechanisms that can cause a deadlock.

As one can see here, Damien Le Moal and Keith Busch both prefer to
submit copy operations as a single operation: Keith Busch, Re: [PATCH
v20 02/12] Add infrastructure for copy offload in block and request
layer, linux-block mailing list, 2024-06-24 
(https://lore.kernel.org/all/Znn6C-C73Tps3WJk@kbusch-mbp.dhcp.thefacebook.com/).

>> Token-based copy offloading (called ODX by Microsoft) could be
>> implemented by maintaining a state machine in the SCSI sd driver
> 
> I suspect the SCSI maintainer would object strongly to the idea of
> maintaining cross-device copy offload state and associated object
> lifetime issues in the sd driver.

Such information wouldn't have to be maintained inside the sd driver. A
new kernel module could be introduced that tracks the state of copy
operations and that interacts with the sd driver.

>> I'm assuming that the IMMED bit will be set to zero in the WRITE USING
>> TOKEN command. Otherwise one or more additional RECEIVE ROD TOKEN
>> INFORMATION commands would be required to poll for the WRITE USING TOKEN
>> completion status.
> 
> What would the benefit of making WRITE USING TOKEN be a background
> operation? That seems like a completely unnecessary complication.

If a single copy operation takes significantly more time than the time
required to switch between power states, power can be saved by using
IMMED=1. Mechanisms like run-time power management (RPM) or the UFS host
controller auto-hibernation mechanism can only be activated if no
commands are in progress. With IMMED=0, the link between the host and
the storage device will remain powered as long as the copy operation is
in progress. With IMMED=1, the link between the host and the storage
device can be powered down after the copy operation has been submitted
until the host decides to check whether or not the copy operation has
completed.

>> I guess that the block layer maintainer wouldn't be happy if all block
>> drivers would have to deal with three or four phases for copy
>> offloading just because ODX is this complicated.
> 
> Last I looked, EXTENDED COPY consumed something like 70 pages in the
> spec. Token-based copy is trivially simple and elegant by comparison.

I don't know of any storage device vendor who has implemented all
EXTENDED COPY features that have been standardized. Assuming that 50
lines of code fit on a single page, here is an example of an EXTENDED
COPY implementation that can be printed on 21 pages of paper:
$ wc -l drivers/target/target_core_xcopy.c
  1041
$ echo $(((1041 + 49) / 50))
21

The advantages of EXTENDED COPY over ODX are as follows:
- EXTENDED COPY is a single SCSI command and hence better suited for
   devices with a limited queue depth. While the UFS 3.0 standard
   restricts the queue depth to 32, most UFS 4.0 devices support a
   queue depth of 64.
- The latency of setting up a copy command with EXTENDED COPY is
   lower since only a single command has to be sent to the device.
   ODX requires three round-trips to the device (assuming IMMED=0).
- EXTENDED COPY requires less memory in storage devices. Each ODX
   token occupies some memory and the rules around token lifetimes
   are nontrivial.

Thanks,

Bart.
Martin K. Petersen Nov. 27, 2024, 8:14 p.m. UTC | #26
Bart,

> Submitting a copy operation as two bios or two requests means that
> there is a risk that one of the two operations never reaches the block
> driver at the bottom of the storage stack and hence that a deadlock
> occurs. I prefer not to introduce any mechanisms that can cause a
> deadlock.

How do you copy a block range without offload? You perform a READ to
read the data into memory. And once the READ completes, you do a WRITE
of the data to the new location.

Token-based copy offload works exactly the same way. You do a POPULATE
TOKEN which is identical to a READ except you get a cookie instead of
the actual data. And then once you have the cookie, you perform a WRITE
USING TOKEN to perform the write operation. Semantically, it's exactly
the same as a normal copy except for the lack of data movement. That's
the whole point!

Once I had support for token-based copy offload working, it became clear
to me that this approach is much simpler than pointer matching, bio
pairs, etc. The REQ_OP_COPY_IN operation and the REQ_OP_COPY_OUT
operation are never in flight at the same time. There are no
synchronization hassles, no lifetimes, no lookup tables in the sd
driver, no nonsense. Semantically, it's a read followed by a write.

For devices that implement single-command copy offload, the
REQ_OP_COPY_IN operation only serves as a validation that no splitting
took place. Once the bio reaches the ULD, the I/O is completed without
ever sending a command to the device. blk-lib then issues a
REQ_OP_COPY_OUT which gets turned into EXTENDED COPY or NVMe Copy and
sent to the destination device.

Aside from making things trivially simple, the COPY_IN/COPY_OUT semantic
is a *requirement* for token-based offload devices. Why would we even
consider having two incompatible sets of copy offload semantics coexist
in the block layer?
Bart Van Assche Nov. 27, 2024, 9:06 p.m. UTC | #27
On 11/27/24 12:14 PM, Martin K. Petersen wrote:
> Once I had support for token-based copy offload working, it became clear
> to me that this approach is much simpler than pointer matching, bio
> pairs, etc. The REQ_OP_COPY_IN operation and the REQ_OP_COPY_OUT
> operation are never in flight at the same time. There are no
> synchronization hassles, no lifetimes, no lookup tables in the sd
> driver, no nonsense. Semantically, it's a read followed by a write.

What if the source LBA range does not require splitting but the
destination LBA range requires splitting, e.g. because it crosses a
chunk_sectors boundary? Will the REQ_OP_COPY_IN operation succeed in
this case and the REQ_OP_COPY_OUT operation fail? Does this mean that a
third operation is needed to cancel REQ_OP_COPY_IN operations if the
REQ_OP_COPY_OUT operation fails?

Additionally, how to handle bugs in REQ_OP_COPY_* submitters where a
large number of REQ_OP_COPY_IN operations is submitted without
corresponding REQ_OP_COPY_OUT operation? Is perhaps a mechanism required
to discard unmatched REQ_OP_COPY_IN operations after a certain time?

> Aside from making things trivially simple, the COPY_IN/COPY_OUT semantic
> is a *requirement* for token-based offload devices.

Hmm ... we may each have a different opinion about whether or not the 
COPY_IN/COPY_OUT semantics are a requirement for token-based copy
offloading.

Additionally, I'm not convinced that implementing COPY_IN/COPY_OUT for
ODX devices is that simple. The COPY_IN and COPY_OUT operations have
to be translated into three SCSI commands, isn't it? I'm referring to
the POPULATE TOKEN, RECEIVE ROD TOKEN INFORMATION and WRITE USING TOKEN
commands. What is your opinion about how to translate the two block
layer operations into these three SCSI commands?

> Why would we even consider having two incompatible sets of copy
> offload semantics coexist in the block layer?
I am not aware of any proposal to implement two sets of copy operations
in the block layer. All proposals I have seen so far involve adding a
single set of copy operations to the block layer. Opinions differ
however about whether to add a single copy operation primitive or
separate IN and OUT primitives.

Thanks,

Bart.
Martin K. Petersen Nov. 28, 2024, 2:09 a.m. UTC | #28
Bart,

> What if the source LBA range does not require splitting but the
> destination LBA range requires splitting, e.g. because it crosses a
> chunk_sectors boundary? Will the REQ_OP_COPY_IN operation succeed in
> this case and the REQ_OP_COPY_OUT operation fail?

Yes.

I experimented with approaching splitting in an iterative fashion. And
thus, if there was a split halfway through the COPY_IN I/O, we'd issue a
corresponding COPY_OUT up to the split point and hope that the write
subsequently didn't need a split. And then deal with the next segment.

However, given that copy offload offers diminishing returns for small
I/Os, it was not worth the hassle for the devices I used for
development. It was cleaner and faster to just fall back to regular
read/write when a split was required.

> Does this mean that a third operation is needed to cancel
> REQ_OP_COPY_IN operations if the REQ_OP_COPY_OUT operation fails?

No. The device times out the token.

> Additionally, how to handle bugs in REQ_OP_COPY_* submitters where a
> large number of REQ_OP_COPY_IN operations is submitted without
> corresponding REQ_OP_COPY_OUT operation? Is perhaps a mechanism
> required to discard unmatched REQ_OP_COPY_IN operations after a
> certain time?

See above.

For your EXTENDED COPY use case there is no token and thus the COPY_IN
completes immediately.

And for the token case, if you populate a million tokens and don't use
them before they time out, it sounds like your submitting code is badly
broken. But it doesn't matter because there are no I/Os in flight and
thus nothing to discard.

> Hmm ... we may each have a different opinion about whether or not the
> COPY_IN/COPY_OUT semantics are a requirement for token-based copy
> offloading.

Maybe. But you'll have a hard time convincing me to add any kind of
state machine or bio matching magic to the SCSI stack when the simplest
solution is to treat copying like a read followed by a write. There is
no concurrency, no kernel state, no dependency between two commands, nor
two scsi_disk/scsi_device object lifetimes to manage.

> Additionally, I'm not convinced that implementing COPY_IN/COPY_OUT for
> ODX devices is that simple. The COPY_IN and COPY_OUT operations have
> to be translated into three SCSI commands, isn't it? I'm referring to
> the POPULATE TOKEN, RECEIVE ROD TOKEN INFORMATION and WRITE USING
> TOKEN commands. What is your opinion about how to translate the two
> block layer operations into these three SCSI commands?

COPY_IN is translated to a NOP for devices implementing EXTENDED COPY
and a POPULATE TOKEN for devices using tokens.

COPY_OUT is translated to an EXTENDED COPY (or NVMe Copy) for devices
using a single command approach and WRITE USING TOKEN for devices using
tokens.

There is no need for RECEIVE ROD TOKEN INFORMATION.

I am not aware of UFS devices using the token-based approach. And for
EXTENDED COPY there is only a single command sent to the device. If you
want to do power management while that command is being processed,
please deal with that in UFS. The block layer doesn't deal with the
async variants of any of the other SCSI commands either...
Christoph Hellwig Nov. 28, 2024, 3:24 a.m. UTC | #29
On Wed, Nov 27, 2024 at 03:14:09PM -0500, Martin K. Petersen wrote:
> How do you copy a block range without offload? You perform a READ to
> read the data into memory. And once the READ completes, you do a WRITE
> of the data to the new location.

Yes.  I.e. this is code that makes this pattern very clearm and for
which I'd love to be able to use copy offload when available:

http://git.infradead.org/?p=users/hch/xfs.git;a=blob;f=fs/xfs/xfs_zone_gc.c;h=ed8aa08b3c18d50afe79326e697d83e09542a9b6;hb=refs/heads/xfs-zoned#l820
Damien Le Moal Nov. 28, 2024, 8:51 a.m. UTC | #30
On 11/28/24 11:09, Martin K. Petersen wrote:
> 
> Bart,
> 
>> What if the source LBA range does not require splitting but the
>> destination LBA range requires splitting, e.g. because it crosses a
>> chunk_sectors boundary? Will the REQ_OP_COPY_IN operation succeed in
>> this case and the REQ_OP_COPY_OUT operation fail?
> 
> Yes.
> 
> I experimented with approaching splitting in an iterative fashion. And
> thus, if there was a split halfway through the COPY_IN I/O, we'd issue a
> corresponding COPY_OUT up to the split point and hope that the write
> subsequently didn't need a split. And then deal with the next segment.
> 
> However, given that copy offload offers diminishing returns for small
> I/Os, it was not worth the hassle for the devices I used for
> development. It was cleaner and faster to just fall back to regular
> read/write when a split was required.
> 
>> Does this mean that a third operation is needed to cancel
>> REQ_OP_COPY_IN operations if the REQ_OP_COPY_OUT operation fails?
> 
> No. The device times out the token.
> 
>> Additionally, how to handle bugs in REQ_OP_COPY_* submitters where a
>> large number of REQ_OP_COPY_IN operations is submitted without
>> corresponding REQ_OP_COPY_OUT operation? Is perhaps a mechanism
>> required to discard unmatched REQ_OP_COPY_IN operations after a
>> certain time?
> 
> See above.
> 
> For your EXTENDED COPY use case there is no token and thus the COPY_IN
> completes immediately.
> 
> And for the token case, if you populate a million tokens and don't use
> them before they time out, it sounds like your submitting code is badly
> broken. But it doesn't matter because there are no I/Os in flight and
> thus nothing to discard.
> 
>> Hmm ... we may each have a different opinion about whether or not the
>> COPY_IN/COPY_OUT semantics are a requirement for token-based copy
>> offloading.
> 
> Maybe. But you'll have a hard time convincing me to add any kind of
> state machine or bio matching magic to the SCSI stack when the simplest
> solution is to treat copying like a read followed by a write. There is
> no concurrency, no kernel state, no dependency between two commands, nor
> two scsi_disk/scsi_device object lifetimes to manage.

And that also would allow supporting a fake copy offload with regular read/write
BIOs very easily, I think. So all block devices can be presented as supporting
"copy offload". That is nice for FSes.

> 
>> Additionally, I'm not convinced that implementing COPY_IN/COPY_OUT for
>> ODX devices is that simple. The COPY_IN and COPY_OUT operations have
>> to be translated into three SCSI commands, isn't it? I'm referring to
>> the POPULATE TOKEN, RECEIVE ROD TOKEN INFORMATION and WRITE USING
>> TOKEN commands. What is your opinion about how to translate the two
>> block layer operations into these three SCSI commands?
> 
> COPY_IN is translated to a NOP for devices implementing EXTENDED COPY
> and a POPULATE TOKEN for devices using tokens.
> 
> COPY_OUT is translated to an EXTENDED COPY (or NVMe Copy) for devices
> using a single command approach and WRITE USING TOKEN for devices using
> tokens.

ATA WRITE GATHERED command is also a single copy command. That matches and while
I have not checked SAT, translation would likely work.

While I was initially worried that the 2 BIO based approach would be overly
complicated, it seems that I was wrong :)

> 
> There is no need for RECEIVE ROD TOKEN INFORMATION.
> 
> I am not aware of UFS devices using the token-based approach. And for
> EXTENDED COPY there is only a single command sent to the device. If you
> want to do power management while that command is being processed,
> please deal with that in UFS. The block layer doesn't deal with the
> async variants of any of the other SCSI commands either...
>
Keith Busch Nov. 28, 2024, 3:21 p.m. UTC | #31
On Wed, Nov 27, 2024 at 03:14:09PM -0500, Martin K. Petersen wrote:
> 
> Bart,
> 
> > Submitting a copy operation as two bios or two requests means that
> > there is a risk that one of the two operations never reaches the block
> > driver at the bottom of the storage stack and hence that a deadlock
> > occurs. I prefer not to introduce any mechanisms that can cause a
> > deadlock.
> 
> How do you copy a block range without offload? You perform a READ to
> read the data into memory. And once the READ completes, you do a WRITE
> of the data to the new location.
> 
> Token-based copy offload works exactly the same way. You do a POPULATE
> TOKEN which is identical to a READ except you get a cookie instead of
> the actual data. And then once you have the cookie, you perform a WRITE
> USING TOKEN to perform the write operation. Semantically, it's exactly
> the same as a normal copy except for the lack of data movement. That's
> the whole point!

I think of copy a little differently. When you do a normal write
command, the host provides the controller a vector of sources and
lengths. A copy command is like a write command, but the sources are
just logical block addresses instead of memory addresses.

Whatever solution happens, it would be a real shame if it doesn't allow
vectored LBAs. The token based source bio doesn't seem to extend to
that.
Christoph Hellwig Nov. 28, 2024, 4:40 p.m. UTC | #32
On Thu, Nov 28, 2024 at 08:21:16AM -0700, Keith Busch wrote:
> I think of copy a little differently. When you do a normal write
> command, the host provides the controller a vector of sources and
> lengths. A copy command is like a write command, but the sources are
> just logical block addresses instead of memory addresses.
> 
> Whatever solution happens, it would be a real shame if it doesn't allow
> vectored LBAs. The token based source bio doesn't seem to extend to
> that.

POPULATE TOKEN as defined by SCSI/SBC takes a list of LBA ranges as
well.
Christoph Hellwig Nov. 29, 2024, 6:19 a.m. UTC | #33
On Thu, Nov 28, 2024 at 05:51:52PM +0900, Damien Le Moal wrote:
> > Maybe. But you'll have a hard time convincing me to add any kind of
> > state machine or bio matching magic to the SCSI stack when the simplest
> > solution is to treat copying like a read followed by a write. There is
> > no concurrency, no kernel state, no dependency between two commands, nor
> > two scsi_disk/scsi_device object lifetimes to manage.
> 
> And that also would allow supporting a fake copy offload with regular
> read/write BIOs very easily, I think. So all block devices can be
> presented as supporting "copy offload". That is nice for FSes.

Just as when that showed up in one of the last copy offload series
I'm still very critical of a stateless copy offload emulation.  The
reason for that is that a host based copy helper needs scratch space
to read into, and doing these large allocation on every copy puts a
lot of pressure onto the allocator.  Allocating the buffer once at
mount time and the just cycling through it is generally a lot more
efficient.
Damien Le Moal Nov. 29, 2024, 6:23 a.m. UTC | #34
On 11/29/24 15:19, Christoph Hellwig wrote:
> On Thu, Nov 28, 2024 at 05:51:52PM +0900, Damien Le Moal wrote:
>>> Maybe. But you'll have a hard time convincing me to add any kind of
>>> state machine or bio matching magic to the SCSI stack when the simplest
>>> solution is to treat copying like a read followed by a write. There is
>>> no concurrency, no kernel state, no dependency between two commands, nor
>>> two scsi_disk/scsi_device object lifetimes to manage.
>>
>> And that also would allow supporting a fake copy offload with regular
>> read/write BIOs very easily, I think. So all block devices can be
>> presented as supporting "copy offload". That is nice for FSes.
> 
> Just as when that showed up in one of the last copy offload series
> I'm still very critical of a stateless copy offload emulation.  The
> reason for that is that a host based copy helper needs scratch space
> to read into, and doing these large allocation on every copy puts a
> lot of pressure onto the allocator.  Allocating the buffer once at
> mount time and the just cycling through it is generally a lot more
> efficient.

Sure, that sounds good. My point was that it seems that a token based copy
offload design makes it relatively easy to emulate copy in software for devices
that do not support copy offload in hardware. That emulation can certainly be
implemented using a single buffer like you suggest.