How to set secondary volume mount options?

I have searched all around with no luck, how can I set mount options for a secondary volume mounted this way:

lxc config device add backup data disk path=/data source=/dev/zd16

As LXD is taking care of the mount there should be a way to do it, isn’t it ?

So we’ve usually been pushing back against this as we don’t like directly exposing kernel APIs to our users as that makes testing, migration and internal reworks much harder.

It’s something we may do an exception on specifically for mounts of a block device though but would need a new option to be added to LXD.

An alternative which would work today is to mount your zvol to some path on your host with whatever options you want, then use your disk entry but change source= to point to the existing mount on your host rather than the device.

Ok thanks, I’ll give it a go and report back. I just need usrquota on a ZVOL.

So we’ve usually been pushing back against this as we don’t like directly exposing kernel APIs to our users as that makes testing, migration and internal reworks much harder.

But it is possible to set rootfs mount points …

LXD seriously needs to support ZVOL as rootfs that would just makes it perfect. I have a web hosting panel on my company’s server that I had to setup using libvirt because it needs usrquotas support for /, so it is slower than I wished it was.

Could you please review and add you two cents on my post about user quotas support in LXD ?
Looking all around, having standard quotas support is recurrent about being a reason of people staying away from LXD.

I tried it and have this in my container:

# mount  | grep data
/dev/zd16p1 on /data type ext4 (rw,relatime,quota,usrquota,grpquota,stripe=2,data=ordered)

I can write to /data/ but cannot enable user quotas:

# quotacheck -gum /
quotacheck: Cannot stat() mounted device /dev/zd16p1: No such file or directory
quotacheck: Mountpoint (or device) / not found or has no quota enabled.
quotacheck: Cannot find filesystem to check or filesystem not mounted with quota option.
root@backup:~# quotacheck -gum /data

It looks like the ZVOL should have to be mounted by the container itself which isn’t possible because of security implications.

Well, you could try passing a unix-char device for /dev/zd16p1, that should make that particular check pass and get you one step further.

Though indeed, it’s not something that’s safe to do at all and so not something we’d do ourselves, but if that fixes it, it may hint that the quota tools may be made a bit smarter to handle cases where the block device isn’t visible.

You mean that I keep the current setup and “add” a unix-char device ?

How is it unsafe ?

Correct. disk device for the data and unix-block device to have the /dev node.

This is very unsafe because it would allow the container to directly write to its backing block device, this would allow you to confuse the filesystem driver by modifying blocks directly, causing kernel crashes or if carefully done, potentially letting you escape the container by exploiting the kernel directly.

It seems to work, I have a few warnings that I need to investigate on.

That said if it can harm the host in anyway it isn’t an options for me. If it was a matter of the container doing bad things on /dev/zd16 ONLY it would have not matter.

Can you run quotacheck under strace to see exactly what it does with that block device?

Here you go. BTW thanks a lot for you fantastic help:

