1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-20 11:11:24 +00:00

Add a flag to the experimental NFSv4 client to indicate when

delegations are being returned for reasons other than a Recall.
Also, re-organize nfscl_recalldeleg() slightly, so that it leaves
clearing NMODIFIED to the ncl_flush() call and invalidates the
attribute cache after flushing. It is hoped that these changes
might fix the problem others have seen when using the NFSv4
client with delegations enabled, since I can't reliably reproduce
the problem. These changes only affect the client when doing NFSv4
mounts with delegations enabled.

MFC after:	10 days
This commit is contained in:
Rick Macklem 2010-10-26 23:18:37 +00:00
parent 240dd5b5aa
commit c5dd9d8c37
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=214406
2 changed files with 24 additions and 22 deletions

View File

@ -118,6 +118,7 @@ struct nfscldeleg {
#define NFSCLDL_NEEDRECLAIM 0x08
#define NFSCLDL_ZAPPED 0x10
#define NFSCLDL_MODTIMESET 0x20
#define NFSCLDL_DELEGRET 0x40
/*
* MALLOC'd to the correct length to accommodate the file handle.

View File

@ -929,8 +929,10 @@ nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
ldp = dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh,
np->n_fhp->nfh_len);
/* Just sanity check for correct type of delegation */
if (dp != NULL && ((dp->nfsdl_flags & NFSCLDL_RECALL) ||
(type == F_WRLCK && !(dp->nfsdl_flags & NFSCLDL_WRITE))))
if (dp != NULL && ((dp->nfsdl_flags &
(NFSCLDL_RECALL | NFSCLDL_DELEGRET)) != 0 ||
(type == F_WRLCK &&
(dp->nfsdl_flags & NFSCLDL_WRITE) == 0)))
dp = NULL;
}
if (dp != NULL) {
@ -2495,8 +2497,8 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p)
if (dp->nfsdl_rwlock.nfslock_usecnt == 0 &&
dp->nfsdl_rwlock.nfslock_lock == 0 &&
dp->nfsdl_timestamp < NFSD_MONOSEC &&
!(dp->nfsdl_flags & (NFSCLDL_RECALL | NFSCLDL_ZAPPED |
NFSCLDL_NEEDRECLAIM))) {
(dp->nfsdl_flags & (NFSCLDL_RECALL | NFSCLDL_ZAPPED |
NFSCLDL_NEEDRECLAIM | NFSCLDL_DELEGRET)) == 0) {
clearok = 1;
LIST_FOREACH(owp, &dp->nfsdl_owner, nfsow_list) {
op = LIST_FIRST(&owp->nfsow_open);
@ -3086,7 +3088,8 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
if (clp != NULL) {
dp = nfscl_finddeleg(clp, nfhp->nfh_fh,
nfhp->nfh_len);
if (dp != NULL) {
if (dp != NULL && (dp->nfsdl_flags &
NFSCLDL_DELEGRET) == 0) {
dp->nfsdl_flags |=
NFSCLDL_RECALL;
wakeup((caddr_t)clp);
@ -3338,7 +3341,6 @@ nfscl_recalldeleg(struct nfsclclient *clp, struct nfsmount *nmp,
np = VTONFS(vp);
}
dp->nfsdl_flags &= ~NFSCLDL_MODTIMESET;
NFSINVALATTRCACHE(np);
/*
* Ok, if it's a write delegation, flush data to the server, so
@ -3347,21 +3349,14 @@ nfscl_recalldeleg(struct nfsclclient *clp, struct nfsmount *nmp,
ret = 0;
NFSLOCKNODE(np);
if ((dp->nfsdl_flags & NFSCLDL_WRITE) && (np->n_flag & NMODIFIED)) {
#ifdef APPLE
OSBitOrAtomic((u_int32_t)NDELEGRECALL, (UInt32 *)&np->n_flag);
#else
np->n_flag |= NDELEGRECALL;
#endif
NFSUNLOCKNODE(np);
ret = ncl_flush(vp, MNT_WAIT, cred, p, 1,
called_from_renewthread);
NFSLOCKNODE(np);
#ifdef APPLE
OSBitAndAtomic((int32_t)~(NMODIFIED | NDELEGRECALL), (UInt32 *)&np->n_flag);
#else
np->n_flag &= ~(NMODIFIED | NDELEGRECALL);
#endif
np->n_flag &= ~NDELEGRECALL;
}
NFSINVALATTRCACHE(np);
NFSUNLOCKNODE(np);
if (ret == EIO && called_from_renewthread != 0) {
/*
@ -3534,8 +3529,10 @@ nfscl_totalrecall(struct nfsclclient *clp)
{
struct nfscldeleg *dp;
TAILQ_FOREACH(dp, &clp->nfsc_deleg, nfsdl_list)
dp->nfsdl_flags |= NFSCLDL_RECALL;
TAILQ_FOREACH(dp, &clp->nfsc_deleg, nfsdl_list) {
if ((dp->nfsdl_flags & NFSCLDL_DELEGRET) == 0)
dp->nfsdl_flags |= NFSCLDL_RECALL;
}
}
/*
@ -3754,8 +3751,9 @@ nfscl_mustflush(vnode_t vp)
return (1);
}
dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
if (dp != NULL && (dp->nfsdl_flags & (NFSCLDL_WRITE | NFSCLDL_RECALL))
== NFSCLDL_WRITE &&
if (dp != NULL && (dp->nfsdl_flags &
(NFSCLDL_WRITE | NFSCLDL_RECALL | NFSCLDL_DELEGRET)) ==
NFSCLDL_WRITE &&
(dp->nfsdl_sizelimit >= np->n_size ||
!NFSHASSTRICT3530(nmp))) {
NFSUNLOCKCLSTATE();
@ -3787,9 +3785,10 @@ nfscl_nodeleg(vnode_t vp, int writedeleg)
return (1);
}
dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_RECALL) == 0 &&
(writedeleg == 0 || (dp->nfsdl_flags & NFSCLDL_WRITE)
== NFSCLDL_WRITE)) {
if (dp != NULL &&
(dp->nfsdl_flags & (NFSCLDL_RECALL | NFSCLDL_DELEGRET)) == 0 &&
(writedeleg == 0 || (dp->nfsdl_flags & NFSCLDL_WRITE) ==
NFSCLDL_WRITE)) {
NFSUNLOCKCLSTATE();
return (0);
}
@ -3860,6 +3859,7 @@ nfscl_removedeleg(vnode_t vp, NFSPROC_T *p, nfsv4stateid_t *stp)
}
}
if (needsrecall && !triedrecall) {
dp->nfsdl_flags |= NFSCLDL_DELEGRET;
islept = 0;
while (!igotlock) {
igotlock = nfsv4_lock(&clp->nfsc_lock, 1,
@ -3958,6 +3958,7 @@ nfscl_renamedeleg(vnode_t fvp, nfsv4stateid_t *fstp, int *gotfdp, vnode_t tvp,
}
}
if (needsrecall && !triedrecall) {
dp->nfsdl_flags |= NFSCLDL_DELEGRET;
islept = 0;
while (!igotlock) {
igotlock = nfsv4_lock(&clp->nfsc_lock, 1,