Module Name:    src
Committed By:   manu
Date:           Wed Apr 18 00:57:22 UTC 2012

Modified Files:
        src/lib/libperfuse: ops.c perfuse.c perfuse_priv.h subr.c
        src/lib/libpuffs: dispatcher.c pnode.c puffs.3 puffs.h puffs_ops.3
            puffs_priv.h

Log Message:
- When using PUFFS_KFLAG_CACHE_FS_TTL, do not use puffs_node to carry
  attribute and TTL fora newly created node. Instead extend puffs_newinfo
  and add puffs_newinfo_setva() and puffs_newinfo_setttl()
- Remove node_mk_common_final in libperfuse. It used to set uid/gid for
  a newly created vnode but has been made redundant along time ago since
  uid and gid are properly set in FUSE header.
- In libperfuse, check for corner case where opc = 0 on INACTIVE and   RECLAIM 
(how is it possible? Check for it to avoid a crash anyway)
- In libperfuse, make sure we unlimit RLIMIT_AS and RLIMIT_DATA so that
  we do notrun out of memory because the kernel is lazy at reclaiming vnodes.
- In libperfuse, cleanup style of perfuse_destroy_pn()


To generate a diff of this commit:
cvs rdiff -u -r1.53 -r1.54 src/lib/libperfuse/ops.c
cvs rdiff -u -r1.27 -r1.28 src/lib/libperfuse/perfuse.c
cvs rdiff -u -r1.28 -r1.29 src/lib/libperfuse/perfuse_priv.h
cvs rdiff -u -r1.17 -r1.18 src/lib/libperfuse/subr.c
cvs rdiff -u -r1.39 -r1.40 src/lib/libpuffs/dispatcher.c
cvs rdiff -u -r1.11 -r1.12 src/lib/libpuffs/pnode.c
cvs rdiff -u -r1.51 -r1.52 src/lib/libpuffs/puffs.3
cvs rdiff -u -r1.120 -r1.121 src/lib/libpuffs/puffs.h
cvs rdiff -u -r1.29 -r1.30 src/lib/libpuffs/puffs_ops.3
cvs rdiff -u -r1.44 -r1.45 src/lib/libpuffs/puffs_priv.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libperfuse/ops.c
diff -u src/lib/libperfuse/ops.c:1.53 src/lib/libperfuse/ops.c:1.54
--- src/lib/libperfuse/ops.c:1.53	Sun Apr  8 15:13:06 2012
+++ src/lib/libperfuse/ops.c	Wed Apr 18 00:57:21 2012
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.53 2012/04/08 15:13:06 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.54 2012/04/18 00:57:21 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -34,7 +34,7 @@
 #include <sysexits.h>
 #include <syslog.h>
 #include <puffs.h>
-#include <sys/socket.h>
+#include <sys/cdefs.h>
 #include <sys/socket.h>
 #include <sys/extattr.h>
 #include <sys/time.h>
@@ -48,9 +48,12 @@ extern int perfuse_diagflags;
 #if 0
 static void print_node(const char *, puffs_cookie_t);
 #endif
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+static void perfuse_newinfo_setttl(struct puffs_newinfo *, 
+    struct fuse_entry_out *, struct fuse_attr_out *);
+#else /* PUFFS_KFLAG_CACHE_FS_TTL */
 static void set_expire(puffs_cookie_t, struct fuse_entry_out *, 
     struct fuse_attr_out *);
-#ifndef PUFFS_KFLAG_CACHE_FS_TTL
 static int attr_expired(puffs_cookie_t);
 static int entry_expired(puffs_cookie_t);
 #endif /* PUFFS_KFLAG_CACHE_FS_TTL */
@@ -63,11 +66,10 @@ static void fuse_attr_to_vap(struct perf
 static int node_lookup_dir_nodot(struct puffs_usermount *,
     puffs_cookie_t, char *, size_t, struct puffs_node **);
 static int node_lookup_common(struct puffs_usermount *, puffs_cookie_t, 
-    const char *, const struct puffs_cred *, struct puffs_node **);
+    struct puffs_newinfo *, const char *, const struct puffs_cred *, 
+    struct puffs_node **);
 static int node_mk_common(struct puffs_usermount *, puffs_cookie_t,
     struct puffs_newinfo *, const struct puffs_cn *pcn, perfuse_msg_t *);
-static int node_mk_common_final(struct puffs_usermount *, puffs_cookie_t,
-    struct puffs_node *, const struct puffs_cn *pcn);
 static uint64_t readdir_last_cookie(struct fuse_dirent *, size_t); 
 static ssize_t fuse_to_dirent(struct puffs_usermount *, puffs_cookie_t,
     struct fuse_dirent *, size_t);
