Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 May 2013 00:09:39 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r250920 - in projects/nfsv4-packrats/sys/fs: nfs nfsclient
Message-ID:  <201305230009.r4N09d0X030400@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Thu May 23 00:09:38 2013
New Revision: 250920
URL: http://svnweb.freebsd.org/changeset/base/250920

Log:
  Update packrats to add some of the code needed for client
  reboot recovery. Also enable read delegations, since they
  are useful for packrat caching.

Modified:
  projects/nfsv4-packrats/sys/fs/nfs/nfs_var.h
  projects/nfsv4-packrats/sys/fs/nfs/nfsclstate.h
  projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clpackrat.c
  projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clrpcops.c
  projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clstate.c
  projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clvnops.c

Modified: projects/nfsv4-packrats/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/nfsv4-packrats/sys/fs/nfs/nfs_var.h	Wed May 22 22:34:48 2013	(r250919)
+++ projects/nfsv4-packrats/sys/fs/nfs/nfs_var.h	Thu May 23 00:09:38 2013	(r250920)
@@ -501,8 +501,8 @@ void nfscl_dupopen(vnode_t, int);
 int nfscl_getclose(vnode_t, struct nfsclclient **);
 int nfscl_doclose(vnode_t, struct nfsclclient **, NFSPROC_T *);
 void nfsrpc_doclose(struct nfsmount *, struct nfsclopen *, NFSPROC_T *);
-int nfscl_deleg(mount_t, struct nfsclclient *, u_int8_t *, int,
-    struct ucred *, NFSPROC_T *, struct nfscldeleg **);
+int nfscl_deleg(mount_t, struct nfsclclient *, u_int8_t *, int, u_int8_t *, int,
+    u_int8_t *, int, struct ucred *, NFSPROC_T *, struct nfscldeleg **);
 void nfscl_lockinit(struct nfsv4lock *);
 void nfscl_lockexcl(struct nfsv4lock *, void *);
 void nfscl_lockunlock(struct nfsv4lock *);
@@ -657,8 +657,8 @@ int nfscbd_addsock(struct file *);
 int nfscbd_nfsd(NFSPROC_T *, struct nfsd_nfscbd_args *);
 
 /* nfs_clpackrat.c */
-void nfscl_packratsetup(struct nfscldeleg *, struct nfsmount *, struct ucred *,
-    NFSPROC_T *);
+void nfscl_packratsetup(struct nfscldeleg *, struct nfsmount *, uint8_t *, int,
+    uint8_t *, int, struct ucred *, NFSPROC_T *);
 void nfscl_packratopen(vnode_t, NFSPROC_T *);
 void nfscl_packratclose(vnode_t, NFSPROC_T *);
 int nfscbd_packrat(char *);
@@ -667,5 +667,5 @@ int nfscl_packratwrite(vnode_t, struct u
     NFSPROC_T *, int *);
 int nfscl_deleglocalflush(struct nfscldeleg *, struct nfsmount *, NFSPROC_T *,
     int, int);
-void nfscl_packratsetsize(vnode_t, uint64_t);
+void nfscl_packratsetsize(vnode_t, uint64_t, struct ucred *, NFSPROC_T *);
 

