Re: Regression: Missing check in nfsd_permission() causes -ENOLCK No locks available

NeilBrown
2026-03-04T23:03:28Z

On Tue, 24 Feb 2026, Tj wrote:
> Upstream commit 4cc9b9f2bf4dfe13fe573 "nfsd: refine and rename
> NFSD_MAY_LOCK" and
>  stable v6.12.54 commit 18744bc56b0ec  (re)moves checks from
> fs/nfsd/vfs.c::nfsd_permission().
>
>  This causes NFS clients to see
>
> $ flock -e -w 4 /srv/NAS/test/debian-13.3.0-amd64-netinst.iso sleep 1
> flock: /srv/NAS/test/debian-13.3.0-amd64-netinst.iso: No locks available
>
> Keeping the check in nfsd_permission() whilst also copying it to
> fs/nfsd/nfsfh.c::__fh_verify() resolves the issue.
>
> This was discovered on the Debian openQA infrastructure server when
> upgrading kernel from v6.12.48 to later v6.12.y where worker hosts (with
> any earlier or later kernel version) pass NFSv3 mounted ISO images to
> qemu-system-x86_64 and it reports:
>
> !!! : qemu-system-x86_64: -device
> scsi-cd,id=cd0-device,drive=cd0-overlay0,serial=cd0: Failed to get
> "consistent read" lock: No locks available
> QEMU: Is another process using the image
> [/var/lib/openqa/pool/2/20260223-1-debian-testing-amd64-netinst.iso]?
>
> A simple reproducer with the server using:
>
> # cat /etc/exports.d/test.exports
> /srv/NAS/test
> fdff::/64(fsid=0,rw,no_root_squash,sync,no_subtree_check,auth_nlm)
>
> and clients using:
>
> # mount -t nfs [fdff::2]:/srv/NAS/test /srv/NAS/test -o
> proto=tcp6,ro,fsc,soft

Linux has two quite different sorts of locks - flock and fcntl.
flocks lock the whole file, shared or exclusive.
fcntl can lock any byte-range (including the whole file), shared or
exclusive. flock and fcntl locks don't conflict.

exclusive flock locks only require read access to the file
exclusive fcntl locks require write access to the file.

The NLM protocol only supports one type of byte-range lock. It is
natural to map fcntl locks onto NLM locks. The early Linux NFS
implementation handled flock locks entirely locally so different clients
didn't conflict. This could be confusing but was widely documented and
understood.
Some years ago Linux NFS was enhanced to handle flock locks like
whole-file fcntl locks. This means that clients with flock locks would
conflict (maybe good) but that flock locks and fcntl locks would now
conflict (maybe bad).
You can still get the old behaviour with "-o local_lock=flock".

So if you open a file on NFS read-only and attempt an exclusive flock,
that will be sent to the server as a full-range fcntl lock which should
require write access. If the server finds you don't have write access -
you lose.

It would seems to make sense to tell qemu that the device is read-only.
Then it will hopefully only request a shared lock. Can you try that?

Note that even before my patch, if the filesystem was exported read-only
or mounted read-only on the server, then exclusive flock locks would
fail.

I think that the current behaviour is correct, however I do understand
that it is a regression and maybe that justifies incorrect behaviour.
Maybe Jeff, as locking maintainer, would be willing to do something like

diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index dd0214dcb695..6c674fc51bab 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -73,6 +73,14 @@ static inline unsigned int file_hash(struct nfs_fh *f)

int lock_to_openmode(struct file_lock *lock)
{
+ /*
+ * flock only requires READ access and to support
+ * clients which send flock locks via NLM we
+ * report O_RDONLY for full-file locks.
+ */
+ if (lock->fl_start == 0 &&
+ lock->fl_end == NLM4_OFFSET_MAX)
+ return O_RDONLY;
return lock_is_write(lock) ? O_WRONLY : O_RDONLY;
}

But I wouldn't encourage him to.

NeilBrown

>
> will trigger the error as shown above:
>
> $ flock -e -w 4 /srv/NAS/test/debian-13.3.0-amd64-netinst.iso sleep 1
> flock: /srv/NAS/test/debian-13.3.0-amd64-netinst.iso: No locks available
>
> A simple test program calling fcntl() with the same arguments QEMU uses
> also fails in the same way.
>
> $ ./nfs3_range_lock_test
> /srv/NAS/test/debian-13.3.0-amd64-netinst.{iso,overlay}
> Opened base file: /srv/NAS/test/debian-13.3.0-amd64-netinst.iso
> Opened overlay file: /srv/NAS/test/debian-13.3.0-amd64-netinst.overlay
> Attempting lock at 4 on /srv/NAS/test/debian-13.3.0-amd64-netinst.iso
> fcntl(fd, F_GETLK, &fl) failed on base: No locks available
> Attempting lock at 8 on /srv/NAS/test/debian-13.3.0-amd64-netinst.overlay
> fcntl(fd, F_GETLK, &fl) failed on overlay: No locks available
>
>
>
>