@@ -336,12 +338,48 @@ fuse_attr_to_vap(struct perfuse_state *p
 	return;
 }
 
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+static void perfuse_newinfo_setttl(struct puffs_newinfo *pni, 
+	struct fuse_entry_out *feo, struct fuse_attr_out *fao)
+{
+#ifdef PERFUSE_DEBUG
+	if ((feo == NULL) && (fao == NULL))
+		DERRX(EX_SOFTWARE, "%s: feo and fao NULL", __func__);
+
+	if ((feo != NULL) && (fao != NULL))
+		DERRX(EX_SOFTWARE, "%s: feo and fao != NULL", __func__);
+#endif /* PERFUSE_DEBUG */
+
+	if (fao != NULL) {
+		struct timespec va_ttl;
+
+		va_ttl.tv_sec = fao->attr_valid;
+		va_ttl.tv_nsec = fao->attr_valid_nsec;
+
+		puffs_newinfo_setvattl(pni, &va_ttl);
+	}
+
+	if (feo != NULL) {
+		struct timespec va_ttl;
+		struct timespec cn_ttl;
+
+		va_ttl.tv_sec = feo->attr_valid;
+		va_ttl.tv_nsec = feo->attr_valid_nsec;
+		cn_ttl.tv_sec = feo->entry_valid;
+		cn_ttl.tv_nsec = feo->entry_valid_nsec;
+
+		puffs_newinfo_setvattl(pni, &va_ttl);
+		puffs_newinfo_setcnttl(pni, &cn_ttl);
+	}
+
+	return;	
+}
+#else /* PUFFS_KFLAG_CACHE_FS_TTL */
 static void 
 set_expire(puffs_cookie_t opc, struct fuse_entry_out *feo,
 	   struct fuse_attr_out *fao)
 {
  	struct puffs_node *pn = (struct puffs_node *)opc;
-#ifndef PUFFS_KFLAG_CACHE_FS_TTL
 	struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
 	struct timespec entry_ts;
 	struct timespec attr_ts;
@@ -349,7 +387,6 @@ set_expire(puffs_cookie_t opc, struct fu
 
 	if (clock_gettime(CLOCK_REALTIME, &now) != 0)
 		DERR(EX_OSERR, "clock_gettime failed");
-#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
 
 	if ((feo == NULL) && (fao == NULL))
 		DERRX(EX_SOFTWARE, "%s: feo and fao NULL", __func__);
@@ -358,12 +395,6 @@ set_expire(puffs_cookie_t opc, struct fu
 		DERRX(EX_SOFTWARE, "%s: feo and fao != NULL", __func__);
 
 	if (feo != NULL) {
-#ifdef PUFFS_KFLAG_CACHE_FS_TTL
-		pn->pn_cn_ttl.tv_sec = feo->entry_valid;
-		pn->pn_cn_ttl.tv_nsec = feo->entry_valid_nsec;
-		pn->pn_va_ttl.tv_sec = feo->attr_valid;
-		pn->pn_va_ttl.tv_nsec = feo->attr_valid_nsec;
-#else /* PUFFS_KFLAG_CACHE_FS_TTL */
 		entry_ts.tv_sec = (time_t)feo->entry_valid;
 		entry_ts.tv_nsec = (long)feo->entry_valid_nsec;
 
@@ -373,25 +404,18 @@ set_expire(puffs_cookie_t opc, struct fu
 		attr_ts.tv_nsec = (long)feo->attr_valid_nsec;
 
 		timespecadd(&now, &attr_ts, &pnd->pnd_attr_expire);
-#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
 	} 
 
 	if (fao != NULL) {
-#ifdef PUFFS_KFLAG_CACHE_FS_TTL
-		pn->pn_va_ttl.tv_sec = fao->attr_valid;
-		pn->pn_va_ttl.tv_nsec = fao->attr_valid_nsec;
-#else /* PUFFS_KFLAG_CACHE_FS_TTL */
 		attr_ts.tv_sec = (time_t)fao->attr_valid;
 		attr_ts.tv_nsec = (long)fao->attr_valid_nsec;
 
 		timespecadd(&now, &attr_ts, &pnd->pnd_attr_expire);
-#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
 	} 
 
 	return;
 }
 
-#ifndef PUFFS_KFLAG_CACHE_FS_TTL
 static int
 attr_expired(puffs_cookie_t opc)
 {
@@ -451,12 +475,13 @@ node_lookup_dir_nodot(struct puffs_userm
 		return 0;
 	}
 
-	return node_lookup_common(pu, opc, name, NULL, pnp);
+	return node_lookup_common(pu, opc, NULL, name, NULL, pnp);
 }
 
 static int
 node_lookup_common(struct puffs_usermount *pu, puffs_cookie_t opc,
-	const char *path, const struct puffs_cred *pcr, struct puffs_node **pnp)
+	struct puffs_newinfo *pni, const char *path, 
+	const struct puffs_cred *pcr, struct puffs_node **pnp)
 {
 	struct perfuse_state *ps;
 	struct perfuse_node_data *oldpnd;
@@ -543,14 +568,12 @@ node_lookup_common(struct puffs_usermoun
 
 	feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out);
 
+	pn = NULL;
 	if (oldpnd != NULL) {
 		if (oldpnd->pnd_nodeid == feo->nodeid) {
 			oldpnd->pnd_fuse_nlookup++;
 			oldpnd->pnd_puffs_nlookup++;
-			*pnp = oldpnd->pnd_pn;
-
-			ps->ps_destroy_msg(pm);
-			return 0;
+			pn = oldpnd->pnd_pn;
 		} else {
 			oldpnd->pnd_flags |= PND_REMOVED;
 #ifdef PERFUSE_DEBUG
@@ -563,12 +586,16 @@ node_lookup_common(struct puffs_usermoun
 		}
 	}
 
-	pn = perfuse_new_pn(pu, path, opc);
-	PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
+	if (pn == NULL) {
+		pn = perfuse_new_pn(pu, path, opc);
+		PERFUSE_NODE_DATA(pn)->pnd_nodeid = feo->nodeid;
+	}
 
 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
 	pn->pn_va.va_gen = (u_long)(feo->generation);
+#ifndef PUFFS_KFLAG_CACHE_FS_TTL
 	set_expire((puffs_cookie_t)pn, feo, NULL);
+#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
 
 	*pnp = pn;
 
@@ -579,6 +606,17 @@ node_lookup_common(struct puffs_usermoun
 			(void *)opc, pn, feo->nodeid, path);
 #endif
 	
+	if (pni != NULL) {
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+		puffs_newinfo_setva(pni, &pn->pn_va);
+		perfuse_newinfo_setttl(pni, feo, NULL);
+#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
+		puffs_newinfo_setcookie(pni, pn);
+		puffs_newinfo_setvtype(pni, pn->pn_va.va_type); 
+		puffs_newinfo_setsize(pni, (voff_t)pn->pn_va.va_size);
+		puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev);
+	}
+
 	ps->ps_destroy_msg(pm);
 
 	return 0;
@@ -615,9 +653,15 @@ node_mk_common(struct puffs_usermount *p
 
 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
 	pn->pn_va.va_gen = (u_long)(feo->generation);
-	set_expire((puffs_cookie_t)pn, feo, NULL);
 
 	puffs_newinfo_setcookie(pni, pn);
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+	puffs_newinfo_setva(pni, &pn->pn_va);
+	perfuse_newinfo_setttl(pni, feo, NULL);
+#else
+	set_expire((puffs_cookie_t)pn, feo, NULL);
+#endif
+
 
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & PDF_FILENAME)
@@ -627,61 +671,11 @@ node_mk_common(struct puffs_usermount *p
 			PERFUSE_NODE_DATA(pn)->pnd_flags, feo->nodeid);
 #endif
 	ps->ps_destroy_msg(pm);
-
-	return node_mk_common_final(pu, opc, pn, pcn);
-}
-
-/*
- * Common final code for methods that create objects:
- * perfuse_node_mkdir via node_mk_common
- * perfuse_node_mknod via node_mk_common
- * perfuse_node_symlink via node_mk_common
- * perfuse_node_create
- */
-static int
-node_mk_common_final(struct puffs_usermount *pu, puffs_cookie_t opc,
-	struct puffs_node *pn, const struct puffs_cn *pcn)
-{
-	struct perfuse_state *ps;
-	perfuse_msg_t *pm;
-	struct fuse_setattr_in *fsi;
-	struct fuse_attr_out *fao;
-	int error;
-
-	ps =  puffs_getspecific(pu);
-
-	/* 
-	 * Set owner and group. The kernel cannot create a file
-	 * on its own (puffs_cred_getuid would return -1), right?
-	 */
-	if (puffs_cred_getuid(pcn->pcn_cred, &pn->pn_va.va_uid) != 0)
-		DERRX(EX_SOFTWARE, "puffs_cred_getuid fails in %s", __func__);
-	if (puffs_cred_getgid(pcn->pcn_cred, &pn->pn_va.va_gid) != 0)
-		DERRX(EX_SOFTWARE, "puffs_cred_getgid fails in %s", __func__);
-
-	pm = ps->ps_new_msg(pu, (puffs_cookie_t)pn, 
-			    FUSE_SETATTR, sizeof(*fsi), pcn->pcn_cred);
-	fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in);
-	fsi->uid = pn->pn_va.va_uid;
-	fsi->gid = pn->pn_va.va_gid;
-	fsi->valid = FUSE_FATTR_UID|FUSE_FATTR_GID;
-
-	if ((error = xchg_msg(pu, (puffs_cookie_t)pn, pm, 
-			      sizeof(*fao), wait_reply)) != 0)
-		return error;
-
-	fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out);
-	fuse_attr_to_vap(ps, &pn->pn_va, &fao->attr);
-	set_expire((puffs_cookie_t)pn, NULL, fao);
-
-	/*
-	 * The parent directory needs a sync
-	 */
+	
+	/* Parents is now dirty */
 	PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY;
 
-	ps->ps_destroy_msg(pm);
-
-	return 0;
+	return 0; 
 }
 
 static uint64_t