# strace quotacheck -mugv /data
execve("/sbin/quotacheck", ["quotacheck", "-mugv", "/data"], 0x7ffe461d0ea0 /* 10 vars */) = 0
brk(NULL)                               = 0x564c2262d000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=17175, ...}) = 0
mmap(NULL, 17175, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43ffe000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libext2fs.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\317\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=323888, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac43ffc000
mmap(NULL, 2419816, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac43b8d000
mprotect(0x7fac43bda000, 2097152, PROT_NONE) = 0
mmap(0x7fac43dda000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4d000) = 0x7fac43dda000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libtirpc.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320r\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=163104, ...}) = 0
mmap(NULL, 2261144, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac43964000
mprotect(0x7fac4398b000, 2093056, PROT_NONE) = 0
mmap(0x7fac43b8a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7fac43b8a000
mmap(0x7fac43b8c000, 152, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fac43b8c000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac43573000
mprotect(0x7fac4375a000, 2097152, PROT_NONE) = 0
mmap(0x7fac4395a000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7fac4395a000
mmap(0x7fac43960000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fac43960000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libcom_err.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200\23\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=14248, ...}) = 0
mmap(NULL, 2109608, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac4336f000
mprotect(0x7fac43372000, 2093056, PROT_NONE) = 0
mmap(0x7fac43571000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7fac43571000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340\266\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=305456, ...}) = 0
mmap(NULL, 2401088, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac43124000
mprotect(0x7fac4316c000, 2093056, PROT_NONE) = 0
mmap(0x7fac4336b000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x47000) = 0x7fac4336b000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000b\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=144976, ...}) = 0
mmap(NULL, 2221184, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac42f05000
mprotect(0x7fac42f1f000, 2093056, PROT_NONE) = 0
mmap(0x7fac4311e000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19000) = 0x7fac4311e000
mmap(0x7fac43120000, 13440, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fac43120000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libkrb5.so.3", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\27\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=877056, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac43ffa000
mmap(NULL, 2972896, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac42c2f000
mprotect(0x7fac42cf5000, 2097152, PROT_NONE) = 0
mmap(0x7fac42ef5000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xc6000) = 0x7fac42ef5000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libk5crypto.so.3", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0PC\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=199104, ...}) = 0
mmap(NULL, 2297976, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac429fd000
mprotect(0x7fac42a2b000, 2097152, PROT_NONE) = 0
mmap(0x7fac42c2b000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2e000) = 0x7fac42c2b000
mmap(0x7fac42c2e000, 120, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fac42c2e000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libkrb5support.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@'\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=43616, ...}) = 0
mmap(NULL, 2139080, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac427f2000
mprotect(0x7fac427fc000, 2093056, PROT_NONE) = 0
mmap(0x7fac429fb000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x9000) = 0x7fac429fb000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libkeyutils.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\22\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=14256, ...}) = 0
mmap(NULL, 2109456, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac425ee000
mprotect(0x7fac425f1000, 2093056, PROT_NONE) = 0
mmap(0x7fac427f0000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7fac427f0000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\00008\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=101168, ...}) = 0
mmap(NULL, 2206336, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac423d3000
mprotect(0x7fac423ea000, 2097152, PROT_NONE) = 0
mmap(0x7fac425ea000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17000) = 0x7fac425ea000
mmap(0x7fac425ec000, 6784, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fac425ec000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\16\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=14560, ...}) = 0
mmap(NULL, 2109712, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac421cf000
mprotect(0x7fac421d2000, 2093056, PROT_NONE) = 0
mmap(0x7fac423d1000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7fac423d1000
close(3)                                = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac43ff8000
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac43ff5000
arch_prctl(ARCH_SET_FS, 0x7fac43ff5740) = 0
mprotect(0x7fac4395a000, 16384, PROT_READ) = 0
mprotect(0x7fac423d1000, 4096, PROT_READ) = 0
mprotect(0x7fac425ea000, 4096, PROT_READ) = 0
mprotect(0x7fac427f0000, 4096, PROT_READ) = 0
mprotect(0x7fac429fb000, 4096, PROT_READ) = 0
mprotect(0x7fac42c2b000, 8192, PROT_READ) = 0
mprotect(0x7fac4311e000, 4096, PROT_READ) = 0
mprotect(0x7fac43571000, 4096, PROT_READ) = 0
mprotect(0x7fac42ef5000, 57344, PROT_READ) = 0
mprotect(0x7fac4336b000, 8192, PROT_READ) = 0
mprotect(0x7fac43b8a000, 4096, PROT_READ) = 0
mprotect(0x7fac43dda000, 4096, PROT_READ) = 0
mprotect(0x564c2091e000, 4096, PROT_READ) = 0
mprotect(0x7fac44003000, 4096, PROT_READ) = 0
munmap(0x7fac43ffe000, 17175)           = 0
set_tid_address(0x7fac43ff5a10)         = 592
set_robust_list(0x7fac43ff5a20, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7fac42f0acb0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7fac42f17890}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7fac42f0ad50, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7fac42f17890}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
brk(NULL)                               = 0x564c2262d000
brk(0x564c2264e000)                     = 0x564c2264e000
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1683120, ...}) = 0
mmap(NULL, 1683120, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43e5a000
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2995, ...}) = 0
read(3, "# Locale name alias data base.\n#"..., 3072) = 2995
read(3, "", 3072)                       = 0
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=252, ...}) = 0
mmap(NULL, 252, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac44002000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26376, ...}) = 0
mmap(NULL, 26376, PROT_READ, MAP_SHARED, 3, 0) = 0x7fac43e53000
close(3)                                = 0
futex(0x7fac4395fa08, FUTEX_WAKE_PRIVATE, 2147483647) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=23, ...}) = 0
mmap(NULL, 23, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac44001000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=47, ...}) = 0
mmap(NULL, 47, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac44000000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=131, ...}) = 0
mmap(NULL, 131, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43fff000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=62, ...}) = 0
mmap(NULL, 62, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43ffe000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=34, ...}) = 0
mmap(NULL, 34, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43e52000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=3, ...}) = 0
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=48, ...}) = 0
mmap(NULL, 48, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43e51000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MONETARY", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=270, ...}) = 0
mmap(NULL, 270, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43e50000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1516558, ...}) = 0
mmap(NULL, 1516558, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac4205c000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TIME", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3360, ...}) = 0
mmap(NULL, 3360, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43e4f000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NUMERIC", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=50, ...}) = 0
mmap(NULL, 50, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43e4e000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=199772, ...}) = 0
mmap(NULL, 199772, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac43e1d000
close(3)                                = 0
rt_sigaction(SIGSEGV, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fac435b1f20}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
stat("/proc/sys/fs/quota", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
rt_sigaction(SIGSEGV, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fac435b1f20}, NULL, 8) = 0
openat(AT_FDCWD, "/proc/mounts", O_RDONLY|O_CLOEXEC) = 3
futex(0x7fac43961168, FUTEX_WAKE_PRIVATE, 2147483647) = 0
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "pool1/lxd/containers/backu"..., 1024) = 1024
read(3, "_inodes=2004914,mode=755 0 0\nude"..., 1024) = 1024
read(3, " /dev/mqueue mqueue rw,relatime "..., 1024) = 1024
quotactl(QCMD(Q_GETINFO, USRQUOTA), "/dev/zd16p1", 0x7ffc259e4880) = -1 ESRCH (No such process)
quotactl(QCMD(Q_GETINFO, GRPQUOTA), "/dev/zd16p1", 0x7ffc259e4880) = -1 ESRCH (No such process)
quotactl(QCMD(Q_GETINFO, PRJQUOTA), "/dev/zd16p1", 0x7ffc259e4880) = -1 ESRCH (No such process)
lstat("/data", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
statfs("/data", {f_type=EXT2_SUPER_MAGIC, f_bsize=4096, f_blocks=51343605, f_bfree=51328234, f_bavail=48702712, f_files=13107200, f_ffree=13107186, f_fsid={val=[3435793630, 4029254633]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_RELATIME}) = 0
stat("/dev/zd16p1", {st_mode=S_IFBLK|0660, st_rdev=makedev(230, 17), ...}) = 0
stat("/data", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
quotactl(QCMD(Q_GETINFO, USRQUOTA), "/dev/sdc2", 0x7ffc259e4880) = -1 ENOENT (No such file or directory)
quotactl(QCMD(Q_GETINFO, GRPQUOTA), "/dev/sdc2", 0x7ffc259e4880) = -1 ENOENT (No such file or directory)
quotactl(QCMD(Q_GETINFO, PRJQUOTA), "/dev/sdc2", 0x7ffc259e4880) = -1 ENOENT (No such file or directory)
read(3, "rw,nosuid,nodev,noexec,relatime,"..., 1024) = 958
read(3, "", 1024)                       = 0
close(3)                                = 0
stat("/data", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat("/data", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
openat(AT_FDCWD, "/usr/share/locale/C.UTF-8/LC_MESSAGES/quota.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C.utf8/LC_MESSAGES/quota.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/C/LC_MESSAGES/quota.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.UTF-8/LC_MESSAGES/quota.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C.utf8/LC_MESSAGES/quota.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale-langpack/C/LC_MESSAGES/quota.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
lstat("/data", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
quotactl(QCMD(Q_GETFMT, USRQUOTA), "/dev/zd16p1", 0x7ffc259e6a54) = -1 ESRCH (No such process)
openat(AT_FDCWD, "/data/aquota.user", O_RDONLY) = 3
lseek(3, 0, SEEK_SET)                   = 0
read(3, "\21\37\300\331\0\0\0\0", 8)    = 8
lseek(3, 8, SEEK_SET)                   = 8
read(3, "\200:\t\0\200:\t\0\0\0\0\0\10\0\0\0\0\0\0\0\5\0\0\0", 24) = 24
lseek(3, 0, SEEK_END)                   = 8192
lseek(3, 1024, SEEK_SET)                = 1024
read(3, "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 2048, SEEK_SET)                = 2048
read(3, "\3\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 3072, SEEK_SET)                = 3072
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 4096, SEEK_SET)                = 4096
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5120, SEEK_SET)                = 5120
read(3, "\0\0\0\0\0\0\0\0\2\0\0\0\0\0\0\0\350\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 6144, SEEK_SET)                = 6144
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 7168, SEEK_SET)                = 7168
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
close(3)                                = 0
quotactl(QCMD(Q_GETFMT, GRPQUOTA), "/dev/zd16p1", 0x7ffc259e6a54) = -1 ESRCH (No such process)
openat(AT_FDCWD, "/data/aquota.group", O_RDONLY) = 3
lseek(3, 0, SEEK_SET)                   = 0
read(3, "'\31\300\331\0\0\0\0", 8)      = 8
lseek(3, 8, SEEK_SET)                   = 8
read(3, "\200:\t\0\200:\t\0\0\0\0\0\6\0\0\0\0\0\0\0\5\0\0\0", 24) = 24
lseek(3, 0, SEEK_END)                   = 6144
lseek(3, 1024, SEEK_SET)                = 1024
read(3, "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 2048, SEEK_SET)                = 2048
read(3, "\0\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 3072, SEEK_SET)                = 3072
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 4096, SEEK_SET)                = 4096
read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5120, SEEK_SET)                = 5120
read(3, "\0\0\0\0\0\0\0\0\1\0\0\0\0\0\0\0\240\206\1\0\0\0\0\0\0\0\0\0\4\0\0\0"..., 1024) = 1024
close(3)                                = 0
write(2, "quotacheck: ", 12quotacheck: )            = 12
write(2, "Scanning /dev/zd16p1 [/data] ", 29Scanning /dev/zd16p1 [/data] ) = 29
openat(AT_FDCWD, "/dev/zd16p1", O_RDONLY) = 3
getuid()                                = 0
geteuid()                               = 0
getgid()                                = 0
getegid()                               = 0
prctl(PR_GET_DUMPABLE)                  = 1 (SUID_DUMP_USER)
fstat(3, {st_mode=S_IFBLK|0660, st_rdev=makedev(230, 17), ...}) = 0
ioctl(3, BLKDISCARDZEROES, [0])         = 0
pread64(3, "\0\0\310\0\373\376\37\3\362\377'\0\3564\17\3\364\377\307\0\0\0\0\0\2\0\0\0\2\0\0\0"..., 1024, 1024) = 1024
brk(0x564c22677000)                     = 0x564c22677000
pread64(3, "\32\4\0\0*\4\0\0:\4\0\0\300[\362\37\2\0\4\0\0\0\0\0\33\3660\243\361\37\204\0"..., 102400, 4096) = 102400
mmap(NULL, 1642496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac41ecb000
mmap(NULL, 1642496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac41d3a000
pread64(3, "\0\0\0\0\0\0\0\0\373\250\242\\\373\250\242\\\373\250\242\\\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 4431872) = 4096
munmap(0x7fac41d3a000, 1642496)         = 0
munmap(0x7fac41ecb000, 1642496)         = 0
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
write(1, "done\n", 5done
)                   = 5
stat("/data/aquota.user", {st_mode=S_IFREG|0600, st_size=8192, ...}) = 0
openat(AT_FDCWD, "/data/aquota.user", O_RDONLY) = 3
ioctl(3, FIOQSIZE, 0x7ffc259e69d0)      = 0
close(3)                                = 0
stat("/data/aquota.group", {st_mode=S_IFREG|0600, st_size=6144, ...}) = 0
openat(AT_FDCWD, "/data/aquota.group", O_RDONLY) = 3
ioctl(3, FIOQSIZE, 0x7ffc259e69d0)      = 0
close(3)                                = 0
stat("/data/aquota.user", {st_mode=S_IFREG|0600, st_size=8192, ...}) = 0
openat(AT_FDCWD, "/data/aquota.user", O_RDONLY) = 3
ioctl(3, FIOQSIZE, 0x7ffc259e69d0)      = 0
close(3)                                = 0
stat("/data/aquota.group", {st_mode=S_IFREG|0600, st_size=6144, ...}) = 0
openat(AT_FDCWD, "/data/aquota.group", O_RDONLY) = 3
ioctl(3, FIOQSIZE, 0x7ffc259e69d0)      = 0
close(3)                                = 0
write(2, "quotacheck: ", 12quotacheck: )            = 12
write(2, "Checked 3 directories and 3 file"..., 34Checked 3 directories and 3 files
) = 34
openat(AT_FDCWD, "/data/aquota.user.new", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
flock(3, LOCK_EX)                       = 0
lseek(3, 0, SEEK_SET)                   = 0
write(3, "\21\37\300\331\0\0\0\0", 8)   = 8
lseek(3, 8, SEEK_SET)                   = 8
write(3, "\200:\t\0\200:\t\0\0\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0", 24) = 24
write(2, "quotacheck: ", 12quotacheck: )            = 12
write(2, "Trying to set quota usage out of"..., 81Trying to set quota usage out of range supported by quota format on /dev/zd16p1.
) = 81
lseek(3, 1024, SEEK_SET)                = 1024
read(3, "", 1024)                       = 0
lseek(3, 2048, SEEK_SET)                = 2048
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 3072, SEEK_SET)                = 3072
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 4096, SEEK_SET)                = 4096
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5120, SEEK_SET)                = 5120
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5120, SEEK_SET)                = 5120
write(3, "\0\0\0\0\0\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 4096, SEEK_SET)                = 4096
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 3072, SEEK_SET)                = 3072
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 2048, SEEK_SET)                = 2048
write(3, "\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 1024, SEEK_SET)                = 1024
write(3, "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5136, SEEK_SET)                = 5136
write(3, "\350\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\350\3\0\0\350\3\0\0\0\0\0\0\0\0\0\0"..., 48) = 48
lseek(3, 1024, SEEK_SET)                = 1024
read(3, "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 2048, SEEK_SET)                = 2048
read(3, "\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 6144, SEEK_SET)                = 6144
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 7168, SEEK_SET)                = 7168
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5120, SEEK_SET)                = 5120
read(3, "\0\0\0\0\0\0\0\0\1\0\0\0\0\0\0\0\350\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5120, SEEK_SET)                = 5120
write(3, "\0\0\0\0\0\0\0\0\2\0\0\0\0\0\0\0\350\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 7168, SEEK_SET)                = 7168
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 6144, SEEK_SET)                = 6144
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 2048, SEEK_SET)                = 2048
write(3, "\3\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5184, SEEK_SET)                = 5184
write(3, "\240\206\1\0\0\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0P\0\0\0\0\0\0"..., 48) = 48
lseek(3, 8, SEEK_SET)                   = 8
write(3, "\200:\t\0\200:\t\0\0\0\0\0\10\0\0\0\0\0\0\0\5\0\0\0", 24) = 24
flock(3, LOCK_UN)                       = 0
close(3)                                = 0
quotactl(QCMD(Q_GETFMT, USRQUOTA), "/dev/zd16p1", 0x7ffc259e6a34) = -1 ESRCH (No such process)
stat("/data/aquota.user", {st_mode=S_IFREG|0600, st_size=8192, ...}) = 0
openat(AT_FDCWD, "/data/aquota.user", O_RDONLY) = 3
ioctl(3, FS_IOC_GETFLAGS, 0x7ffc259e5998) = 0
close(3)                                = 0
rename("/data/aquota.user.new", "/data/aquota.user") = 0
chmod("/data/aquota.user", 0600)        = 0
openat(AT_FDCWD, "/data/aquota.user", O_RDONLY) = 3
ioctl(3, FS_IOC_SETFLAGS, 0x7ffc259e5998) = 0
close(3)                                = 0
openat(AT_FDCWD, "/data/aquota.group.new", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
flock(3, LOCK_EX)                       = 0
lseek(3, 0, SEEK_SET)                   = 0
write(3, "'\31\300\331\0\0\0\0", 8)     = 8
lseek(3, 8, SEEK_SET)                   = 8
write(3, "\200:\t\0\200:\t\0\0\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0", 24) = 24
write(2, "quotacheck: ", 12quotacheck: )            = 12
write(2, "Trying to set quota usage out of"..., 81Trying to set quota usage out of range supported by quota format on /dev/zd16p1.
) = 81
lseek(3, 1024, SEEK_SET)                = 1024
read(3, "", 1024)                       = 0
lseek(3, 2048, SEEK_SET)                = 2048
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 3072, SEEK_SET)                = 3072
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 4096, SEEK_SET)                = 4096
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5120, SEEK_SET)                = 5120
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5120, SEEK_SET)                = 5120
write(3, "\0\0\0\0\0\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 4096, SEEK_SET)                = 4096
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 3072, SEEK_SET)                = 3072
write(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 2048, SEEK_SET)                = 2048
write(3, "\0\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 1024, SEEK_SET)                = 1024
write(3, "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
lseek(3, 5136, SEEK_SET)                = 5136
write(3, "\240\206\1\0\0\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0P\0\0\0\0\0\0"..., 48) = 48
lseek(3, 8, SEEK_SET)                   = 8
write(3, "\200:\t\0\200:\t\0\0\0\0\0\6\0\0\0\0\0\0\0\5\0\0\0", 24) = 24
flock(3, LOCK_UN)                       = 0
close(3)                                = 0
quotactl(QCMD(Q_GETFMT, GRPQUOTA), "/dev/zd16p1", 0x7ffc259e6a34) = -1 ESRCH (No such process)
stat("/data/aquota.group", {st_mode=S_IFREG|0600, st_size=6144, ...}) = 0
openat(AT_FDCWD, "/data/aquota.group", O_RDONLY) = 3
ioctl(3, FS_IOC_GETFLAGS, 0x7ffc259e5998) = 0
close(3)                                = 0
rename("/data/aquota.group.new", "/data/aquota.group") = 0
chmod("/data/aquota.group", 0600)       = 0
openat(AT_FDCWD, "/data/aquota.group", O_RDONLY) = 3
ioctl(3, FS_IOC_SETFLAGS, 0x7ffc259e5998) = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
# df -h
Filesystem                         Size  Used Avail Use% Mounted on
pool1/lxd/containers/backup   19G  404M   19G   3% /
none                               492K     0  492K   0% /dev
udev                               7.7G     0  7.7G   0% /dev/tty
tmpfs                              100K     0  100K   0% /dev/lxd
/dev/zd16p1                        196G   61M  186G   1% /data
/dev/sdc2                          117G   12G   99G  11% /dev/zd16p1
tmpfs                              100K     0  100K   0% /dev/.lxd-mounts
tmpfs                              7.7G     0  7.7G   0% /dev/shm
tmpfs                              7.7G  100K  7.7G   1% /run
tmpfs                              5.0M     0  5.0M   0% /run/lock
tmpfs                              7.7G     0  7.7G   0% /sys/fs/cgroup

So the trace does show quotacheck directly opening /dev/zd16p1 as well as stating it (possibly to get its major/minor) and running quotactl syscalls using the path, so that doesn’t look too good for making all this work without providing access to that block device…

I’ll go the libvirt way then.

Wouldn’t ZVOL rootfs support allow that securely ?

No, it wouldn’t, you’d similarly need to expose the block device to the container for the quota tools to work, which means root in the container could mess with the block device and attack the kernel that way.