13879 flock(3C) on NFS files should fail with EOPNOTSUPP
Reviewed by: Andy Stormont <andyjstormont@gmail.com>
Approved by: Dan McDonald <danmcd@mnx.io>
diff --git a/usr/src/man/man2/fcntl.2 b/usr/src/man/man2/fcntl.2
index f178315..5426f56 100644
--- a/usr/src/man/man2/fcntl.2
+++ b/usr/src/man/man2/fcntl.2
@@ -45,12 +45,12 @@
 .\" Copyright (c) 2007, Sun Microsystems, Inc.  All Rights Reserved.
 .\" Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
 .\" Copyright 2015 Joyent, Inc.
+.\" Copyright 2022 Oxide Computer Company
 .\"
 .TH FCNTL 2 "Feb 16, 2015"
 .SH NAME
 fcntl \- file control
 .SH SYNOPSIS
-.LP
 .nf
 #include <sys/types.h>
 #include <unistd.h>
@@ -60,7 +60,6 @@
 .fi
 
 .SH DESCRIPTION
-.LP
 The \fBfcntl()\fR function provides for control over open files. The
 \fIfildes\fR argument is an open file descriptor.
 .sp
@@ -461,7 +460,6 @@
 .RE
 
 .SH FILE LOCKING
-.LP
 Two types of file locks are supported: POSIX-style and OFD-style. OFD-style
 locks are associated with the open file description (not descriptor) instead
 of with a process. Either type is advisory by default, but POSIX-style locks
@@ -616,7 +614,6 @@
 performed when attempting to set an OFD-style lock.
 
 .SH SHARE RESERVATIONS
-.LP
 File share reservations are an advisory form of access control among
 cooperating processes, on both local and remote machines. They are most often
 used by \fBDOS\fR or Windows emulators and \fBDOS based\fR \fBNFS\fR clients.
@@ -727,7 +724,6 @@
 .RE
 
 .SH RETURN VALUES
-.LP
 Upon successful completion, the value returned depends on \fIcmd\fR as follows:
 .sp
 .ne 2