@@ -1168,11 +1162,20 @@ perfuse_node_lookup(struct puffs_usermou
 	/*
 	 * Special case for ..
 	 */
-	if (strcmp(pcn->pcn_name, "..") == 0) 
+	if (strcmp(pcn->pcn_name, "..") == 0) {
 		pn = PERFUSE_NODE_DATA(opc)->pnd_parent;
-	else
-		error = node_lookup_common(pu, (puffs_cookie_t)opc,
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+		puffs_newinfo_setva(pni, &pn->pn_va);
+		/* XXX cannot call perfuse_newinfo_setttl */
+#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
+		puffs_newinfo_setcookie(pni, pn);
+		puffs_newinfo_setvtype(pni, pn->pn_va.va_type); 
+		puffs_newinfo_setsize(pni, (voff_t)pn->pn_va.va_size);
+		puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev);
+	} else {
+		error = node_lookup_common(pu, (puffs_cookie_t)opc, pni,
 					   pcn->pcn_name, pcn->pcn_cred, &pn);
+	}
 	if (error != 0)
 		return error;
 
@@ -1222,11 +1225,6 @@ perfuse_node_lookup(struct puffs_usermou
 	 */
 	PERFUSE_NODE_DATA(pn)->pnd_flags &= ~PND_RECLAIMED;
 
-	puffs_newinfo_setcookie(pni, pn);
-	puffs_newinfo_setvtype(pni, pn->pn_va.va_type); 
-	puffs_newinfo_setsize(pni, (voff_t)pn->pn_va.va_size);
-	puffs_newinfo_setrdev(pni, pn->pn_va.va_rdev);
-
 	return error;
 }
 
@@ -1255,7 +1253,7 @@ perfuse_node_create(struct puffs_usermou
 	 */
 	ps = puffs_getspecific(pu);
 	if (ps->ps_flags & PS_NO_CREAT) {
-		error = node_lookup_common(pu, opc, pcn->pcn_name, 
+		error = node_lookup_common(pu, opc, NULL, pcn->pcn_name,
 					   pcn->pcn_cred, &pn);
 		if (error == 0)	
 			return EEXIST;
@@ -1264,7 +1262,7 @@ perfuse_node_create(struct puffs_usermou
 		if (error != 0)
 			return error;
 
-		error = node_lookup_common(pu, opc, pcn->pcn_name,
+		error = node_lookup_common(pu, opc, NULL, pcn->pcn_name,
 					   pcn->pcn_cred, &pn);
 		if (error != 0)	
 			return error;
@@ -1331,9 +1329,14 @@ perfuse_node_create(struct puffs_usermou
 
 	fuse_attr_to_vap(ps, &pn->pn_va, &feo->attr);
 	pn->pn_va.va_gen = (u_long)(feo->generation);
-	set_expire((puffs_cookie_t)pn, feo, NULL);
-		
+
 	puffs_newinfo_setcookie(pni, pn);
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+	puffs_newinfo_setva(pni, &pn->pn_va);
+	perfuse_newinfo_setttl(pni, feo, NULL);
+#else /* PUFFS_KFLAG_CACHE_FS_TTL */
+	set_expire((puffs_cookie_t)pn, feo, NULL);
+#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
 
 #ifdef PERFUSE_DEBUG
 	if (perfuse_diagflags & (PDF_FH|PDF_FILENAME))
@@ -1346,7 +1349,7 @@ perfuse_node_create(struct puffs_usermou
 
 	ps->ps_destroy_msg(pm);
 
-	return node_mk_common_final(pu, opc, pn, pcn);
+	return 0;
 }
 
 
@@ -1576,6 +1579,14 @@ int
 perfuse_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc,
 	struct vattr *vap, const struct puffs_cred *pcr)
 {
+	return perfuse_node_getattr_ttl(pu, opc, vap, pcr, NULL);
+}
+
+int
+perfuse_node_getattr_ttl(struct puffs_usermount *pu, puffs_cookie_t opc,
+	struct vattr *vap, const struct puffs_cred *pcr,
+	struct timespec *va_ttl)
+{
 	perfuse_msg_t *pm = NULL;
 	struct perfuse_state *ps;
 	struct perfuse_node_data *pnd = PERFUSE_NODE_DATA(opc);
@@ -1645,7 +1656,15 @@ perfuse_node_getattr(struct puffs_usermo
 	 * not available from filesystem.
 	 */
 	fuse_attr_to_vap(ps, vap, &fao->attr);
+
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+	if (va_ttl != NULL) {
+		va_ttl->tv_sec = fao->attr_valid;
+		va_ttl->tv_nsec = fao->attr_valid_nsec;
+	}
+#else /* PUFFS_KFLAG_CACHE_FS_TTL */
 	set_expire(opc, NULL, fao);
+#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
 
 	ps->ps_destroy_msg(pm);
 out:
@@ -1660,6 +1679,15 @@ int
 perfuse_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc,
 	const struct vattr *vap, const struct puffs_cred *pcr)
 {
+	return perfuse_node_setattr_ttl(pu, opc, 
+					__UNCONST(vap), pcr, NULL);
+}
+
+int
+perfuse_node_setattr_ttl(struct puffs_usermount *pu, puffs_cookie_t opc,
+	struct vattr *vap, const struct puffs_cred *pcr,
+	struct timespec *va_ttl)
+{
 	perfuse_msg_t *pm;
 	uint64_t fh;
 	struct perfuse_state *ps;
@@ -1860,7 +1888,16 @@ perfuse_node_setattr(struct puffs_usermo
 #endif
 
 	fuse_attr_to_vap(ps, old_va, &fao->attr);
+
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+	if (va_ttl != NULL) {
+		va_ttl->tv_sec = fao->attr_valid;
+		va_ttl->tv_nsec = fao->attr_valid_nsec;
+		(void)memcpy(vap, old_va, sizeof(*vap));
+	}
+#else /* PUFFS_KFLAG_CACHE_FS_TTL */
 	set_expire(opc, NULL, fao);
+#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
 
 	ps->ps_destroy_msg(pm);
 
@@ -2582,6 +2619,9 @@ perfuse_node_reclaim(struct puffs_usermo
 	struct puffs_node *pn;
 	struct puffs_node *pn_root;
 	
+	if (opc == 0)
+		return 0;
+
 	ps = puffs_getspecific(pu);
 	pnd = PERFUSE_NODE_DATA(opc);
 
@@ -2689,6 +2729,9 @@ perfuse_node_inactive(struct puffs_userm
 	struct perfuse_node_data *pnd;
 	int error;
 
+	if (opc == 0)
+		return 0;
+
 	ps = puffs_getspecific(pu);
 	pnd = PERFUSE_NODE_DATA(opc);
 

Index: src/lib/libperfuse/perfuse.c
diff -u src/lib/libperfuse/perfuse.c:1.27 src/lib/libperfuse/perfuse.c:1.28
--- src/lib/libperfuse/perfuse.c:1.27	Sun Apr  8 15:13:06 2012
+++ src/lib/libperfuse/perfuse.c	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse.c,v 1.27 2012/04/08 15:13:06 manu Exp $ */
+/*  $NetBSD: perfuse.c,v 1.28 2012/04/18 00:57:22 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -397,17 +397,18 @@ perfuse_init(struct perfuse_callbacks *p
 	/*
 	 * perfused can grow quite large, let assume there's enough ram ...
 	 */
-	if (getrlimit(RLIMIT_DATA, &rl) < 0) {
-		DERR(EX_OSERR, "%s: getrlimit failed: %s", __func__,
+	rl.rlim_cur = RLIM_INFINITY;
+	rl.rlim_max = RLIM_INFINITY;
+
+	if (setrlimit(RLIMIT_DATA, &rl) < 0) {
+		DERR(EX_OSERR, "%s: setrlimit failed: %s", __func__,
+		    strerror(errno));
+	}
+
+	if (setrlimit(RLIMIT_AS, &rl) < 0) {
+		DERR(EX_OSERR, "%s: setrlimit failed: %s", __func__,
 		    strerror(errno));
-	} else {
-		rl.rlim_cur = rl.rlim_max;
-		if (setrlimit(RLIMIT_DATA, &rl) < 0) {
-			DERR(EX_OSERR, "%s: setrlimit failed: %s", __func__,
-			    strerror(errno));
-		}
 	}
-		
 
 	ps = init_state();
 	ps->ps_owner_uid = pmi->pmi_uid;
@@ -485,25 +486,12 @@ perfuse_init(struct perfuse_callbacks *p
 	PUFFSOP_SET(pops, perfuse, node, listextattr);
 	PUFFSOP_SET(pops, perfuse, node, deleteextattr);
 #endif /* PUFFS_EXTNAMELEN */
+#ifdef PUFFS_KFLAG_CACHE_FS_TTL
+	PUFFSOP_SET(pops, perfuse, node, getattr_ttl);
+	PUFFSOP_SET(pops, perfuse, node, setattr_ttl);
+#endif /* PUFFS_KFLAG_CACHE_FS_TTL */
 
 	/*
-	 * We used to have PUFFS_KFLAG_WTCACHE here, which uses the
-	 * page cache (highly desirable to get mmap(2)), but still sends
-	 * all writes to the filesystem. In fact it does not send the
-	 * data written, but the pages that contain it. 
-	 *
-	 * There is a nasty bug hidden somewhere, possibly in libpuffs'
-	 * VOP_FSYNC, which sends an asynchronous PUFFS_SETATTR that
-	 * update file size. When writes are in progress, it will cause
-	 * the file to be truncated and we get a zero-filled chunk at the
-	 * beginning of a page. Removing PUFFS_KFLAG_WTCACHE fixes that
-	 * problem. 
-	 * 
-	 * The other consequences are that changes will not be propagated
-	 * immediatly to the filesystem, and we get a huge performance gain
-	 * because much less requests are sent. A test case for the above
-	 * mentioned bug got its execution time slashed by factor 50.
-	 *
 	 * PUFFS_KFLAG_NOCACHE_NAME is required so that we can see changes
 	 * done by other machines in networked filesystems. In later
 	 * NetBSD releases we use the alternative PUFFS_KFLAG_CACHE_FS_TTL, 

Index: src/lib/libperfuse/perfuse_priv.h
diff -u src/lib/libperfuse/perfuse_priv.h:1.28 src/lib/libperfuse/perfuse_priv.h:1.29
--- src/lib/libperfuse/perfuse_priv.h:1.28	Sun Apr  8 15:13:06 2012
+++ src/lib/libperfuse/perfuse_priv.h	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse_priv.h,v 1.28 2012/04/08 15:13:06 manu Exp $ */
+/*  $NetBSD: perfuse_priv.h,v 1.29 2012/04/18 00:57:22 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -254,6 +254,12 @@ int perfuse_node_listextattr(struct puff
     int, size_t *, uint8_t *, size_t *, int, const struct puffs_cred *);
 int perfuse_node_deleteextattr(struct puffs_usermount *, puffs_cookie_t,
     int, const char *, const struct puffs_cred *);
+int perfuse_node_getattr_ttl(struct puffs_usermount *,
+    puffs_cookie_t, struct vattr *, const struct puffs_cred *,
+    struct timespec *);
+int perfuse_node_setattr_ttl(struct puffs_usermount *,
+    puffs_cookie_t, struct vattr *, const struct puffs_cred *,
+    struct timespec *);
 
 struct perfuse_trace *perfuse_trace_begin(struct perfuse_state *, 
     puffs_cookie_t, perfuse_msg_t *);

Index: src/lib/libperfuse/subr.c
diff -u src/lib/libperfuse/subr.c:1.17 src/lib/libperfuse/subr.c:1.18
--- src/lib/libperfuse/subr.c:1.17	Wed Mar 21 10:10:36 2012
+++ src/lib/libperfuse/subr.c	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-/*  $NetBSD: subr.c,v 1.17 2012/03/21 10:10:36 matt Exp $ */
+/*  $NetBSD: subr.c,v 1.18 2012/04/18 00:57:22 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -90,18 +90,15 @@ perfuse_destroy_pn(struct puffs_node *pn
 {
 	struct perfuse_node_data *pnd;
 
-	pnd = PERFUSE_NODE_DATA(pn);
-
-	if (pnd->pnd_parent != NULL) {
-		struct perfuse_node_data *parent_pnd;
+	if ((pnd = puffs_pn_getpriv(pn)) != NULL) {
+		if (pnd->pnd_parent != NULL) {
+			struct perfuse_node_data *parent_pnd;
 
-		parent_pnd = PERFUSE_NODE_DATA(pnd->pnd_parent);
-		TAILQ_REMOVE(&parent_pnd->pnd_children, pnd, pnd_next);
-	}
+			parent_pnd = PERFUSE_NODE_DATA(pnd->pnd_parent);
+			TAILQ_REMOVE(&parent_pnd->pnd_children, pnd, pnd_next);
 
-	if ((pnd = puffs_pn_getpriv(pn)) != NULL) {
-		if (pnd->pnd_parent != NULL)
 			PERFUSE_NODE_DATA(pnd->pnd_parent)->pnd_childcount--;
+		}
 
 		if (pnd->pnd_dirent != NULL)
 			free(pnd->pnd_dirent);
@@ -114,9 +111,6 @@ perfuse_destroy_pn(struct puffs_node *pn
 
 		if (!TAILQ_EMPTY(&pnd->pnd_pcq))
 			DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__);
-
-		if (pnd == NULL)
-			DERRX(EX_SOFTWARE, "%s: pnd == NULL ???", __func__);
 #endif /* PERFUSE_DEBUG */
 
 		free(pnd);

Index: src/lib/libpuffs/dispatcher.c
diff -u src/lib/libpuffs/dispatcher.c:1.39 src/lib/libpuffs/dispatcher.c:1.40
--- src/lib/libpuffs/dispatcher.c:1.39	Sun Apr  8 15:07:45 2012
+++ src/lib/libpuffs/dispatcher.c	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: dispatcher.c,v 1.39 2012/04/08 15:07:45 manu Exp $	*/
+/*	$NetBSD: dispatcher.c,v 1.40 2012/04/18 00:57:22 manu Exp $	*/
 
 /*
  * Copyright (c) 2006, 2007, 2008 Antti Kantee.  All Rights Reserved.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #if !defined(lint)
-__RCSID("$NetBSD: dispatcher.c,v 1.39 2012/04/08 15:07:45 manu Exp $");
+__RCSID("$NetBSD: dispatcher.c,v 1.40 2012/04/18 00:57:22 manu Exp $");
 #endif /* !lint */
 
 #include <sys/types.h>
@@ -52,26 +52,6 @@ __RCSID("$NetBSD: dispatcher.c,v 1.39 20
 
 static void dispatch(struct puffs_cc *);
 
-static void 
-update_fs_ttl(struct puffs_usermount *pu, puffs_cookie_t opc, 
-	      struct vattr *rvap, 
-	      struct timespec *va_ttl, struct timespec *cn_ttl)
-{
-	struct puffs_node *pn = NULL;
-
-	pn = PU_CMAP(pu, opc);
-
-	(void)memcpy(rvap, &pn->pn_va, sizeof(*rvap));
-
-	va_ttl->tv_sec =  pn->pn_va_ttl.tv_sec;
-	va_ttl->tv_nsec =  pn->pn_va_ttl.tv_nsec;
-
-	if (cn_ttl != NULL) {
-		cn_ttl->tv_sec =  pn->pn_cn_ttl.tv_sec;
-		cn_ttl->tv_nsec =  pn->pn_cn_ttl.tv_nsec;
-	}
-}
-
 /* for our eyes only */
 void
 puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb)
@@ -222,6 +202,9 @@ dispatch(struct puffs_cc *pcc)
 			pni.pni_vtype = &auxt->pvfsr_vtype;
 			pni.pni_size = &auxt->pvfsr_size;
 			pni.pni_rdev = &auxt->pvfsr_rdev;
+			pni.pni_va = NULL;
+			pni.pni_va_ttl = NULL;
+			pni.pni_cn_ttl = NULL;
 
 			error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data,
 			    auxt->pvfsr_dsize, &pni);
@@ -288,6 +271,9 @@ dispatch(struct puffs_cc *pcc)
 			pni.pni_vtype = &auxt->pvnr_vtype;
 			pni.pni_size = &auxt->pvnr_size;
 			pni.pni_rdev = &auxt->pvnr_rdev;
+			pni.pni_va = &auxt->pvnr_va;
+			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
+			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
 
 			if (buildpath) {
 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
@@ -315,13 +301,6 @@ dispatch(struct puffs_cc *pcc)
 						    &pcn.pcn_po_full);
 				}
 			}
-
-			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
-				update_fs_ttl(pu, auxt->pvnr_newnode, 
-					      &auxt->pvnr_va,
-					      &auxt->pvnr_va_ttl, 
-					      &auxt->pvnr_cn_ttl);
-
 			break;
 		}
 
@@ -341,6 +320,9 @@ dispatch(struct puffs_cc *pcc)
 
 			memset(&pni, 0, sizeof(pni));
 			pni.pni_cookie = &auxt->pvnr_newnode;
+			pni.pni_va = &auxt->pvnr_va;
+			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
+			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
 
 			if (buildpath) {
 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
@@ -362,12 +344,6 @@ dispatch(struct puffs_cc *pcc)
 				}
 			}
 
-			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
-				update_fs_ttl(pu, auxt->pvnr_newnode, 
-					      &auxt->pvnr_va,
-					      &auxt->pvnr_va_ttl, 
-					      &auxt->pvnr_cn_ttl);
-
 			break;
 		}
 
@@ -387,6 +363,9 @@ dispatch(struct puffs_cc *pcc)
 
 			memset(&pni, 0, sizeof(pni));
 			pni.pni_cookie = &auxt->pvnr_newnode;
+			pni.pni_va = &auxt->pvnr_va;
+			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
+			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
 
 			if (buildpath) {
 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
@@ -408,12 +387,6 @@ dispatch(struct puffs_cc *pcc)
 				}
 			}
 
-			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
-				update_fs_ttl(pu, auxt->pvnr_newnode, 
-					      &auxt->pvnr_va,
-					      &auxt->pvnr_va_ttl, 
-					      &auxt->pvnr_cn_ttl);
-
 			break;
 		}
 
@@ -467,27 +440,24 @@ dispatch(struct puffs_cc *pcc)
 			struct puffs_vnmsg_getattr *auxt = auxbuf;
 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
 
-			if (pops->puffs_node_getattr == NULL) {
-				error = EOPNOTSUPP;
-				break;
-			}
-
-			error = pops->puffs_node_getattr(pu,
-			    opcookie, &auxt->pvnr_va, pcr);
+			if (PUFFS_USE_FS_TTL(pu)) {
+				if (pops->puffs_node_getattr_ttl == NULL) {
+					error = EOPNOTSUPP;
+					break;
+				}
 
-			if ((error == 0) && PUFFS_USE_FS_TTL(pu)) {
-				struct puffs_node *pn;
+				error = pops->puffs_node_getattr_ttl(pu,
+				    opcookie, &auxt->pvnr_va, pcr,
+				    &auxt->pvnr_va_ttl);
+			} else {
+				if (pops->puffs_node_getattr == NULL) {
+					error = EOPNOTSUPP;
+					break;
+				}
 
-				pn = PU_CMAP(pu, opcookie);
-				auxt->pvnr_va_ttl = pn->pn_va_ttl;
+				error = pops->puffs_node_getattr(pu,
+				    opcookie, &auxt->pvnr_va, pcr);
 			}
-
-			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
-				update_fs_ttl(pu, opcookie,
-					      &auxt->pvnr_va,
-					      &auxt->pvnr_va_ttl, 
-					      NULL);
-
 			break;
 		}
 
@@ -496,19 +466,24 @@ dispatch(struct puffs_cc *pcc)
 			struct puffs_vnmsg_setattr *auxt = auxbuf;
 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
 
-			if (pops->puffs_node_setattr == NULL) {
-				error = EOPNOTSUPP;
-				break;
-			}
+			if (PUFFS_USE_FS_TTL(pu)) {
+				if (pops->puffs_node_setattr_ttl == NULL) {
+					error = EOPNOTSUPP;
+					break;
+				}
 
-			error = pops->puffs_node_setattr(pu,
-			    opcookie, &auxt->pvnr_va, pcr);
+				error = pops->puffs_node_setattr_ttl(pu,
+				    opcookie, &auxt->pvnr_va, pcr,
+				    &auxt->pvnr_va_ttl);
+			} else {
+				if (pops->puffs_node_setattr == NULL) {
+					error = EOPNOTSUPP;
+					break;
+				}
 
-			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
-				update_fs_ttl(pu, opcookie,
-					      &auxt->pvnr_va,
-					      &auxt->pvnr_va_ttl, 
-					      NULL);
+				error = pops->puffs_node_setattr(pu,
+				    opcookie, &auxt->pvnr_va, pcr);
+			}
 			break;
 		}
 
@@ -684,6 +659,9 @@ dispatch(struct puffs_cc *pcc)
 
 			memset(&pni, 0, sizeof(pni));
 			pni.pni_cookie = &auxt->pvnr_newnode;
+			pni.pni_va = &auxt->pvnr_va;
+			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
+			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
 
 			if (buildpath) {
 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
@@ -705,12 +683,6 @@ dispatch(struct puffs_cc *pcc)
 				}
 			}
 
-			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
-				update_fs_ttl(pu, auxt->pvnr_newnode, 
-					      &auxt->pvnr_va,
-					      &auxt->pvnr_va_ttl, 
-					      &auxt->pvnr_cn_ttl);
-
 			break;
 		}
 
@@ -747,6 +719,9 @@ dispatch(struct puffs_cc *pcc)
 
 			memset(&pni, 0, sizeof(pni));
 			pni.pni_cookie = &auxt->pvnr_newnode;
+			pni.pni_va = &auxt->pvnr_va;
+			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
+			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
 
 			if (buildpath) {
 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
@@ -769,12 +744,6 @@ dispatch(struct puffs_cc *pcc)
 				}
 			}
 
-			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
-				update_fs_ttl(pu, auxt->pvnr_newnode, 
-					      &auxt->pvnr_va,
-					      &auxt->pvnr_va_ttl, 
-					      &auxt->pvnr_cn_ttl);
-
 			break;
 		}
 

Index: src/lib/libpuffs/pnode.c
diff -u src/lib/libpuffs/pnode.c:1.11 src/lib/libpuffs/pnode.c:1.12
--- src/lib/libpuffs/pnode.c:1.11	Sun Apr  8 15:07:45 2012
+++ src/lib/libpuffs/pnode.c	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pnode.c,v 1.11 2012/04/08 15:07:45 manu Exp $	*/
+/*	$NetBSD: pnode.c,v 1.12 2012/04/18 00:57:22 manu Exp $	*/
 
 /*
  * Copyright (c) 2006 Antti Kantee.  All Rights Reserved.
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 #if !defined(lint)
-__RCSID("$NetBSD: pnode.c,v 1.11 2012/04/08 15:07:45 manu Exp $");
+__RCSID("$NetBSD: pnode.c,v 1.12 2012/04/18 00:57:22 manu Exp $");
 #endif /* !lint */
 
 #include <sys/types.h>
@@ -136,19 +136,6 @@ puffs_pn_getmnt(struct puffs_node *pn)
 	return pn->pn_mnt;
 }
 
