Module Name: src Committed By: manu Date: Sun Apr 8 15:04:41 UTC 2012
Modified Files: src/sys/fs/puffs: puffs_msgif.h puffs_node.c puffs_sys.h puffs_vfsops.c puffs_vnops.c Log Message: Add name and atttribute cache with filesytem provided TTL. lookup, create, mknod, mkdir, symlink, getattr and setattr messages have been extended so that attributes and their TTL can be provided by the filesytem. lookup, create, mknod, mkdir, and symlink messages are also extended so that the filesystem can provide name TTL. To generate a diff of this commit: cvs rdiff -u -r1.77 -r1.78 src/sys/fs/puffs/puffs_msgif.h cvs rdiff -u -r1.23 -r1.24 src/sys/fs/puffs/puffs_node.c cvs rdiff -u -r1.78 -r1.79 src/sys/fs/puffs/puffs_sys.h cvs rdiff -u -r1.100 -r1.101 src/sys/fs/puffs/puffs_vfsops.c cvs rdiff -u -r1.164 -r1.165 src/sys/fs/puffs/puffs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/fs/puffs/puffs_msgif.h diff -u src/sys/fs/puffs/puffs_msgif.h:1.77 src/sys/fs/puffs/puffs_msgif.h:1.78 --- src/sys/fs/puffs/puffs_msgif.h:1.77 Tue Sep 27 01:48:57 2011 +++ src/sys/fs/puffs/puffs_msgif.h Sun Apr 8 15:04:41 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_msgif.h,v 1.77 2011/09/27 01:48:57 christos Exp $ */ +/* $NetBSD: puffs_msgif.h,v 1.78 2012/04/08 15:04:41 manu Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -159,8 +159,9 @@ struct puffs_kargs { #define PUFFS_KFLAG_WTCACHE 0x08 /* write-through page cache */ #define PUFFS_KFLAG_IAONDEMAND 0x10 /* inactive only on demand */ #define PUFFS_KFLAG_LOOKUP_FULLPNBUF 0x20 /* full pnbuf in lookup */ -#define PUFFS_KFLAG_MASK 0x3f #define PUFFS_KFLAG_NOCACHE_ATTR 0x40 /* no attrib cache (unused) */ +#define PUFFS_KFLAG_CACHE_FS_TTL 0x80 /* cache use TTL from FS */ +#define PUFFS_KFLAG_MASK 0xbf #define PUFFS_FHFLAG_DYNAMIC 0x01 #define PUFFS_FHFLAG_NFSV2 0x02 @@ -360,6 +361,10 @@ struct puffs_vnmsg_lookup { enum vtype pvnr_vtype; /* IN */ voff_t pvnr_size; /* IN */ dev_t pvnr_rdev; /* IN */ + /* Used only if PUFFS_KFLAG_CACHE_USE_TTL */ + struct vattr pvnr_va; /* IN */ + struct timespec pvnr_va_ttl; /* IN */ + struct timespec pvnr_cn_ttl; /* IN */ }; struct puffs_vnmsg_create { @@ -370,6 +375,9 @@ struct puffs_vnmsg_create { struct vattr pvnr_va; /* OUT */ puffs_cookie_t pvnr_newnode; /* IN */ + /* Used only if PUFFS_KFLAG_CACHE_USE_TTL */ + struct timespec pvnr_va_ttl; /* IN */ + struct timespec pvnr_cn_ttl; /* IN */ }; struct puffs_vnmsg_mknod { @@ -380,6 +388,9 @@ struct puffs_vnmsg_mknod { struct vattr pvnr_va; /* OUT */ puffs_cookie_t pvnr_newnode; /* IN */ + /* Used only if PUFFS_KFLAG_CACHE_USE_TTL */ + struct timespec pvnr_va_ttl; /* IN */ + struct timespec pvnr_cn_ttl; /* IN */ }; struct puffs_vnmsg_open { @@ -410,6 +421,8 @@ struct puffs_vnmsg_setgetattr { struct puffs_kcred pvnr_cred; /* OUT */ struct vattr pvnr_va; /* IN/OUT (op depend) */ + /* Used only if PUFFS_KFLAG_CACHE_USE_TTL */ + struct timespec pvnr_va_ttl; /* IN */ }; #define puffs_vnmsg_read puffs_vnmsg_rw @@ -480,6 +493,9 @@ struct puffs_vnmsg_mkdir { struct vattr pvnr_va; /* OUT */ puffs_cookie_t pvnr_newnode; /* IN */ + /* Used only if PUFFS_KFLAG_CACHE_USE_TTL */ + struct timespec pvnr_va_ttl; /* IN */ + struct timespec pvnr_cn_ttl; /* IN */ }; struct puffs_vnmsg_rmdir { @@ -522,6 +538,9 @@ struct puffs_vnmsg_symlink { struct vattr pvnr_va; /* OUT */ puffs_cookie_t pvnr_newnode; /* IN */ char pvnr_link[MAXPATHLEN]; /* OUT */ + /* Used only if PUFFS_KFLAG_CACHE_USE_TTL */ + struct timespec pvnr_va_ttl; /* IN */ + struct timespec pvnr_cn_ttl; /* IN */ }; struct puffs_vnmsg_readdir { Index: src/sys/fs/puffs/puffs_node.c diff -u src/sys/fs/puffs/puffs_node.c:1.23 src/sys/fs/puffs/puffs_node.c:1.24 --- src/sys/fs/puffs/puffs_node.c:1.23 Thu Jan 19 08:14:41 2012 +++ src/sys/fs/puffs/puffs_node.c Sun Apr 8 15:04:41 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_node.c,v 1.23 2012/01/19 08:14:41 manu Exp $ */ +/* $NetBSD: puffs_node.c,v 1.24 2012/04/08 15:04:41 manu Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.23 2012/01/19 08:14:41 manu Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.24 2012/04/08 15:04:41 manu Exp $"); #include <sys/param.h> #include <sys/hash.h> @@ -63,6 +63,7 @@ static struct puffs_node *puffs_cookie2p puffs_cookie_t); struct pool puffs_pnpool; +struct pool puffs_vapool; /* * Grab a vnode, intialize all the puffs-dependent stuff. @@ -483,6 +484,8 @@ puffs_releasenode(struct puffs_node *pn) mutex_destroy(&pn->pn_mtx); mutex_destroy(&pn->pn_sizemtx); seldestroy(&pn->pn_sel); + if (pn->pn_va_cache != NULL) + pool_put(&puffs_vapool, pn->pn_va_cache); pool_put(&puffs_pnpool, pn); } else { mutex_exit(&pn->pn_mtx); Index: src/sys/fs/puffs/puffs_sys.h diff -u src/sys/fs/puffs/puffs_sys.h:1.78 src/sys/fs/puffs/puffs_sys.h:1.79 --- src/sys/fs/puffs/puffs_sys.h:1.78 Mon Aug 29 04:12:45 2011 +++ src/sys/fs/puffs/puffs_sys.h Sun Apr 8 15:04:41 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_sys.h,v 1.78 2011/08/29 04:12:45 manu Exp $ */ +/* $NetBSD: puffs_sys.h,v 1.79 2012/04/08 15:04:41 manu Exp $ */ /* * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. @@ -53,6 +53,7 @@ extern const struct vnodeopv_desc puffs_ extern const struct vnodeopv_desc puffs_msgop_opv_desc; extern struct pool puffs_pnpool; +extern struct pool puffs_vapool; #ifdef DEBUG #ifndef PUFFSDEBUG @@ -89,6 +90,8 @@ extern int puffsdebug; /* puffs_subr.c * (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_PAGE) == 0) #define PUFFS_USE_FULLPNBUF(pmp) \ ((pmp)->pmp_flags & PUFFS_KFLAG_LOOKUP_FULLPNBUF) +#define PUFFS_USE_FS_TTL(pmp) \ + ((pmp)->pmp_flags & PUFFS_KFLAG_CACHE_FS_TTL) #define PUFFS_WCACHEINFO(pmp) 0 @@ -210,6 +213,10 @@ struct puffs_node { struct lockf * pn_lockf; kmutex_t pn_sizemtx; /* size modification mutex */ + + int pn_cn_timeout; /* path cache */ + int pn_va_timeout; /* attribute cache */ + struct vattr * pn_va_cache; /* attribute cache */ LIST_ENTRY(puffs_node) pn_hashent; }; Index: src/sys/fs/puffs/puffs_vfsops.c diff -u src/sys/fs/puffs/puffs_vfsops.c:1.100 src/sys/fs/puffs/puffs_vfsops.c:1.101 --- src/sys/fs/puffs/puffs_vfsops.c:1.100 Wed Oct 19 01:39:29 2011 +++ src/sys/fs/puffs/puffs_vfsops.c Sun Apr 8 15:04:41 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vfsops.c,v 1.100 2011/10/19 01:39:29 manu Exp $ */ +/* $NetBSD: puffs_vfsops.c,v 1.101 2012/04/08 15:04:41 manu Exp $ */ /* * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.100 2011/10/19 01:39:29 manu Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.101 2012/04/08 15:04:41 manu Exp $"); #include <sys/param.h> #include <sys/mount.h> @@ -763,6 +763,8 @@ puffs_vfsop_init(void) pool_init(&puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0, "puffpnpl", &pool_allocator_nointr, IPL_NONE); + pool_init(&puffs_vapool, sizeof(struct vattr), 0, 0, 0, + "puffvapl", &pool_allocator_nointr, IPL_NONE); puffs_msgif_init(); } @@ -772,6 +774,7 @@ puffs_vfsop_done(void) puffs_msgif_destroy(); pool_destroy(&puffs_pnpool); + pool_destroy(&puffs_vapool); } int Index: src/sys/fs/puffs/puffs_vnops.c diff -u src/sys/fs/puffs/puffs_vnops.c:1.164 src/sys/fs/puffs/puffs_vnops.c:1.165 --- src/sys/fs/puffs/puffs_vnops.c:1.164 Fri Mar 16 23:13:48 2012 +++ src/sys/fs/puffs/puffs_vnops.c Sun Apr 8 15:04:41 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vnops.c,v 1.164 2012/03/16 23:13:48 jakllsch Exp $ */ +/* $NetBSD: puffs_vnops.c,v 1.165 2012/04/08 15:04:41 manu Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.164 2012/03/16 23:13:48 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.165 2012/04/08 15:04:41 manu Exp $"); #include <sys/param.h> #include <sys/buf.h> @@ -40,6 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: puffs_vnops. #include <sys/namei.h> #include <sys/vnode.h> #include <sys/proc.h> +#include <sys/kernel.h> /* For hz, hardclock_ticks */ #include <uvm/uvm.h> @@ -410,6 +411,8 @@ static int callrmdir(struct puffs_mount static void callinactive(struct puffs_mount *, puffs_cookie_t, int); static void callreclaim(struct puffs_mount *, puffs_cookie_t); static int flushvncache(struct vnode *, off_t, off_t, bool); +static void update_va(struct vnode *, struct vattr *, struct vattr *, + struct timespec *, struct timespec *); #define PUFFS_ABORT_LOOKUP 1 @@ -455,6 +458,8 @@ puffs_abortbutton(struct puffs_mount *pm * don't want to think of the consequences for the time being. */ +#define TTL_TO_TIMEOUT(ts) \ + (hardclock_ticks + (ts->tv_sec * hz) + (ts->tv_nsec * hz / 1000000000)) int puffs_vnop_lookup(void *v) { @@ -467,14 +472,16 @@ puffs_vnop_lookup(void *v) PUFFS_MSG_VARS(vn, lookup); struct puffs_mount *pmp; struct componentname *cnp; - struct vnode *vp, *dvp; - struct puffs_node *dpn; + struct vnode *vp, *dvp, *cvp; + struct puffs_node *dpn, *cpn; int isdot; int error; pmp = MPTOPUFFSMP(ap->a_dvp->v_mount); cnp = ap->a_cnp; dvp = ap->a_dvp; + cvp = NULL; + cpn = NULL; *ap->a_vpp = NULL; /* r/o fs? we check create later to handle EEXIST */ @@ -494,7 +501,31 @@ puffs_vnop_lookup(void *v) if (PUFFS_USE_NAMECACHE(pmp)) { error = cache_lookup(dvp, ap->a_vpp, cnp); - if (error >= 0) + if ((error == 0) && PUFFS_USE_FS_TTL(pmp)) { + + cvp = *ap->a_vpp; + cpn = VPTOPP(cvp); + if (hardclock_ticks > cpn->pn_cn_timeout) { + cache_purge1(cvp, NULL, PURGE_CHILDREN); + + /* + * cached vnode (cvp) is still locked + * so that we can reuse it upon a new + * successful lookup. + */ + *ap->a_vpp = NULL; + error = -1; + } + } + + /* + * Do not use negative caching, since the filesystem + * provides no TTL for it. + */ + if ((error == ENOENT) && PUFFS_USE_FS_TTL(pmp)) + error = -1; + + if (error >= 0) return error; } @@ -503,12 +534,18 @@ puffs_vnop_lookup(void *v) if (cnp->cn_nameiop == RENAME && (cnp->cn_flags & ISLASTCN)) return EISDIR; + if (cvp != NULL) + vput(cvp); + vp = ap->a_dvp; vref(vp); *ap->a_vpp = vp; return 0; } + if (cvp != NULL) + mutex_enter(&cpn->pn_sizemtx); + PUFFS_MSG_ALLOC(vn, lookup); puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred, cnp, PUFFS_USE_FULLPNBUF(pmp)); @@ -545,7 +582,8 @@ puffs_vnop_lookup(void *v) /* save negative cache entry */ } else { if ((cnp->cn_flags & MAKEENTRY) - && PUFFS_USE_NAMECACHE(pmp)) + && PUFFS_USE_NAMECACHE(pmp) + && !PUFFS_USE_FS_TTL(pmp)) cache_enter(dvp, NULL, cnp); } } @@ -564,21 +602,41 @@ puffs_vnop_lookup(void *v) goto out; } - error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, 1, 1, &vp); - if (error == PUFFS_NOSUCHCOOKIE) { - error = puffs_getvnode(dvp->v_mount, - lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype, - lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp); - if (error) { + /* + * On successfull relookup, do not create a new node. + */ + if (cvp != NULL) { + vp = cvp; + } else { + error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, + 1, 1, &vp); + + if (error == PUFFS_NOSUCHCOOKIE) { + error = puffs_getvnode(dvp->v_mount, + lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype, + lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp); + if (error) { + puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, + VPTOPNC(dvp), lookup_msg->pvnr_newnode, + ap->a_cnp); + goto out; + } + + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + } else if (error) { puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), lookup_msg->pvnr_newnode, ap->a_cnp); goto out; } - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - } else if (error) { - puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), - lookup_msg->pvnr_newnode, ap->a_cnp); - goto out; + } + + /* + * Update cache and TTL + */ + if (PUFFS_USE_FS_TTL(pmp)) { + struct timespec *va_ttl = &lookup_msg->pvnr_va_ttl; + struct timespec *cn_ttl = &lookup_msg->pvnr_cn_ttl; + update_va(vp, NULL, &lookup_msg->pvnr_va, va_ttl, cn_ttl); } *ap->a_vpp = vp; @@ -594,6 +652,16 @@ puffs_vnop_lookup(void *v) strlen(cnp->cn_nameptr) - cnp->cn_namelen); out: + if (cvp != NULL) { + mutex_exit(&cpn->pn_sizemtx); + /* + * We had a cached vnode but new lookup failed, + * unlock it and let it die now. + */ + if (error != 0) + vput(cvp); + } + if (cnp->cn_flags & ISDOTDOT) vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); @@ -658,9 +726,19 @@ puffs_vnop_create(void *v) error = puffs_newnode(mp, dvp, ap->a_vpp, create_msg->pvnr_newnode, cnp, ap->a_vap->va_type, 0); - if (error) + if (error) { puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie, create_msg->pvnr_newnode, cnp); + goto out; + } + + if (PUFFS_USE_FS_TTL(pmp)) { + struct timespec *va_ttl = &create_msg->pvnr_va_ttl; + struct timespec *cn_ttl = &create_msg->pvnr_cn_ttl; + struct vattr *rvap = &create_msg->pvnr_va; + + update_va(*ap->a_vpp, NULL, rvap, va_ttl, cn_ttl); + } out: vput(dvp); @@ -704,9 +782,19 @@ puffs_vnop_mknod(void *v) error = puffs_newnode(mp, dvp, ap->a_vpp, mknod_msg->pvnr_newnode, cnp, ap->a_vap->va_type, ap->a_vap->va_rdev); - if (error) + if (error) { puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie, mknod_msg->pvnr_newnode, cnp); + goto out; + } + + if (PUFFS_USE_FS_TTL(pmp)) { + struct timespec *va_ttl = &mknod_msg->pvnr_va_ttl; + struct timespec *cn_ttl = &mknod_msg->pvnr_cn_ttl; + struct vattr *rvap = &mknod_msg->pvnr_va; + + update_va(*ap->a_vpp, NULL, rvap, va_ttl, cn_ttl); + } out: vput(dvp); @@ -822,6 +910,60 @@ puffs_vnop_access(void *v) return error; } +static void +update_va(struct vnode *vp, struct vattr *vap, struct vattr *rvap, + struct timespec *va_ttl, struct timespec *cn_ttl) +{ + struct puffs_node *pn = VPTOPP(vp); + + if (cn_ttl != NULL) + pn->pn_cn_timeout = TTL_TO_TIMEOUT(cn_ttl); + + /* + * Don't listen to the file server regarding special device + * size info, the file server doesn't know anything about them. + */ + if (vp->v_type == VBLK || vp->v_type == VCHR) + rvap->va_size = vp->v_size; + + /* Ditto for blocksize (ufs comment: this doesn't belong here) */ + if (vp->v_type == VBLK) + rvap->va_blocksize = BLKDEV_IOSIZE; + else if (vp->v_type == VCHR) + rvap->va_blocksize = MAXBSIZE; + + if (vap != NULL) { + (void) memcpy(vap, rvap, sizeof(struct vattr)); + vap->va_fsid = vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0]; + + if (pn->pn_stat & PNODE_METACACHE_ATIME) + vap->va_atime = pn->pn_mc_atime; + if (pn->pn_stat & PNODE_METACACHE_CTIME) + vap->va_ctime = pn->pn_mc_ctime; + if (pn->pn_stat & PNODE_METACACHE_MTIME) + vap->va_mtime = pn->pn_mc_mtime; + if (pn->pn_stat & PNODE_METACACHE_SIZE) + vap->va_size = pn->pn_mc_size; + } + + if (!(pn->pn_stat & PNODE_METACACHE_SIZE)) { + if (rvap->va_size != VNOVAL + && vp->v_type != VBLK && vp->v_type != VCHR) { + uvm_vnp_setsize(vp, rvap->va_size); + pn->pn_serversize = rvap->va_size; + } + } + + if (va_ttl != NULL) { + if (pn->pn_va_cache == NULL) + pn->pn_va_cache = pool_get(&puffs_vapool, PR_WAITOK); + + (void)memcpy(pn->pn_va_cache, rvap, sizeof(*rvap)); + + pn->pn_va_timeout = TTL_TO_TIMEOUT(va_ttl); + } +} + int puffs_vnop_getattr(void *v) { @@ -837,6 +979,7 @@ puffs_vnop_getattr(void *v) struct puffs_mount *pmp = MPTOPUFFSMP(mp); struct vattr *vap, *rvap; struct puffs_node *pn = VPTOPP(vp); + struct timespec *va_ttl = NULL; int error = 0; /* @@ -857,6 +1000,13 @@ puffs_vnop_getattr(void *v) REFPN(pn); vap = ap->a_vap; + if (PUFFS_USE_FS_TTL(pmp)) { + if (hardclock_ticks < pn->pn_va_timeout) { + update_va(vp, vap, pn->pn_va_cache, NULL, NULL); + goto out2; + } + } + PUFFS_MSG_ALLOC(vn, getattr); vattr_null(&getattr_msg->pvnr_va); puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred); @@ -869,41 +1019,17 @@ puffs_vnop_getattr(void *v) goto out; rvap = &getattr_msg->pvnr_va; - /* - * Don't listen to the file server regarding special device - * size info, the file server doesn't know anything about them. - */ - if (vp->v_type == VBLK || vp->v_type == VCHR) - rvap->va_size = vp->v_size; - /* Ditto for blocksize (ufs comment: this doesn't belong here) */ - if (vp->v_type == VBLK) - rvap->va_blocksize = BLKDEV_IOSIZE; - else if (vp->v_type == VCHR) - rvap->va_blocksize = MAXBSIZE; + if (PUFFS_USE_FS_TTL(pmp)) + va_ttl = &getattr_msg->pvnr_va_ttl; - (void) memcpy(vap, rvap, sizeof(struct vattr)); - vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; - - if (pn->pn_stat & PNODE_METACACHE_ATIME) - vap->va_atime = pn->pn_mc_atime; - if (pn->pn_stat & PNODE_METACACHE_CTIME) - vap->va_ctime = pn->pn_mc_ctime; - if (pn->pn_stat & PNODE_METACACHE_MTIME) - vap->va_mtime = pn->pn_mc_mtime; - if (pn->pn_stat & PNODE_METACACHE_SIZE) { - vap->va_size = pn->pn_mc_size; - } else { - if (rvap->va_size != VNOVAL - && vp->v_type != VBLK && vp->v_type != VCHR) { - uvm_vnp_setsize(vp, rvap->va_size); - pn->pn_serversize = rvap->va_size; - } - } + update_va(vp, vap, rvap, va_ttl, NULL); out: - puffs_releasenode(pn); PUFFS_MSG_RELEASE(getattr); + + out2: + puffs_releasenode(pn); mutex_exit(&pn->pn_sizemtx); @@ -954,6 +1080,13 @@ dosetattr(struct vnode *vp, struct vattr pn->pn_stat &= ~PNODE_METACACHE_MASK; } + /* + * Flush attribute cache so that another thread do + * not get a stale value during the operation. + */ + if (PUFFS_USE_FS_TTL(pmp)) + pn->pn_va_timeout = 0; + PUFFS_MSG_ALLOC(vn, setattr); (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr)); puffs_credcvt(&setattr_msg->pvnr_cred, cred); @@ -965,6 +1098,14 @@ dosetattr(struct vnode *vp, struct vattr puffs_msg_enqueue(pmp, park_setattr); if ((flags & SETATTR_ASYNC) == 0) error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL); + + if ((error == 0) && PUFFS_USE_FS_TTL(pmp)) { + struct timespec *va_ttl = &setattr_msg->pvnr_va_ttl; + struct vattr *rvap = &setattr_msg->pvnr_va; + + update_va(vp, NULL, rvap, va_ttl, NULL); + } + PUFFS_MSG_RELEASE(setattr); if ((flags & SETATTR_ASYNC) == 0) { error = checkerr(pmp, error, __func__); @@ -1340,6 +1481,7 @@ flushvncache(struct vnode *vp, off_t off pflags = PGO_CLEANIT; if (wait) pflags |= PGO_SYNCIO; + mutex_enter(vp->v_interlock); return VOP_PUTPAGES(vp, trunc_page(offlo), round_page(offhi), pflags); } @@ -1550,9 +1692,19 @@ puffs_vnop_mkdir(void *v) error = puffs_newnode(mp, dvp, ap->a_vpp, mkdir_msg->pvnr_newnode, cnp, VDIR, 0); - if (error) + if (error) { puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie, mkdir_msg->pvnr_newnode, cnp); + goto out; + } + + if (PUFFS_USE_FS_TTL(pmp)) { + struct timespec *va_ttl = &mkdir_msg->pvnr_va_ttl; + struct timespec *cn_ttl = &mkdir_msg->pvnr_cn_ttl; + struct vattr *rvap = &mkdir_msg->pvnr_va; + + update_va(*ap->a_vpp, NULL, rvap, va_ttl, cn_ttl); + } out: vput(dvp); @@ -1703,9 +1855,19 @@ puffs_vnop_symlink(void *v) error = puffs_newnode(mp, dvp, ap->a_vpp, symlink_msg->pvnr_newnode, cnp, VLNK, 0); - if (error) + if (error) { puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie, symlink_msg->pvnr_newnode, cnp); + goto out; + } + + if (PUFFS_USE_FS_TTL(pmp)) { + struct timespec *va_ttl = &symlink_msg->pvnr_va_ttl; + struct timespec *cn_ttl = &symlink_msg->pvnr_cn_ttl; + struct vattr *rvap = &symlink_msg->pvnr_va; + + update_va(*ap->a_vpp, NULL, rvap, va_ttl, cn_ttl); + } out: vput(dvp);