svn commit: r214406 - in head/sys/fs: nfs nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Tue Oct 26 23:18:37 UTC 2010
Author: rmacklem
Date: Tue Oct 26 23:18:37 2010
New Revision: 214406
URL: http://svn.freebsd.org/changeset/base/214406
Log:
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
Modified:
head/sys/fs/nfs/nfsclstate.h
head/sys/fs/nfsclient/nfs_clstate.c
Modified: head/sys/fs/nfs/nfsclstate.h
==============================================================================
--- head/sys/fs/nfs/nfsclstate.h Tue Oct 26 23:06:53 2010 (r214405)
+++ head/sys/fs/nfs/nfsclstate.h Tue Oct 26 23:18:37 2010 (r214406)
@@ -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.
Modified: head/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clstate.c Tue Oct 26 23:06:53 2010 (r214405)
+++ head/sys/fs/nfsclient/nfs_clstate.c Tue Oct 26 23:18:37 2010 (r214406)
@@ -929,8 +929,10 @@ nfscl_getbytelock(vnode_t vp, u_int64_t
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 @@ tryagain:
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, NF
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 *cl
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 *cl
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 *cl
{
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
}
}
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, nfsv4stat
}
}
if (needsrecall && !triedrecall) {
+ dp->nfsdl_flags |= NFSCLDL_DELEGRET;
islept = 0;
while (!igotlock) {
igotlock = nfsv4_lock(&clp->nfsc_lock, 1,
More information about the svn-src-all
mailing list