Re: What is needed for ZFS block cloning to work?

"Rob Norris" <[email protected]> Mon, 13 Jul 2026 10:06:57 +1000
Newsgroups gmane.os.freebsd.devel.file-systems
Message-ID <[email protected]>
--77a03b9c2ea4cec1c9adc822ecc59fa03c8ebf64
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

On Mon, 13 Jul 2026, at 6:01 AM, John F Carr wrote:
> Is copy_file_range supposed to use cloning when copying between children of
> the same encrypted filesystem?  Or only within a filesystem?

Within the same "clone group", which is a filesystem/zvol, its snapshots, and clones created from those snapshots (ie via zfs clone). All datasets within such a group share a master key, so a block created in one can be decrypted in another.

Note that "clone group" is not the same thing as "encryption root" - datasets with the same encryption root share a wrapping key, but not necessarily the same master key.

I'll note here a possible misunderstanding that I see a lot. For copy_file_range(), block cloning is an implementation detail. copy_file_range()'s purpose is to ask the kernel to make a logical copy of some data, by whatever means its chooses. It's reasonable to wonder about when cloning is chosen as an academic exercise, but the only thing the call guarantees on success is that reading back the source and destination will yield the same bytes; the underlying structure is irrelevant.

None of that is to say that it shouldn't be more controllable or predictable, but it would need more work. On Linux the FICLONERANGE ioctl is (effectively) the same as copy_file_range(), but it _must_ clone, or fail. Again on Linux, the FIEMAP ioctl or something like it would allow inspecting the underlying structure of the object in question (ZFS on Linux implements FICLONERANGE but not FIEMAP, yet). A richer error/result return path would allow us to return back to userspace why a clone didn't happen, but I'm not sure that there's any really pleasant facility out there for such things.

Rob.
--77a03b9c2ea4cec1c9adc822ecc59fa03c8ebf64
Content-Type: text/html
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html><html><head><title></title></head><body><div>On Mon, 13 J=
ul 2026, at 6:01 AM, John F Carr wrote:<br></div><blockquote type=3D"cit=
e" id=3D"qt" style=3D""><div>Is copy_file_range supposed to use cloning =
when copying between children of</div><div>the same encrypted filesystem=
?&nbsp; Or only within a filesystem?</div></blockquote><div><br></div><d=
iv>Within the same "clone group", which is a filesystem/zvol, its snapsh=
ots, and clones created from those snapshots (ie via zfs clone). All dat=
asets within such a group share a master key, so a block created in one =
can be decrypted in another.</div><div><br></div><div>Note that "clone g=
roup" is not the same thing as "encryption root" - datasets with the sam=
e encryption root share a wrapping key, but not necessarily the same mas=
ter key.</div><div><br></div><div>I'll note here a possible misunderstan=
ding that I see a lot. For copy_file_range(), block cloning is an implem=
entation detail. copy_file_range()'s purpose is to ask the kernel to mak=
e a logical copy of some data, by whatever means its chooses. It's reaso=
nable to wonder about when cloning is chosen as an academic exercise, bu=
t the only thing the call guarantees on success is that reading back the=
 source and destination will yield the same bytes; the underlying struct=
ure is irrelevant.</div><div><br></div><div>None of that is to say that =
it shouldn't be more controllable or predictable, but it would need more=
 work. On Linux the FICLONERANGE ioctl is (effectively) the same as copy=
_file_range(), but it _must_ clone, or fail. Again on Linux, the FIEMAP =
ioctl or something like it would allow inspecting the underlying structu=
re of the object in question (ZFS on Linux implements FICLONERANGE but n=
ot FIEMAP, yet). A richer error/result return path would allow us to ret=
urn back to userspace why a clone didn't happen, but I'm not sure that t=
here's any really pleasant facility out there for such things.</div><div=
><br></div><div>Rob.</div></body></html>
--77a03b9c2ea4cec1c9adc822ecc59fa03c8ebf64--