-struct timespec *
-puffs_pn_getvattl(struct puffs_node *pn)
-{
-	return &pn->pn_va_ttl;
-}
-
-struct timespec *
-puffs_pn_getcnttl(struct puffs_node *pn)
-{
-	return &pn->pn_cn_ttl;
-}
-
-
 /* convenience / shortcut */
 void *
 puffs_pn_getmntspecific(struct puffs_node *pn)
@@ -187,3 +174,27 @@ puffs_newinfo_setrdev(struct puffs_newin
 
 	*pni->pni_rdev = rdev;
 }
+
+void
+puffs_newinfo_setva(struct puffs_newinfo *pni, struct vattr *va)
+{
+
+	(void)memcpy(pni->pni_va, va, sizeof(struct vattr));
+}
+
+void
+puffs_newinfo_setvattl(struct puffs_newinfo *pni, struct timespec *va_ttl)
+{
+
+	pni->pni_va_ttl->tv_sec = va_ttl->tv_sec;
+	pni->pni_va_ttl->tv_nsec = va_ttl->tv_nsec;
+}
+
+void
+puffs_newinfo_setcnttl(struct puffs_newinfo *pni, struct timespec *cn_ttl)
+{
+
+	pni->pni_cn_ttl->tv_sec = cn_ttl->tv_sec;
+	pni->pni_cn_ttl->tv_nsec = cn_ttl->tv_nsec;
+}
+

