From owner-svn-src-projects@FreeBSD.ORG Thu May 23 00:09:40 2013 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id B7CFC9F1; Thu, 23 May 2013 00:09:40 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id A95BF1A1; Thu, 23 May 2013 00:09:40 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r4N09e9o030407; Thu, 23 May 2013 00:09:40 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r4N09d0X030400; Thu, 23 May 2013 00:09:39 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201305230009.r4N09d0X030400@svn.freebsd.org> From: Rick Macklem Date: Thu, 23 May 2013 00:09:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r250920 - in projects/nfsv4-packrats/sys/fs: nfs nfsclient X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 May 2013 00:09:40 -0000 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); }