Re: [PATCH v7 17/43] btrfs: add get_devices hook for fscrypt

From: Daniel Vacek

Date: Fri May 29 2026 - 11:32:30 EST


On Fri, 22 May 2026 at 14:17, Christoph Hellwig <hch@xxxxxxxxxxxxx> wrote:
> On Fri, May 22, 2026 at 02:00:28PM +0200, Daniel Vacek wrote:
> > > How does this handled adding/removing devices at runtime?
> >
> > When called, this callback returns the list of bdevs opened by the
> > given superblock. If devices are added or removed, this function
> > returns a different list.
> > In other words it always returns a valid list.
> >
> > This is called from `fscrypt_get_devices()`, which is called from
> > `fscrypt_select_encryption_impl()` or
> > `fscrypt_prepare_inline_crypt_key()` or
> > `fscrypt_destroy_inline_crypt_key()`. All these functions walk the
> > returned list and discard it immediately afterwards.
> >
> > Note that with btrfs at this point we're only using the inline crypto fallback.
> > Is there any particular reason you asked this question?
>
> Well, assume you have a single device fs, and then you add a device
> later, you will not get the blk_crypto_config_supported call for this
> device, and it will not be taken into account.

This function is called from `fscrypt_prepare_new_inode()` from
`btrfs_new_inode_prepare()` as well as from many other places.
It looks quite OK to me and I can also confirm this with tracing.
Using the following bpftrace script:

```
fr:fscrypt_get_devices {
// $num_devs = args.num_devs[0];
$num_devs = ((uint32 *)args.num_devs)[0];
// if ($num_devs < 2) { return; }
printf("%s()\t\t\t(%4d %13s[%d])\tnum_devs %d\n", func,
cpu, curtask->comm, curtask->pid, $num_devs);
}

f:blk_crypto_config_supported {
printf("%s()\t\t(%4d %13s[%d])\tbdev %18p\n", func,
cpu, curtask->comm, curtask->pid, args.bdev);
}
```

... and mounting an encrypted FS, then adding an additional device, like this:

```
$ mount /dev/vdb /mnt/scratch; \
echo -ne $TEST_RAW_KEY | xfs_io -c add_enckey /mnt/scratch; \
touch /mnt/scratch/dir/foo; \
btrfs device add /dev/vdc /mnt/scratch; \
touch /mnt/scratch/dir/bar
```

I'm getting this:

```
fscrypt_get_devices() ( 5 touch[26840]) num_devs 1
blk_crypto_config_supported() ( 5 touch[26840]) bdev
0xffff88a9c33fc880
fscrypt_get_devices() ( 5 touch[26840]) num_devs 1
fscrypt_get_devices() ( 5 touch[26844]) num_devs 2
blk_crypto_config_supported() ( 5 touch[26844]) bdev
0xffff88a9c3262b80
blk_crypto_config_supported() ( 5 touch[26844]) bdev
0xffff88a9c33fc880
fscrypt_get_devices() ( 5 touch[26844]) num_devs 2
```

Here you can see the newly added device is being considered.

Moreover btrfs only supports the fallback encryption due to the need
to compute the checksums of encrypted data stored on the device.

> Now can btrfs even support hardware inline encryption? The way the bio
> processing is special cased I somehow doubt it. But the concept of a
> static device list just doesn't work for btrfs, so I think the fscrypt
> side of this will need refactoring not to rely on it. If we never
> support hardware inline encryption on such dynamic file systems that
> would be relative easy, if we need to support that case things might
> get a lot more complicated.

Yeah, this depends. If the device or fscrypt could return the checksum
to the FS, btrfs could use the inline HW encryption. Note that the
checksum must also be one that btrfs supports.
Otherwise we need to get the encrypted data to compute the checksum
ourselves. That is precisely why only fallback encryption is currently
supported. And it's where the FS callback hook is used to compute the
checksum.

--nX