Index: src/lib/libpuffs/puffs.3
diff -u src/lib/libpuffs/puffs.3:1.51 src/lib/libpuffs/puffs.3:1.52
--- src/lib/libpuffs/puffs.3:1.51	Sun Apr  8 16:09:55 2012
+++ src/lib/libpuffs/puffs.3	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-.\"	$NetBSD: puffs.3,v 1.51 2012/04/08 16:09:55 wiz Exp $
+.\"	$NetBSD: puffs.3,v 1.52 2012/04/18 00:57:22 manu Exp $
 .\"
 .\" Copyright (c) 2006, 2007, 2008 Antti Kantee.  All rights reserved.
 .\"
@@ -237,15 +237,22 @@ Especially if the file system uses the a
 is a good idea to define this flag.
 .It Dv PUFFS_KFLAG_CACHE_FS_TTL
 Enforce name and attribute caches based on file system-supplied TTL.
-In lookup, create, mknod, mkdir, symlink, getattr, and setattr,
-the file system must update the attributes and their TTL through
-.Fn puffs_pn_getvap
-and
-.Fn puffs_pn_getvattl .
-.Pp
-In lookup, create, mknod, mkdir, and symlink,
-the name TTL must be updated through
-.Fn puffs_pn_getcnttl .
+In lookup, create, mknod, mkdir, and symlink, the file system must 
+update the node attributes, their TTL, and the node name TTL  through
+.Fn puffs_newinfo_setva ,
+.Fn puffs_newinfo_setvattl
+and
+.Fn puffs_newinfo_setcnttl .
+.Pp
+Additionally, 
+.Fn puffs_node_getattr_ttl
+and
+.Fn puffs_node_setattr_ttl
+will be called instead of 
+.Fn puffs_node_getattr
+and
+.Fn puffs_node_setattr .
+
 .It Dv PUFFS_FLAG_OPDUMP
 This option makes the framework dump a textual representation of
 each operation before executing it.

Index: src/lib/libpuffs/puffs.h
diff -u src/lib/libpuffs/puffs.h:1.120 src/lib/libpuffs/puffs.h:1.121
--- src/lib/libpuffs/puffs.h:1.120	Sun Apr  8 15:07:45 2012
+++ src/lib/libpuffs/puffs.h	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: puffs.h,v 1.120 2012/04/08 15:07:45 manu Exp $	*/
+/*	$NetBSD: puffs.h,v 1.121 2012/04/18 00:57:22 manu Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007  Antti Kantee.  All Rights Reserved.
@@ -89,9 +89,6 @@ struct puffs_node {
 	LIST_ENTRY(puffs_node)	pn_entries;
 
 	LIST_HEAD(,puffs_kcache)pn_cacheinfo;	/* PUFFS_KFLAG_CACHE	*/
-
-	struct timespec		pn_cn_ttl;	/* PUFFS_FLAG_CACHE_FS_TTL */
-	struct timespec		pn_va_ttl;	/* PUFFS_FLAG_CACHE_FS_TTL */
 };
 #define PUFFS_NODE_REMOVED	0x01		/* not on entry list	*/
 
@@ -236,8 +233,14 @@ struct puffs_ops {
 	    int, size_t *, uint8_t *, size_t *, int, const struct puffs_cred *);
 	int (*puffs_node_deleteextattr)(struct puffs_usermount *,
 	    puffs_cookie_t, int, const char *, const struct puffs_cred *);
+	int (*puffs_node_getattr_ttl)(struct puffs_usermount *,
+	    puffs_cookie_t, struct vattr *, const struct puffs_cred *,
+	    struct timespec *);
+	int (*puffs_node_setattr_ttl)(struct puffs_usermount *,
+	    puffs_cookie_t, struct vattr *, const struct puffs_cred *,
+	    struct timespec *);
 
-	void *puffs_ops_spare[32];
+	void *puffs_ops_spare[30];
 };
 
 typedef	int (*pu_pathbuild_fn)(struct puffs_usermount *,
@@ -384,7 +387,14 @@ enum {
 	    int, const struct puffs_cred *);				\
 	int fsname##_node_deleteextattr(struct puffs_usermount *,	\
 	    puffs_cookie_t, int, const char *,				\
-	    const struct puffs_cred *);
+	    const struct puffs_cred *);					\
+	int fsname##_node_getattr_ttl(struct puffs_usermount *,		\
+	    puffs_cookie_t, struct vattr *, const struct puffs_cred *,	\
+	    struct timespec *);						\
+	int fsname##_node_setattr_ttl(struct puffs_usermount *,		\
+	    puffs_cookie_t, struct vattr *, const struct puffs_cred *,	\
+	    struct timespec *);
+
 
 #define PUFFSOP_INIT(ops)						\
     ops = malloc(sizeof(struct puffs_ops));				\