@@ -945,7 +941,6 @@
 Otherwise, \fB\(mi1\fR is returned and \fBerrno\fR is set to indicate the
 error.
 .SH ERRORS
-.LP
 The \fBfcntl()\fR function will fail if:
 .sp
 .ne 2
@@ -1140,8 +1135,19 @@
 detected.
 .RE
 
+.sp
+.ne 2
+.na
+\fB\fBEOPNOTSUPP\fR
+.ad
+.RS 11n
+The \fIcmd\fR argument is \fBF_OFD_GETLK\fR, \fBF_OFD_GETLK64\fR,
+\fBF_OFD_SETLK\fR, \fBF_OFD_SETLK64\fR, \fBF_OFD_SETLKW\fR, or
+\fBF_OFD_SETLKW64\fR and the locking of files of the type indicated by the
+\fIfildes\fR argument is not supported.
+.RE
+
 .SH ATTRIBUTES
-.LP
 See \fBattributes\fR(7) for descriptions of the following attributes:
 .sp
 
@@ -1158,7 +1164,6 @@
 .TE
 
 .SH SEE ALSO
-.LP
 .BR chmod (2),
 .BR close (2),
 .BR creat (2),
@@ -1183,7 +1188,6 @@
 .LP
 \fIProgramming Interfaces Guide\fR
 .SH NOTES
-.LP
 In the past, the variable \fBerrno\fR was set to \fBEACCES\fR rather than
 \fBEAGAIN\fR when a section of a file is already locked by another process.
 Therefore, portable application programs should expect and test for either
diff --git a/usr/src/uts/common/fs/fs_subr.c b/usr/src/uts/common/fs/fs_subr.c
index e3d07b59..0682c96 100644
--- a/usr/src/uts/common/fs/fs_subr.c
+++ b/usr/src/uts/common/fs/fs_subr.c
@@ -19,13 +19,14 @@
  * CDDL HEADER END
  */
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
-/*	  All Rights Reserved  	*/
+/*	All Rights Reserved	*/
 
 
 /*
  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2017 Joyent, Inc.
+ * Copyright 2022 Oxide Computer Company
  */
 
 /*
@@ -256,7 +257,7 @@
 		 * TBD we do not support remote OFD locks at this time.
 		 */
 		if (flag & (F_REMOTELOCK | F_PXFSLOCK)) {
-			error = EINVAL;
+			error = EOPNOTSUPP;
 			goto done;
 		}
 		skip_lock = B_TRUE;
@@ -331,7 +332,7 @@
 		 * TBD we do not support remote OFD locks at this time.
 		 */
 		if (flag & (F_REMOTELOCK | F_PXFSLOCK)) {
-			error = EINVAL;
+			error = EOPNOTSUPP;
 			goto done;
 		}
 		skip_lock = B_TRUE;
@@ -740,8 +741,8 @@
 {
 	ulong_t		acl_styles;
 	ulong_t		acl_flavor;
-	vsecattr_t 	vsecattr;
-	int 		error;
+	vsecattr_t	vsecattr;
+	int		error;
 	int		isnontrivial;
 
 	/* determine the forms of ACLs maintained */
diff --git a/usr/src/uts/common/fs/nfs/nfs3_vnops.c b/usr/src/uts/common/fs/nfs/nfs3_vnops.c
index b7354c1..74d47dd 100644
--- a/usr/src/uts/common/fs/nfs/nfs3_vnops.c
+++ b/usr/src/uts/common/fs/nfs/nfs3_vnops.c
@@ -31,6 +31,7 @@
 /*
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2022 Oxide Computer Company
  */
 
 #include <sys/param.h>
@@ -275,7 +276,7 @@
 	VOPNAME_SETSECATTR,	{ .vop_setsecattr = nfs3_setsecattr },
 	VOPNAME_GETSECATTR,	{ .vop_getsecattr = nfs3_getsecattr },
 	VOPNAME_SHRLOCK,	{ .vop_shrlock = nfs3_shrlock },
-	VOPNAME_VNEVENT, 	{ .vop_vnevent = fs_vnevent_support },
+	VOPNAME_VNEVENT,	{ .vop_vnevent = fs_vnevent_support },
 	NULL,			NULL
 };
 
@@ -342,7 +343,7 @@
 /* ARGSUSED */
 static int
 nfs3_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
-		caller_context_t *ct)
+    caller_context_t *ct)
 {
 	rnode_t *rp;
 	int error;
@@ -538,7 +539,7 @@
 /* ARGSUSED */
 static int
 nfs3_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	rnode_t *rp;
 	u_offset_t off;
@@ -647,7 +648,7 @@
 /* ARGSUSED */
 static int
 nfs3_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	rlim64_t limit = uiop->uio_llimit;
 	rnode_t *rp;
@@ -928,7 +929,7 @@
  */
 static int
 nfs3_rdwrlbn(vnode_t *vp, page_t *pp, u_offset_t off, size_t len,
-	int flags, cred_t *cr)
+    int flags, cred_t *cr)
 {
 	struct buf *bp;
 	int error;
@@ -1000,7 +1001,7 @@
  */
 static int
 nfs3write(vnode_t *vp, caddr_t base, u_offset_t offset, int count, cred_t *cr,
-	stable_how *stab_comm)
+    stable_how *stab_comm)
 {
 	mntinfo_t *mi;
 	WRITE3args args;
@@ -1125,8 +1126,8 @@
  * Read from a file.  Reads data in largest chunks our interface can handle.
  */
 static int
-nfs3read(vnode_t *vp, caddr_t base, offset_t offset, int count,
-	size_t *residp, cred_t *cr)
+nfs3read(vnode_t *vp, caddr_t base, offset_t offset, int count, size_t *residp,
+    cred_t *cr)
 {
 	mntinfo_t *mi;
 	READ3args args;
@@ -1235,7 +1236,7 @@
 /* ARGSUSED */
 static int
 nfs3_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 
 	if (nfs_zone() != VTOMI(vp)->mi_zone)
@@ -1251,7 +1252,7 @@
 /* ARGSUSED */
 static int
 nfs3_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	int error;
 	rnode_t *rp;
@@ -1312,7 +1313,7 @@
 /*ARGSUSED4*/
 static int
 nfs3_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
-		caller_context_t *ct)
+    caller_context_t *ct)
 {
 	int error;
 	struct vattr va;
@@ -1921,8 +1922,8 @@
 /* ARGSUSED */
 static int
 nfs3_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
-	int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
-	int *direntflags, pathname_t *realpnp)
+    int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
+    int *direntflags, pathname_t *realpnp)
 {
 	int error;
 	vnode_t *vp;
@@ -2006,7 +2007,7 @@
 /* ARGSUSED */
 int
 nfs3lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
-	int flags, vnode_t *rdir, cred_t *cr, int rfscall_flags)
+    int flags, vnode_t *rdir, cred_t *cr, int rfscall_flags)
 {
 	int error;
 	rnode_t *drp;
@@ -2140,7 +2141,7 @@
 
 static int
 nfs3lookup_otw(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
-	int rfscall_flags)
+    int rfscall_flags)
 {
 	int error;
 	LOOKUP3args args;
@@ -2222,8 +2223,8 @@
 /* ARGSUSED */
 static int
 nfs3_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
-	int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
-	vsecattr_t *vsecp)
+    int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
+    vsecattr_t *vsecp)
 {
 	int error;
 	vnode_t *vp;
@@ -2396,7 +2397,7 @@
 /* ARGSUSED */
 static int
 nfs3create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
-	int mode, vnode_t **vpp, cred_t *cr, int lfaware)
+    int mode, vnode_t **vpp, cred_t *cr, int lfaware)
 {
 	int error;
 	CREATE3args args;
@@ -2714,7 +2715,7 @@
 /* ARGSUSED */
 static int
 nfs3mknod(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
-	int mode, vnode_t **vpp, cred_t *cr)
+    int mode, vnode_t **vpp, cred_t *cr)
 {
 	int error;
 	MKNOD3args args;
@@ -2973,7 +2974,7 @@
 /* ARGSUSED */
 static int
 nfs3_link(vnode_t *tdvp, vnode_t *svp, char *tnm, cred_t *cr,
-	caller_context_t *ct, int flags)
+    caller_context_t *ct, int flags)
 {
 	int error;
 	LINK3args args;
@@ -3052,7 +3053,7 @@
 /* ARGSUSED */
 static int
 nfs3_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
-	caller_context_t *ct, int flags)
+    caller_context_t *ct, int flags)
 {
 	vnode_t *realvp;
 
@@ -3373,7 +3374,7 @@
 /* ARGSUSED */
 static int
 nfs3_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp, cred_t *cr,
-	caller_context_t *ct, int flags, vsecattr_t *vsecp)
+    caller_context_t *ct, int flags, vsecattr_t *vsecp)
 {
 	int error;
 	MKDIR3args args;
@@ -3478,7 +3479,7 @@
 /* ARGSUSED */
 static int
 nfs3_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
-	caller_context_t *ct, int flags)
+    caller_context_t *ct, int flags)
 {
 	int error;
 	RMDIR3args args;
@@ -3583,7 +3584,7 @@
 /* ARGSUSED */
 static int
 nfs3_symlink(vnode_t *dvp, char *lnm, struct vattr *tva, char *tnm, cred_t *cr,
-	caller_context_t *ct, int flags)
+    caller_context_t *ct, int flags)
 {
 	int error;
 	SYMLINK3args args;
@@ -3714,7 +3715,7 @@
 /* ARGSUSED */
 static int
 nfs3_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp,
-	caller_context_t *ct, int flags)
+    caller_context_t *ct, int flags)
 {
 	int error;
 	size_t count;
@@ -4530,8 +4531,8 @@
 /* ARGSUSED */
 static int
 nfs3_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
-	page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
-	enum seg_rw rw, cred_t *cr, caller_context_t *ct)
+    page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
+    enum seg_rw rw, cred_t *cr, caller_context_t *ct)
 {
 	rnode_t *rp;
 	int error;
@@ -4606,8 +4607,8 @@
 /* ARGSUSED */
 static int
 nfs3_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp,
-	page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
-	enum seg_rw rw, cred_t *cr)
+    page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
+    enum seg_rw rw, cred_t *cr)
 {
 	rnode_t *rp;
 	uint_t bsize;
@@ -4875,7 +4876,7 @@
 
 static void
 nfs3_readahead(vnode_t *vp, u_offset_t blkoff, caddr_t addr, struct seg *seg,
-	cred_t *cr)
+    cred_t *cr)
 {
 	int error;
 	page_t *pp;
@@ -4992,7 +4993,7 @@
 /* ARGSUSED */
 static int
 nfs3_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	int error;
 	rnode_t *rp;
@@ -5027,7 +5028,7 @@
  */
 int
 nfs3_putapage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
-	int flags, cred_t *cr)
+    int flags, cred_t *cr)
 {
 	u_offset_t io_off;
 	u_offset_t lbn_off;
@@ -5148,7 +5149,7 @@
 
 static int
 nfs3_sync_putapage(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len,
-	int flags, cred_t *cr)
+    int flags, cred_t *cr)
 {
 	int error;
 	rnode_t *rp;
@@ -5211,8 +5212,8 @@
 /* ARGSUSED */
 static int
 nfs3_map(vnode_t *vp, offset_t off, struct as *as, caddr_t *addrp,
-	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
-	cred_t *cr, caller_context_t *ct)
+    size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
+    cred_t *cr, caller_context_t *ct)
 {
 	struct segvn_crargs vn_a;
 	int error;
@@ -5325,8 +5326,8 @@
 /* ARGSUSED */
 static int
 nfs3_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
-	size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
-	cred_t *cr, caller_context_t *ct)
+    size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
+    cred_t *cr, caller_context_t *ct)
 {
 	rnode_t *rp;
 
@@ -5344,8 +5345,8 @@
 /* ARGSUSED */
 static int
 nfs3_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
-	offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
-	caller_context_t *ct)
+    offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
+    caller_context_t *ct)
 {
 	netobj lm_fh3;
 	int rc;
@@ -5355,9 +5356,22 @@
 
 	if (nfs_zone() != VTOMI(vp)->mi_zone)
 		return (EIO);
+
 	/* check for valid cmd parameter */
-	if (cmd != F_GETLK && cmd != F_SETLK && cmd != F_SETLKW)
+	switch (cmd) {
+	case F_FLOCK:
+	case F_FLOCKW:
+	case F_OFD_GETLK:
+	case F_OFD_SETLK:
+	case F_OFD_SETLKW:
+		return (EOPNOTSUPP);
+	case F_GETLK:
+	case F_SETLK:
+	case F_SETLKW:
+		break;
+	default:
 		return (EINVAL);
+	}
 
 	/* Verify l_type. */
 	switch (bfp->l_type) {
@@ -5494,7 +5508,7 @@
 /* ARGSUSED */
 static int
 nfs3_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
-	offset_t offset, cred_t *cr, caller_context_t *ct)
+    offset_t offset, cred_t *cr, caller_context_t *ct)
 {
 	int error;
 
@@ -5553,8 +5567,8 @@
 /* ARGSUSED */
 static int
 nfs3_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
-	size_t len, uint_t prot, uint_t maxprot, uint_t flags,
-	cred_t *cr, caller_context_t *ct)
+    size_t len, uint_t prot, uint_t maxprot, uint_t flags,
+    cred_t *cr, caller_context_t *ct)
 {
 	int			caller_found;
 	int			error;
@@ -5716,7 +5730,7 @@
 /* ARGSUSED */
 static int
 nfs3_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	int error;
 	PATHCONF3args args;
@@ -5914,7 +5928,7 @@
  */
 static int
 nfs3_sync_pageio(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len,
-	int flags, cred_t *cr)
+    int flags, cred_t *cr)
 {
 	int error;
 
@@ -5930,7 +5944,7 @@
 /* ARGSUSED */
 static int
 nfs3_pageio(vnode_t *vp, page_t *pp, u_offset_t io_off, size_t io_len,
-	int flags, cred_t *cr, caller_context_t *ct)
+    int flags, cred_t *cr, caller_context_t *ct)
 {
 	int error;
 	rnode_t *rp;
@@ -5960,7 +5974,7 @@
 /* ARGSUSED */
 static void
 nfs3_dispose(vnode_t *vp, page_t *pp, int fl, int dn, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	int error;
 	rnode_t *rp;
@@ -6568,7 +6582,7 @@
 
 static int
 nfs3_sync_commit(vnode_t *vp, page_t *plist, offset3 offset, count3 count,
-	cred_t *cr)
+    cred_t *cr)
 {
 	int error;
 	page_t *pp;
@@ -6605,7 +6619,7 @@
 
 static void
 nfs3_async_commit(vnode_t *vp, page_t *plist, offset3 offset, count3 count,
-	cred_t *cr)
+    cred_t *cr)
 {
 	ASSERT(nfs_zone() == VTOMI(vp)->mi_zone);
 	(void) nfs3_sync_commit(vp, plist, offset, count, cr);
@@ -6614,7 +6628,7 @@
 /* ARGSUSED */
 static int
 nfs3_setsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	int error;
 	mntinfo_t *mi;
@@ -6636,7 +6650,7 @@
 /* ARGSUSED */
 static int
 nfs3_getsecattr(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	int error;
 	mntinfo_t *mi;
@@ -6658,7 +6672,7 @@
 /* ARGSUSED */
 static int
 nfs3_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	int error;
 	struct shrlock nshr;
diff --git a/usr/src/uts/common/fs/nfs/nfs4_vnops.c b/usr/src/uts/common/fs/nfs/nfs4_vnops.c
index db93bf2..2a501bc 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_vnops.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_vnops.c
@@ -39,6 +39,7 @@
 
 /*
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2022 Oxide Computer Company
  */
 
 #include <sys/param.h>
@@ -10849,8 +10850,20 @@
 		return (EIO);
 
 	/* check for valid cmd parameter */
-	if (cmd != F_GETLK && cmd != F_SETLK && cmd != F_SETLKW)
+	switch (cmd) {
+	case F_FLOCK:
+	case F_FLOCKW:
+	case F_OFD_GETLK:
+	case F_OFD_SETLK:
+	case F_OFD_SETLKW:
+		return (EOPNOTSUPP);
+	case F_GETLK:
+	case F_SETLK:
+	case F_SETLKW:
+		break;
+	default:
 		return (EINVAL);
+	}
 
 	/* Verify l_type. */
 	switch (bfp->l_type) {