mirror of
https://git.freebsd.org/src.git
synced 2026-01-16 23:02:24 +00:00
nfs_clrpcops.c: Fix acquisition of post-op attributes for link
Without this patch, the link RPC (done by nfsrpc_link()) did not acquire post link operation attributes for the file object for NFSv4. For some recent Linux NFSv4 servers that support delegations, this would result in the client's cached attribute for st_nlinks not being increased right away, because the delegation would indicate that the now stale cached attributes were still valid. This patch fixes the problem by acquiring post link attributes and updating the client's cached copy in the same manner as the NFSv3 RPC did. Detected at the recent NFSv4 Bakeathon testing event. Applications will only be affected if they examine st_nlinks after a new hard link is created for a file object. MFC after: 2 weeks
This commit is contained in:
parent
ecc352af59
commit
772258c89f
2 changed files with 28 additions and 14 deletions
|
|
@ -254,7 +254,7 @@ static struct {
|
|||
{ NFSV4OP_REMOVE, 1, "Remove", 6, },
|
||||
{ NFSV4OP_REMOVE, 1, "Remove", 6, },
|
||||
{ NFSV4OP_SAVEFH, 5, "Rename", 6, },
|
||||
{ NFSV4OP_SAVEFH, 4, "Link", 4, },
|
||||
{ NFSV4OP_SAVEFH, 6, "Link", 4, },
|
||||
{ NFSV4OP_READDIR, 2, "Readdir", 7, },
|
||||
{ NFSV4OP_READDIR, 2, "Readdir", 7, },
|
||||
{ NFSV4OP_GETATTR, 1, "Getattr", 7, },
|
||||
|
|
|
|||
|
|
@ -3113,15 +3113,20 @@ nfsrpc_link(vnode_t dvp, vnode_t vp, char *name, int namelen,
|
|||
(void)nfsm_fhtom(VFSTONFS(dvp->v_mount), nd, VTONFS(dvp)->n_fhp->nfh_fh,
|
||||
VTONFS(dvp)->n_fhp->nfh_len, 0);
|
||||
if (nd->nd_flag & ND_NFSV4) {
|
||||
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(NFSV4OP_GETATTR);
|
||||
NFSWCCATTR_ATTRBIT(&attrbits);
|
||||
(void) nfsrv_putattrbit(nd, &attrbits);
|
||||
nd->nd_flag |= ND_V4WCCATTR;
|
||||
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(NFSV4OP_LINK);
|
||||
}
|
||||
(void) nfsm_strtom(nd, name, namelen);
|
||||
if (nd->nd_flag & ND_NFSV4) {
|
||||
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
*tl = txdr_unsigned(NFSV4OP_GETATTR);
|
||||
NFSGETATTR_ATTRBIT(&attrbits);
|
||||
(void)nfsrv_putattrbit(nd, &attrbits);
|
||||
NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
||||
*tl++ = txdr_unsigned(NFSV4OP_RESTOREFH);
|
||||
*tl = txdr_unsigned(NFSV4OP_GETATTR);
|
||||
(void)nfsrv_putattrbit(nd, &attrbits);
|
||||
}
|
||||
error = nfscl_request(nd, vp, p, cred);
|
||||
if (error)
|
||||
return (error);
|
||||
|
|
@ -3130,19 +3135,28 @@ nfsrpc_link(vnode_t dvp, vnode_t vp, char *name, int namelen,
|
|||
if (!error)
|
||||
error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp,
|
||||
NULL, NULL);
|
||||
} else if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4) {
|
||||
} else if (nd->nd_repstat == 0 && (nd->nd_flag & ND_NFSV4) != 0) {
|
||||
/*
|
||||
* First, parse out the PutFH and Getattr result.
|
||||
* First and parse out the PutFH and Link results.
|
||||
*/
|
||||
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
|
||||
if (!(*(tl + 1)))
|
||||
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
|
||||
if (*(tl + 1))
|
||||
NFSM_DISSECT(tl, uint32_t *, 5 * NFSX_UNSIGNED +
|
||||
2 * NFSX_HYPER);
|
||||
if (*(tl + 3))
|
||||
nd->nd_flag |= ND_NOMOREDATA;
|
||||
/*
|
||||
* Get the pre-op attributes.
|
||||
* Get the directory post-op attributes.
|
||||
*/
|
||||
error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
|
||||
if ((nd->nd_flag & ND_NOMOREDATA) == 0)
|
||||
error = nfscl_postop_attr(nd, dnap, dattrflagp);
|
||||
if (error == 0 && (nd->nd_flag & ND_NOMOREDATA) == 0) {
|
||||
/* Get rid of the RestoreFH reply. */
|
||||
NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
|
||||
if (*(tl + 1))
|
||||
nd->nd_flag |= ND_NOMOREDATA;
|
||||
}
|
||||
/* Get the file's post-op attributes. */
|
||||
if (error == 0 && (nd->nd_flag & ND_NOMOREDATA) == 0)
|
||||
error = nfscl_postop_attr(nd, nap, attrflagp);
|
||||
}
|
||||
if (nd->nd_repstat && !error)
|
||||
error = nd->nd_repstat;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue