mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
nfsd: Fix Link conformance with RFC8881 for delegations
RFC8881 specifies that, when a Link operation occurs on an NFSv4, that file delegations issued to other clients must be recalled. Discovered during a recent discussion on nfsv4@ietf.org. Although I have not observed a problem caused by not doing the required delegation recall, it is definitely required by the RFC, so this patch makes the server do the recall. Tested during a recent NFSv4 IETF Bakeathon event. MFC after: 1 week
This commit is contained in:
parent
6f44401900
commit
3f65000b6b
|
@ -713,7 +713,7 @@ int nfsvno_rmdirsub(struct nameidata *, int, struct ucred *, NFSPROC_T *,
|
|||
struct nfsexstuff *);
|
||||
int nfsvno_rename(struct nameidata *, struct nameidata *, u_int32_t,
|
||||
u_int32_t, struct ucred *, NFSPROC_T *);
|
||||
int nfsvno_link(struct nameidata *, vnode_t, struct ucred *,
|
||||
int nfsvno_link(struct nameidata *, vnode_t, nfsquad_t, struct ucred *,
|
||||
NFSPROC_T *, struct nfsexstuff *);
|
||||
int nfsvno_fsync(vnode_t, u_int64_t, int, struct ucred *, NFSPROC_T *);
|
||||
int nfsvno_statfs(vnode_t, struct statfs *);
|
||||
|
|
|
@ -1655,8 +1655,8 @@ nfsvno_rename(struct nameidata *fromndp, struct nameidata *tondp,
|
|||
* Link vnode op.
|
||||
*/
|
||||
int
|
||||
nfsvno_link(struct nameidata *ndp, struct vnode *vp, struct ucred *cred,
|
||||
struct thread *p, struct nfsexstuff *exp)
|
||||
nfsvno_link(struct nameidata *ndp, struct vnode *vp, nfsquad_t clientid,
|
||||
struct ucred *cred, struct thread *p, struct nfsexstuff *exp)
|
||||
{
|
||||
struct vnode *xp;
|
||||
int error = 0;
|
||||
|
@ -1671,9 +1671,11 @@ nfsvno_link(struct nameidata *ndp, struct vnode *vp, struct ucred *cred,
|
|||
}
|
||||
if (!error) {
|
||||
NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
if (!VN_IS_DOOMED(vp))
|
||||
if (!VN_IS_DOOMED(vp)) {
|
||||
error = nfsrv_checkremove(vp, 0, NULL, clientid, p);
|
||||
if (error == 0)
|
||||
error = VOP_LINK(ndp->ni_dvp, vp, &ndp->ni_cnd);
|
||||
else
|
||||
} else
|
||||
error = EPERM;
|
||||
if (ndp->ni_dvp == vp) {
|
||||
vrele(ndp->ni_dvp);
|
||||
|
|
|
@ -1797,6 +1797,7 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
|
|||
char *bufp;
|
||||
u_long *hashp;
|
||||
struct thread *p = curthread;
|
||||
nfsquad_t clientid;
|
||||
|
||||
if (nd->nd_repstat) {
|
||||
nfsrv_postopattr(nd, getret, &at);
|
||||
|
@ -1858,8 +1859,14 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
|
|||
NULL);
|
||||
}
|
||||
}
|
||||
if (!nd->nd_repstat)
|
||||
nd->nd_repstat = nfsvno_link(&named, vp, nd->nd_cred, p, exp);
|
||||
if (!nd->nd_repstat) {
|
||||
clientid.qval = 0;
|
||||
if ((nd->nd_flag & (ND_IMPLIEDCLID | ND_NFSV41)) ==
|
||||
(ND_IMPLIEDCLID | ND_NFSV41))
|
||||
clientid.qval = nd->nd_clientid.qval;
|
||||
nd->nd_repstat = nfsvno_link(&named, vp, clientid, nd->nd_cred,
|
||||
p, exp);
|
||||
}
|
||||
if (nd->nd_flag & ND_NFSV3)
|
||||
getret = nfsvno_getattr(vp, &at, nd, p, 0, NULL);
|
||||
if (dirp) {
|
||||
|
|
Loading…
Reference in a new issue