@@ -494,6 +504,9 @@ void	puffs_newinfo_setcookie(struct puff
 void	puffs_newinfo_setvtype(struct puffs_newinfo *, enum vtype);
 void	puffs_newinfo_setsize(struct puffs_newinfo *, voff_t);
 void	puffs_newinfo_setrdev(struct puffs_newinfo *, dev_t);
+void	puffs_newinfo_setva(struct puffs_newinfo *, struct vattr *);
+void	puffs_newinfo_setvattl(struct puffs_newinfo *, struct timespec *);
+void	puffs_newinfo_setcnttl(struct puffs_newinfo *, struct timespec *);
 
 void			*puffs_pn_getmntspecific(struct puffs_node *);
 

Index: src/lib/libpuffs/puffs_ops.3
diff -u src/lib/libpuffs/puffs_ops.3:1.29 src/lib/libpuffs/puffs_ops.3:1.30
--- src/lib/libpuffs/puffs_ops.3:1.29	Mon Jul  4 08:07:30 2011
+++ src/lib/libpuffs/puffs_ops.3	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-.\"	$NetBSD: puffs_ops.3,v 1.29 2011/07/04 08:07:30 manu Exp $
+.\"	$NetBSD: puffs_ops.3,v 1.30 2012/04/18 00:57:22 manu Exp $
 .\"
 .\" Copyright (c) 2007 Antti Kantee.  All rights reserved.
 .\"
@@ -103,6 +103,16 @@
 .Fa "const struct puffs_cred *pcr"
 .Fc
 .Ft int
+.Fo puffs_node_getattr_ttl
+.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "struct vattr *vap"
+.Fa "const struct puffs_cred *pcr" "struct timespec *va_ttl"
+.Fc
+.Ft int
+.Fo puffs_node_setattr_ttl
+.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "const struct vattr *vap"
+.Fa "const struct puffs_cred *pcr" "struct timespec *va_ttl"
+.Fc
+.Ft int
 .Fo puffs_node_poll
 .Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int *events"
 .Fc
@@ -225,6 +235,12 @@
 .Fn puffs_newinfo_setsize "struct puffs_newinfo *pni" "voff_t size"
 .Ft void
 .Fn puffs_newinfo_setrdev "struct puffs_newinfo *pni" "dev_t rdev"
+.Ft void
+.Fn puffs_newinfo_setva "struct puffs_newinfo *pni" "struct vattr *vap"
+.Ft void
+.Fn puffs_newinfo_setvattl "struct puffs_newinfo *pni" "struct timespec *va_ttl"
+.Ft void
+.Fn puffs_newinfo_setcnttl "struct puffs_newinfo *pni" "struct timespec *cn_ttl"
 .Sh DESCRIPTION
 The operations
 .Nm puffs
@@ -370,6 +386,18 @@ If the located entry is a block device o
 the dev_t for the entry should be set using
 .Fn puffs_newinfo_setrdev .
 .Pp
+If 
+.Fn puffs_init
+was called with
+.Dv PUFFS_KFLAG_CACHE_FS_TTL
+then 
+.Fn puffs_newinfo_setva ,
+.Fn puffs_newinfo_setvattl ,
+and
+.Fn puffs_newinfo_setcnttl
+can be called to specify the new node attributes, cached attributes
+time to live, and cached name timeto live.
+.Pp
 The type of operation is found from
 .Va pcn-\*[Gt]pcn_nameiop :
 .Bl -tag -width XNAMEI_LOOKUPX
@@ -478,6 +506,11 @@ The attributes of the node specified by
 .Fa opc
 must be copied to the space pointed by
 .Fa va .
+.It Fn puffs_node_getattr_ttl "pu" "opc" "va" "pcr" "va_ttl"
+Same as
+.Fn puffs_node_getattr
+with cached attribute time to live specified in
+.Fa va_ttl
 .It Fn puffs_node_setattr "pu" "opc" "va" "pcr"
 The attributes for the node specified by
 .Fa opc
@@ -488,6 +521,11 @@ Only fields of
 which contain a value different from
 .Dv PUFFS_VNOVAL
 (typecast to the field's type!) contain a valid value.
+.It Fn puffs_node_setattr_ttl "pu" "opc" "va" "pcr" "va_ttl"
+Same as
+.Fn puffs_node_setattr
+with cached attribute time to live specified in
+.Fa va_ttl
 .It Fn puffs_node_poll "pu" "opc" "events"
 Poll for events on node
 .Ar opc .
@@ -788,6 +826,46 @@ This call is valid only for
 and
 .Fn fhtovp
 producing device type nodes.
+.It Fn puffs_newinfo_setva pni vap
+Set the attributes for newly created vnode. This call is valid for 
+.Fn lookup ,
+.Fn create ,
+.Fn mkdir ,
+.Fn mknod ,
+and
+.Fn symlink ,
+if
+.Fn puffs_init
+vas called with 
+.Dv PUFFS_KFLAG_CACHE_FS_TTL
+flag set.
+.It Fn puffs_newinfo_setvattl pni va_ttl
+Set cached attribute time to live for newly created vnode. 
+This call is valid for 
+.Fn lookup ,
+.Fn create ,
+.Fn mkdir ,
+.Fn mknod ,
+and
+.Fn symlink ,
+if
+.Fn puffs_init
+vas called with 
+.Dv PUFFS_KFLAG_CACHE_FS_TTL
+flag set.
+.It Fn puffs_newinfo_setcnttl pni cn_ttl
+Set cached name time to live for newly created vnode. This call is valid for 
+.Fn lookup ,
+.Fn create ,
+.Fn mkdir ,
+.Fn mknod ,
+and
+.Fn symlink ,
+if
+.Fn puffs_init
+vas called with 
+.Dv PUFFS_KFLAG_CACHE_FS_TTL
+flag set.
 .El
 .Sh SEE ALSO
 .Xr puffs 3 ,

Index: src/lib/libpuffs/puffs_priv.h
diff -u src/lib/libpuffs/puffs_priv.h:1.44 src/lib/libpuffs/puffs_priv.h:1.45
--- src/lib/libpuffs/puffs_priv.h:1.44	Mon Jun 20 09:11:17 2011
+++ src/lib/libpuffs/puffs_priv.h	Wed Apr 18 00:57:22 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: puffs_priv.h,v 1.44 2011/06/20 09:11:17 mrg Exp $	*/
+/*	$NetBSD: puffs_priv.h,v 1.45 2012/04/18 00:57:22 manu Exp $	*/
 
 /*
  * Copyright (c) 2006, 2007, 2008 Antti Kantee.  All Rights Reserved.
@@ -199,6 +199,9 @@ struct puffs_newinfo {
 	enum vtype	*pni_vtype;
 	voff_t		*pni_size;
 	dev_t		*pni_rdev;
+	struct vattr	*pni_va;
+	struct timespec	*pni_va_ttl;
+	struct timespec	*pni_cn_ttl;
 };
 
 #define PUFFS_MAKEKCRED(to, from)					\

Reply via email to