Modified: projects/nfsv4-packrats/sys/fs/nfs/nfsclstate.h
==============================================================================
--- projects/nfsv4-packrats/sys/fs/nfs/nfsclstate.h	Wed May 22 22:34:48 2013	(r250919)
+++ projects/nfsv4-packrats/sys/fs/nfs/nfsclstate.h	Thu May 23 00:09:38 2013	(r250920)
@@ -188,6 +188,7 @@ struct nfscldeleg {
 #define	NFSCLDL_LOCALSIZESET	0x0100
 #define	NFSCLDL_HASCOPY		0x0200
 #define	NFSCLDL_WAITRECALL	0x0400
+#define	NFSCLDL_LOCALFLUSHED	0x0800
 
 /*
  * Maximum length of a local filename used by the packrat daemons.
@@ -199,6 +200,20 @@ struct nfscldeleg {
 #define	NFSPCKRAT_MAXFILELEN	(1 + 1 + 32 + 174)
 
 /*
+ * Structure that stores delegation recovery information. It is fixed
+ * size, so that it can easily be written/read from the packrat delegation
+ * file.
+ */
+struct nfsdelegrecover {
+	uint16_t	nfsdr_dirty;
+	uint16_t	nfsdr_flags;
+	uint16_t	nfsdr_dfhlen;
+	uint16_t	nfsdr_namelen;
+	uint8_t		nfsdr_dfh[NFSX_V4FHMAX];
+	uint8_t		nfsdr_name[NAME_MAX + 1];
+};
+
+/*
  * MALLOC'd to the correct length to accommodate the file handle.
  */
 struct nfsclopen {

Modified: projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clpackrat.c
==============================================================================
--- projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clpackrat.c	Wed May 22 22:34:48 2013	(r250919)
+++ projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clpackrat.c	Thu May 23 00:09:38 2013	(r250920)
@@ -69,6 +69,7 @@ static void nfscl_truncdirty(struct nfsc
 static int nfscl_packrathostaddr(struct nfsmount *, char *, int);
 static void nfscl_packratgetvp(struct nfscldeleg *, struct nfsmount *, char *,
     int, struct ucred *, NFSPROC_T *);
+static int nfscl_writedelegdirty(vnode_t, int, struct ucred *, NFSPROC_T *);
 
 /*
  * This function opens/creates a file for reading and writing, returning the
@@ -332,12 +333,13 @@ nfscl_fhtofilename(u_int8_t *fh, u_int16
  * Set up a new delegation for packrat support.
  */
 void
-nfscl_packratsetup(struct nfscldeleg *dp, struct nfsmount *nmp,
-    struct ucred *cred, NFSPROC_T *p)
+nfscl_packratsetup(struct nfscldeleg *dp, struct nfsmount *nmp, uint8_t *dfhp,
+    int dfhlen, uint8_t *name, int namelen, struct ucred *cred, NFSPROC_T *p)
 {
 	vnode_t delegvp, filevp;
 	char fname[MAXPATHLEN + 1];
-	int pathlen, pathlen2;
+	int error, pathlen, pathlen2;
+	struct nfsdelegrecover delegrecover;
 
 	NFSLOCKCLSTATE();
 	if (nfscl_packratpathlen == 0 ||
@@ -375,10 +377,23 @@ nfscl_packratsetup(struct nfscldeleg *dp
 		NFSUNLOCKCLSTATE();
 		return;
 	}
+
+	/* Write out the delegation record for use during recovery. */
+	delegrecover.nfsdr_dirty = 0;
+	delegrecover.nfsdr_flags = dp->nfsdl_flags;
+	delegrecover.nfsdr_dfhlen = dfhlen;
+	bcopy(dfhp, delegrecover.nfsdr_dfh, dfhlen);
+	delegrecover.nfsdr_namelen = namelen;
+	bcopy(name, delegrecover.nfsdr_name, namelen);
+	delegrecover.nfsdr_name[namelen] = 0;
 	VOP_UNLOCK(delegvp, 0);
+	error = vn_rdwr(UIO_WRITE, delegvp, &delegrecover, sizeof(delegrecover),
+	    (off_t)0, UIO_SYSSPACE, 0, cred, NOCRED, NULL, p);
+
 	fname[pathlen2] = 'F';
-	filevp = nfscl_openfile(fname, TRUE, cred, p);
-	if (filevp == NULL) {
+	if (error == 0)
+		filevp = nfscl_openfile(fname, TRUE, cred, p);
+	if (error != 0 || filevp == NULL) {
 		nfscl_closefile(delegvp, fname, TRUE, cred, p);
 		NFSLOCKCLSTATE();
 		dp->nfsdl_flags &= ~NFSCLDL_COPYINPROG;
@@ -423,9 +438,8 @@ nfscl_packratopen(vnode_t vp, NFSPROC_T 
 		return;
 	}
 	dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
-	if (dp == NULL || (dp->nfsdl_flags &
-	    (NFSCLDL_RECALL | NFSCLDL_WRITE | NFSCLDL_HASCOPY)) !=
-	    (NFSCLDL_WRITE | NFSCLDL_HASCOPY) ||
+	if (dp == NULL || (dp->nfsdl_flags & (NFSCLDL_RECALL |
+	    NFSCLDL_DELEGRET | NFSCLDL_HASCOPY)) != NFSCLDL_HASCOPY ||
 	    dp->nfsdl_filevp != NULL) {
 		NFSUNLOCKCLSTATE();
 		return;
@@ -524,8 +538,8 @@ nfscl_packratbreakdown(struct nfscldeleg
 		nfscl_fhtofilename(dp->nfsdl_fh, dp->nfsdl_fhlen,
 		    &fname[pathlen]);
 	while (dp->nfsdl_localiocnt > 0)
-		(void) nfsmsleep(&dp->nfsdl_localiocnt, NFSCLSTATEMUTEXPTR,
-		    PZERO, "nfspckbr", NULL);
+		(void)mtx_sleep(&dp->nfsdl_localiocnt, NFSCLSTATEMUTEXPTR,
+		    PZERO, "nfspckbr", 0);
 	if ((dp->nfsdl_flags & NFSCLDL_COPYINPROG) != 0) {
 		dp->nfsdl_flags &= ~NFSCLDL_COPYINPROG;
 		wakeup(&dp->nfsdl_flags);
@@ -573,9 +587,8 @@ nfscl_packratclose(vnode_t vp, NFSPROC_T
 		return;
 	}
 	dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
-	if (dp == NULL || (dp->nfsdl_flags &
-	    (NFSCLDL_RECALL | NFSCLDL_WRITE | NFSCLDL_HASCOPY)) !=
-	    (NFSCLDL_WRITE | NFSCLDL_HASCOPY) ||
+	if (dp == NULL || (dp->nfsdl_flags & (NFSCLDL_RECALL |
+	    NFSCLDL_DELEGRET | NFSCLDL_HASCOPY)) != NFSCLDL_HASCOPY ||
 	    dp->nfsdl_filevp == NULL) {
 		NFSUNLOCKCLSTATE();
 		return;
@@ -587,8 +600,8 @@ nfscl_packratclose(vnode_t vp, NFSPROC_T
 	dp->nfsdl_delegvp = NULL;
 	dp->nfsdl_filevp = NULL;
 	while (dp->nfsdl_localiocnt > 0)
-		(void) nfsmsleep(&dp->nfsdl_localiocnt, NFSCLSTATEMUTEXPTR,
-		    PZERO, "nfspckbr", NULL);
+		(void)mtx_sleep(&dp->nfsdl_localiocnt, NFSCLSTATEMUTEXPTR,
+		    PZERO, "nfspckbr", 0);
 	NFSUNLOCKCLSTATE();
 	pathlen2 = pathlen;
 	fname[pathlen++] = 'D';
@@ -655,15 +668,20 @@ nfscl_packratread(vnode_t vp, struct uio
 		return (0);
 	}
 	dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
-	if (dp == NULL || (dp->nfsdl_flags &
-	    (NFSCLDL_RECALL | NFSCLDL_WRITE)) != NFSCLDL_WRITE ||
-	    dp->nfsdl_filevp == NULL ||
+	if (dp == NULL || (dp->nfsdl_flags & (NFSCLDL_RECALL |
+	    NFSCLDL_DELEGRET)) != 0 || dp->nfsdl_filevp == NULL ||
 	    ((dp->nfsdl_flags & NFSCLDL_COPYINPROG) != 0 &&
 	     uio->uio_offset + uio->uio_resid > dp->nfsdl_localsize)) {
-		if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_RECALL) != 0) {
+		if (dp != NULL && (dp->nfsdl_flags & (NFSCLDL_RECALL |
+		    NFSCLDL_DELEGRET)) != 0 &&
+		    (dp->nfsdl_flags & NFSCLDL_LOCALFLUSHED) == 0) {
 			dp->nfsdl_flags |= NFSCLDL_WAITRECALL;
-			(void) nfsmsleep(&dp->nfsdl_ldirty, NFSCLSTATEMUTEXPTR,
-			    PZERO, "nfspkrc", NULL);
+			(void)mtx_sleep(&dp->nfsdl_ldirty, NFSCLSTATEMUTEXPTR,
+			    PZERO, "nfspkrc", 0);
+			/*
+			 * After this sleep, do not access "dp", since it
+			 * may be free'd.
+			 */
 		}
 		NFSUNLOCKCLSTATE();
 		NFSLOCKNODE(np);
@@ -687,15 +705,7 @@ nfscl_packratread(vnode_t vp, struct uio
 	dp->nfsdl_localiocnt++;
 	filevp = dp->nfsdl_filevp;
 	NFSUNLOCKCLSTATE();
-	error = 0;
-	vn_lock(filevp, LK_SHARED | LK_RETRY);
-	VI_LOCK(filevp);
-	if ((filevp->v_iflag & VI_DOOMED) != 0)
-		error = ENOENT;
-	VI_UNLOCK(filevp);
-	if (error == 0)
-		error = VOP_READ(filevp, uio, ioflag, cred);
-	VOP_UNLOCK(filevp, 0);
+	error = vn_rdwr_uio(uio, filevp, ioflag, cred, NULL, NULL);
 	uio->uio_resid += tresid;
 	NFSLOCKCLSTATE();
 	dp->nfsdl_localiocnt--;
@@ -720,13 +730,15 @@ nfscl_packratwrite(vnode_t vp, struct ui
 	struct mount *mp;
 	struct nfsldirty *wp;
 	vnode_t filevp;
+	vnode_t delegvp;
 	uint64_t end;
-	int error;
+	int error, mark_dirty;
 	off_t setsize;
 
 	*didwrite = 0;
 	nmp = VFSTONFS(vnode_mount(vp));
 	NFSLOCKCLSTATE();
+tryagain:
 	if (nfscl_packratpathlen == 0 || (nmp->nm_flag & NFSMNT_NFSV4) == 0) {
 		NFSUNLOCKCLSTATE();
 		NFSLOCKNODE(np);
@@ -743,13 +755,32 @@ nfscl_packratwrite(vnode_t vp, struct ui
 		return (0);
 	}
 	dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
-	if (dp == NULL || (dp->nfsdl_flags &
-	    (NFSCLDL_RECALL | NFSCLDL_WRITE)) != NFSCLDL_WRITE ||
+	if (dp == NULL || (dp->nfsdl_flags & (NFSCLDL_RECALL |
+	    NFSCLDL_DELEGRET | NFSCLDL_WRITE)) != NFSCLDL_WRITE ||
 	    dp->nfsdl_filevp == NULL) {
-		if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_RECALL) != 0) {
-			dp->nfsdl_flags |= NFSCLDL_WAITRECALL;
-			(void) nfsmsleep(&dp->nfsdl_ldirty, NFSCLSTATEMUTEXPTR,
-			    PZERO, "nfspkwc", NULL);
+		if (dp != NULL) {
+			if ((dp->nfsdl_flags & (NFSCLDL_RECALL |
+			    NFSCLDL_DELEGRET)) == 0 &&
+			    dp->nfsdl_filevp != NULL) {
+				/*
+				 * Start a Recall, so the local copy of
+				 * the file for a read delegation won't
+				 * continue to be used.
+				 */
+				dp->nfsdl_flags |= NFSCLDL_RECALL;
+				wakeup(clp);
+			}
+			if ((dp->nfsdl_flags & (NFSCLDL_RECALL |
+			    NFSCLDL_DELEGRET)) != 0 &&
+			    (dp->nfsdl_flags & NFSCLDL_LOCALFLUSHED) == 0) {
+				dp->nfsdl_flags |= NFSCLDL_WAITRECALL;
+				(void)mtx_sleep(&dp->nfsdl_ldirty,
+				    NFSCLSTATEMUTEXPTR, PZERO, "nfspkwc", 0);
+				/*
+				 * After this sleep, do not access "dp", since
+				 * it may be free'd.
+				 */
+			}
 		}
 		NFSUNLOCKCLSTATE();
 		NFSLOCKNODE(np);
@@ -761,16 +792,21 @@ nfscl_packratwrite(vnode_t vp, struct ui
 	/*
 	 * We can now try and do the write. It cannot be done until the
 	 * local copy has been read in to past the point at which we
-	 * are writing, so we must loop until enough reading has been
+	 * are writing, so we must sleep until enough reading has been
 	 * completed.
+	 * Go back up to the top after sleeping, just in case the delegation
+	 * has gone away or similar.
 	 */
 	end = (uint64_t)uio->uio_offset + uio->uio_resid;
-	while ((dp->nfsdl_flags & NFSCLDL_COPYINPROG) != 0 &&
-	    (end > dp->nfsdl_localsize || (ioflag & IO_APPEND) != 0))
-		(void) nfsmsleep(&dp->nfsdl_localsize, NFSCLSTATEMUTEXPTR,
-		    PZERO, "nfspckw", NULL);
+	if ((dp->nfsdl_flags & NFSCLDL_COPYINPROG) != 0 &&
+	    (end > dp->nfsdl_localsize || (ioflag & IO_APPEND) != 0)) {
+		(void)mtx_sleep(&dp->nfsdl_localsize, NFSCLSTATEMUTEXPTR,
+		    PZERO, "nfspckw", 0);
+		goto tryagain;
+	}
 	filevp = dp->nfsdl_filevp;
-	if (filevp == NULL) {
+	delegvp = dp->nfsdl_delegvp;
+	if (filevp == NULL || delegvp == NULL) {
 		NFSUNLOCKCLSTATE();
 		NFSLOCKNODE(np);
 		np->n_flag &= ~NLOCALCACHE;
@@ -796,6 +832,7 @@ nfscl_packratwrite(vnode_t vp, struct ui
 		return (0);
 	}
 	dp->nfsdl_localiocnt++;
+	mark_dirty = LIST_EMPTY(&dp->nfsdl_ldirty);
 	NFSUNLOCKCLSTATE();
 	NFSLOCKNODE(np);
 	np->n_flag |= (NMODIFIED | NLOCALCACHE);
@@ -814,22 +851,15 @@ nfscl_packratwrite(vnode_t vp, struct ui
 	wp->nfsw_first = (uint64_t)uio->uio_offset;
 	wp->nfsw_end = end;
 	mp = NULL;
-	if (error == 0)
-		error = vn_start_write(filevp, &mp, V_WAIT);
 	if (error == 0) {
-		if (MNT_SHARED_WRITES(mp) || ((mp == NULL) &&
-		    MNT_SHARED_WRITES(filevp->v_mount)))
-			vn_lock(filevp, LK_SHARED | LK_RETRY);
-		else
-			vn_lock(filevp, LK_EXCLUSIVE | LK_RETRY);
-		VI_LOCK(filevp);
-		if ((filevp->v_iflag & VI_DOOMED) != 0)
-			error = ENOENT;
-		VI_UNLOCK(filevp);
-		if (error == 0)
-			error = VOP_WRITE(filevp, uio, ioflag, cred);
-		vn_finished_write(mp);
-		VOP_UNLOCK(filevp, 0);
+		error = vn_rdwr_uio(uio, filevp, ioflag, cred, NULL, NULL);
+
+		/*
+		 * Now, write the dirty mark to the delegation file, as
+		 * required.
+		 */
+		if (mark_dirty != 0 && error == 0)
+			error = nfscl_writedelegdirty(delegvp, 1, cred, p);
 	}
 	setsize = 0;
 	NFSLOCKCLSTATE();
@@ -922,20 +952,22 @@ nfscl_deleglocalflush(struct nfscldeleg 
 	if (nfscl_packratpathlen == 0) {
 		if ((dp->nfsdl_flags & NFSCLDL_WAITRECALL) != 0)
 			wakeup(&dp->nfsdl_ldirty);
+		dp->nfsdl_flags |= NFSCLDL_LOCALFLUSHED;
 		NFSUNLOCKCLSTATE();
 		return (0);
 	}
 
 	/* Wait for the packrat thread to complete. */
 	while ((dp->nfsdl_flags & NFSCLDL_COPYINPROG) != 0)
-		(void) nfsmsleep(&dp->nfsdl_flags, NFSCLSTATEMUTEXPTR,
-		    PZERO, "nfspckth", NULL);
+		(void)mtx_sleep(&dp->nfsdl_flags, NFSCLSTATEMUTEXPTR,
+		    PZERO, "nfspckth", 0);
 
 	if ((dp->nfsdl_flags & NFSCLDL_WRITE) == 0 ||
 	    (dp->nfsdl_filevp == NULL &&
 	     (dp->nfsdl_flags & NFSCLDL_HASCOPY) == 0)) {
 		if ((dp->nfsdl_flags & NFSCLDL_WAITRECALL) != 0)
 			wakeup(&dp->nfsdl_ldirty);
+		dp->nfsdl_flags |= NFSCLDL_LOCALFLUSHED;
 		NFSUNLOCKCLSTATE();
 		return (0);
 	}
@@ -973,6 +1005,7 @@ nfscl_deleglocalflush(struct nfscldeleg 
 		NFSLOCKCLSTATE();
 		if ((dp->nfsdl_flags & NFSCLDL_WAITRECALL) != 0)
 			wakeup(&dp->nfsdl_ldirty);
+		dp->nfsdl_flags |= NFSCLDL_LOCALFLUSHED;
 		NFSUNLOCKCLSTATE();
 		/* Now, the local files can be closed/deleted. */
 		nfscl_packratbreakdown(dp, nmp, incred, p);
@@ -1114,13 +1147,17 @@ nfsmout:
  * dirty region(s) that no longer apply.
  */
 void
-nfscl_packratsetsize(vnode_t vp, uint64_t size)
+nfscl_packratsetsize(vnode_t vp, uint64_t size, struct ucred *cred,
+    NFSPROC_T *p)
 {
 	struct nfsclclient *clp;
 	struct nfscldeleg *dp;
 	struct nfsnode *np = VTONFS(vp);
 	struct nfsmount *nmp;
+	int mark_clean;
+	vnode_t delegvp = NULL, filevp;
 
+	mark_clean = 0;
 	nmp = VFSTONFS(vnode_mount(vp));
 	NFSLOCKCLSTATE();
 	if (nfscl_packratpathlen == 0 || (nmp->nm_flag & NFSMNT_NFSV4) == 0) {
@@ -1133,8 +1170,8 @@ nfscl_packratsetsize(vnode_t vp, uint64_
 		return;
 	}
 	dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
-	if (dp == NULL || (dp->nfsdl_flags &
-	    (NFSCLDL_RECALL | NFSCLDL_WRITE)) != NFSCLDL_WRITE ||
+	if (dp == NULL || (dp->nfsdl_flags & (NFSCLDL_RECALL |
+	    NFSCLDL_DELEGRET | NFSCLDL_WRITE)) != NFSCLDL_WRITE ||
 	    (dp->nfsdl_filevp == NULL &&
 	     (dp->nfsdl_flags & NFSCLDL_HASCOPY) == 0) ||
 	    dp->nfsdl_localsize == size) {
@@ -1142,14 +1179,27 @@ nfscl_packratsetsize(vnode_t vp, uint64_
 		return;
 	}
 
-	if (size < dp->nfsdl_localsize)
+	if (size < dp->nfsdl_localsize) {
 		/* Get rid of dirty region(s) that no longer apply. */
 		nfscl_truncdirty(dp, size);
+		mark_clean = LIST_EMPTY(&dp->nfsdl_ldirty);
+		delegvp = dp->nfsdl_delegvp;
+	}
+	filevp = dp->nfsdl_filevp;
 	/* Update the local size. */
 	dp->nfsdl_localsize = size;
 	dp->nfsdl_flags |= NFSCLDL_LOCALSIZESET;
+	dp->nfsdl_localiocnt++;
 	NFSUNLOCKCLSTATE();
 	vnode_pager_setsize(vp, size);
+	if (mark_clean != 0 && delegvp != NULL)
+		(void)nfscl_writedelegdirty(delegvp, 0, cred, p);
+	(void)vn_truncate_vnode(filevp, size, cred, NULL, p);
+	NFSLOCKCLSTATE();
+	dp->nfsdl_localiocnt--;
+	if (dp->nfsdl_localiocnt == 0)
+		wakeup(&dp->nfsdl_localiocnt);
+	NFSUNLOCKCLSTATE();
 }
 
 /*
@@ -1210,3 +1260,18 @@ nfscl_packrathostaddr(struct nfsmount *n
 	return (pathlen);
 }
 
+/*
+ * Write the dirty flag field of the delegation recovery file.
+ */
+static int
+nfscl_writedelegdirty(vnode_t vp, int dirty, struct ucred *cred, NFSPROC_T *p)
+{
+	uint16_t dirtyflag;
+	int error;
+
+	dirtyflag = (dirty != 0) ? 1 : 0;
+	error = vn_rdwr(UIO_WRITE, vp, &dirtyflag, sizeof(dirtyflag),
+	    (off_t)0, UIO_SYSSPACE, 0, cred, NOCRED, NULL, p);
+	return (error);
+}
+

Modified: projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clrpcops.c	Wed May 22 22:34:48 2013	(r250919)
+++ projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clrpcops.c	Thu May 23 00:09:38 2013	(r250920)
@@ -316,8 +316,10 @@ else printf(" fhl=0\n");
 				NFSUNLOCKNODE(np);
 #endif
 				(void) nfscl_deleg(nmp->nm_mountp,
-				    op->nfso_own->nfsow_clp,
-				    nfhp->nfh_fh, nfhp->nfh_len, cred, p, &dp);
+				    op->nfso_own->nfsow_clp, np->n_v4->n4_data,
+				    np->n_v4->n4_fhlen, NFS4NODENAME(np->n_v4),
+				    np->n_v4->n4_namelen, nfhp->nfh_fh,
+				    nfhp->nfh_len, cred, p, &dp);
 			}
 		} else {
 			error = EIO;
@@ -1828,9 +1830,11 @@ nfsrpc_create(vnode_t dvp, char *name, i
 	struct nfscldeleg *dp;
 	struct nfsmount *nmp = VFSTONFS(vnode_mount(dvp));
 	u_int32_t clidrev;
+	struct nfsnode *dnp;
 
 	if (NFSHASNFSV4(nmp)) {
 	    retrycnt = 0;
+	    dnp = VTONFS(dvp);
 	    do {
 		dp = NULL;
 		error = nfscl_open(dvp, NULL, 0, (NFSV4OPEN_ACCESSWRITE |
@@ -1853,7 +1857,9 @@ nfsrpc_create(vnode_t dvp, char *name, i
 		 */
 		if (dp != NULL)
 			(void) nfscl_deleg(nmp->nm_mountp, owp->nfsow_clp,
-			    (*nfhpp)->nfh_fh, (*nfhpp)->nfh_len, cred, p, &dp);
+			    dnp->n_fhp->nfh_fh, dnp->n_fhp->nfh_len, name,
+			    namelen, (*nfhpp)->nfh_fh, (*nfhpp)->nfh_len, cred,
+			    p, &dp);
 		nfscl_ownerrelease(owp, error, newone, unlocked);
 		if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||

Modified: projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clstate.c	Wed May 22 22:34:48 2013	(r250919)
+++ projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clstate.c	Thu May 23 00:09:38 2013	(r250920)
@@ -398,25 +398,13 @@ nfscl_newopen(struct nfsclclient *clp, s
  * Called to find/add a delegation to a client.
  */
 APPLESTATIC int
-nfscl_deleg(mount_t mp, struct nfsclclient *clp, u_int8_t *nfhp,
-    int fhlen, struct ucred *cred, NFSPROC_T *p, struct nfscldeleg **dpp)
+nfscl_deleg(mount_t mp, struct nfsclclient *clp, u_int8_t *dfhp, int dfhlen,
+    u_int8_t *name, int namelen, u_int8_t *nfhp, int fhlen, struct ucred *cred,
+    NFSPROC_T *p, struct nfscldeleg **dpp)
 {
 	struct nfscldeleg *dp = *dpp, *tdp;
 	struct nfsmount *nmp = VFSTONFS(mp);
 
-	/*
-	 * First, if we have received a Read delegation for a file on a
-	 * read/write file system, just return it, because they aren't
-	 * useful, imho.
-	 */
-	if (mp != NULL && dp != NULL && !NFSMNT_RDONLY(mp) &&
-	    (dp->nfsdl_flags & NFSCLDL_READ)) {
-		(void) nfscl_trydelegreturn(dp, cred, nmp, p);
-		FREE((caddr_t)dp, M_NFSCLDELEG);
-		*dpp = NULL;
-		return (0);
-	}
-
 	/* Look for the correct deleg, based upon FH */
 	NFSLOCKCLSTATE();
 	tdp = nfscl_finddeleg(clp, nfhp, fhlen);
@@ -439,7 +427,8 @@ nfscl_deleg(mount_t mp, struct nfsclclie
 		 * Call nfscl_packratsetup() to create the local copy
 		 * and start the copying via a kernel thread.
 		 */
-		nfscl_packratsetup(dp, nmp, cred, p);
+		nfscl_packratsetup(dp, nmp, dfhp, dfhlen, name, namelen, cred,
+		    p);
 	} else {
 		/*
 		 * Delegation already exists, what do we do if a new one??
@@ -1469,8 +1458,8 @@ nfscl_expireopen(struct nfsclclient *clp
 			}
 		}
 		if (dp != NULL)
-			nfscl_deleg(nmp->nm_mountp, clp, op->nfso_fh,
-			    op->nfso_fhlen, cred, p, &dp);
+			nfscl_deleg(nmp->nm_mountp, clp, NULL, 0, NULL, 0,
+			    op->nfso_fh, op->nfso_fhlen, cred, p, &dp);
 	}
 
 	/*
@@ -2009,8 +1998,7 @@ nfscl_recover(struct nfsclclient *clp, s
 			tcred, p);
 		    if (!error) {
 			/* Handle any replied delegation */
-			if (ndp != NULL && ((ndp->nfsdl_flags & NFSCLDL_WRITE)
-			    || NFSMNT_RDONLY(nmp->nm_mountp))) {
+			if (ndp != NULL) {
 			    if ((ndp->nfsdl_flags & NFSCLDL_WRITE))
 				mode = NFSV4OPEN_ACCESSWRITE;
 			    else

Modified: projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clvnops.c	Wed May 22 22:34:48 2013	(r250919)
+++ projects/nfsv4-packrats/sys/fs/nfsclient/nfs_clvnops.c	Thu May 23 00:09:38 2013	(r250920)
@@ -1001,7 +1001,7 @@ nfs_setattr(struct vop_setattr_args *ap)
 	}
 	if (NFS_ISV4(vp) && error == 0 && vap->va_size != VNOVAL &&
 	    vp->v_type == VREG)
-		nfscl_packratsetsize(vp, vap->va_size);
+		nfscl_packratsetsize(vp, vap->va_size, ap->a_cred, td);
 	return (error);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305230009.r4N09d0X030400>