nfscl: Allow "nolockd" to work for NFSv4 mounts

Commit 40ada74ee1 modified the NFSv4.1/4.2 client so
that it would issue a DestroySession to the server when
all session slots are marked bad.  This handles the
case where session slots get broken when "intr" or "soft"
NFSv4 fairly well.1/4.2 mounts are done.

There are two other cases where having an NFSv4.1/4.2
RPC attempt terminate without completion can leave
state in a non-determinate condition.

One is file locking RPCs.  If the "nolockd" option is
used, this avoids file locking RPCs by doing locking
locally within the client.

The other is Open locks, but since all FreeBSD Open
locks are done with OPEN_SHARE_DENY_NONE, the locking
state for these should not be critical.

This patch enables use of "nolockd" for NFSv4 mounts,
so that it can be combined with "intr" and/or "soft",
making the latter more usable.

Use of "intr" or "soft" NFSv4 mounts are still not
recommended, but when combined with "nolockd" should
now work fairly well.

A man page update will be done as a separate commit.

MFC after:	2 weeks
This commit is contained in:
Rick Macklem 2022-09-04 13:09:33 -07:00
parent 5f285d5537
commit 33721eb991
2 changed files with 28 additions and 28 deletions

View File

@ -2131,8 +2131,8 @@ void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
",noncontigwr", &buf, &blen);
nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
0, ",lockd", &buf, &blen);
nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOLOCKD) != 0, ",nolockd",
&buf, &blen);
nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
&buf, &blen);
nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",

View File

@ -3289,7 +3289,32 @@ nfs_advlock(struct vop_advlock_args *ap)
error = NFSVOPLOCK(vp, LK_SHARED);
if (error != 0)
return (EBADF);
if (NFS_ISV4(vp) && (ap->a_flags & (F_POSIX | F_FLOCK)) != 0) {
nmp = VFSTONFS(vp->v_mount);
if (!NFS_ISV4(vp) || (nmp->nm_flag & NFSMNT_NOLOCKD) != 0) {
if ((nmp->nm_flag & NFSMNT_NOLOCKD) != 0) {
size = np->n_size;
NFSVOPUNLOCK(vp);
error = lf_advlock(ap, &(vp->v_lockf), size);
} else {
if (nfs_advlock_p != NULL)
error = nfs_advlock_p(ap);
else {
NFSVOPUNLOCK(vp);
error = ENOLCK;
}
}
if (error == 0 && ap->a_op == F_SETLK) {
error = NFSVOPLOCK(vp, LK_SHARED);
if (error == 0) {
/* Mark that a file lock has been acquired. */
NFSLOCKNODE(np);
np->n_flag |= NHASBEENLOCKED;
NFSUNLOCKNODE(np);
NFSVOPUNLOCK(vp);
}
}
return (error);
} else if ((ap->a_flags & (F_POSIX | F_FLOCK)) != 0) {
if (vp->v_type != VREG) {
error = EINVAL;
goto out;
@ -3323,7 +3348,6 @@ nfs_advlock(struct vop_advlock_args *ap)
* state structure cannot exist for the file.
* Only done for "oneopenown" NFSv4.1/4.2 mounts.
*/
nmp = VFSTONFS(vp->v_mount);
if (NFSHASNFSV4N(nmp) && NFSHASONEOPENOWN(nmp)) {
NFSLOCKNODE(np);
np->n_flag |= NMIGHTBELOCKED;
@ -3390,30 +3414,6 @@ nfs_advlock(struct vop_advlock_args *ap)
np->n_flag |= NHASBEENLOCKED;
NFSUNLOCKNODE(np);
}
} else if (!NFS_ISV4(vp)) {
if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
size = VTONFS(vp)->n_size;
NFSVOPUNLOCK(vp);
error = lf_advlock(ap, &(vp->v_lockf), size);
} else {
if (nfs_advlock_p != NULL)
error = nfs_advlock_p(ap);
else {
NFSVOPUNLOCK(vp);
error = ENOLCK;
}
}
if (error == 0 && ap->a_op == F_SETLK) {
error = NFSVOPLOCK(vp, LK_SHARED);
if (error == 0) {
/* Mark that a file lock has been acquired. */
NFSLOCKNODE(np);
np->n_flag |= NHASBEENLOCKED;
NFSUNLOCKNODE(np);
NFSVOPUNLOCK(vp);
}
}
return (error);
} else
error = EOPNOTSUPP;
out: