Module Name:    src
Committed By:   manu
Date:           Wed Apr 18 00:42:50 UTC 2012

Modified Files:
        src/sys/fs/puffs: puffs_vnops.c

Log Message:
- Makesure update_va does not change vnode size when it should not. For
instance when doing a fault-issued VOP_GETPAGES within VOP_WRITE, changing
size leads to panic: genfs_getpages: past eof.
-Handle ticks wrap around for vnode name andattribute timeout


To generate a diff of this commit:
cvs rdiff -u -r1.165 -r1.166 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_vnops.c
diff -u src/sys/fs/puffs/puffs_vnops.c:1.165 src/sys/fs/puffs/puffs_vnops.c:1.166
--- src/sys/fs/puffs/puffs_vnops.c:1.165	Sun Apr  8 15:04:41 2012
+++ src/sys/fs/puffs/puffs_vnops.c	Wed Apr 18 00:42:50 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: puffs_vnops.c,v 1.165 2012/04/08 15:04:41 manu Exp $	*/
+/*	$NetBSD: puffs_vnops.c,v 1.166 2012/04/18 00:42:50 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.165 2012/04/08 15:04:41 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.166 2012/04/18 00:42:50 manu Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -299,6 +299,11 @@ const struct vnodeopv_entry_desc puffs_m
 const struct vnodeopv_desc puffs_msgop_opv_desc =
 	{ &puffs_msgop_p, puffs_msgop_entries };
 
+/*
+ * for dosetattr / update_va 
+ */
+#define SETATTR_CHSIZE	0x01
+#define SETATTR_ASYNC	0x02
 
 #define ERROUT(err)							\
 do {									\
@@ -412,7 +417,7 @@ static void callinactive(struct puffs_mo
 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 *);
+		      struct timespec *, struct timespec *, int);
 
 
 #define PUFFS_ABORT_LOOKUP	1
@@ -460,6 +465,10 @@ puffs_abortbutton(struct puffs_mount *pm
 
 #define TTL_TO_TIMEOUT(ts) \
     (hardclock_ticks + (ts->tv_sec * hz) + (ts->tv_nsec * hz / 1000000000))
+#define TTL_VALID(ts) \
+    ((ts != NULL) && !((ts->tv_sec == 0) && (ts->tv_nsec == 0)))
+#define TIMED_OUT(expire) \
+    ((int)((unsigned int)hardclock_ticks - (unsigned int)expire) > 0)
 int
 puffs_vnop_lookup(void *v)
 {
@@ -505,7 +514,7 @@ puffs_vnop_lookup(void *v)
 
 			cvp = *ap->a_vpp;
 			cpn = VPTOPP(cvp);
-			if (hardclock_ticks > cpn->pn_cn_timeout) {
+			if (TIMED_OUT(cpn->pn_cn_timeout)) {
 				cache_purge1(cvp, NULL, PURGE_CHILDREN);
 
 				/*
@@ -636,7 +645,8 @@ puffs_vnop_lookup(void *v)
 	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);
+		update_va(vp, NULL, &lookup_msg->pvnr_va, 
+			  va_ttl, cn_ttl, SETATTR_CHSIZE);
 	}
 
 	*ap->a_vpp = vp;
@@ -737,7 +747,8 @@ puffs_vnop_create(void *v)
 		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);
+		update_va(*ap->a_vpp, NULL, rvap, 
+			  va_ttl, cn_ttl, SETATTR_CHSIZE);
 	}
 
  out:
@@ -793,7 +804,8 @@ puffs_vnop_mknod(void *v)
 		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);
+		update_va(*ap->a_vpp, NULL, rvap, 
+			   va_ttl, cn_ttl, SETATTR_CHSIZE);
 	}
 
  out:
@@ -912,11 +924,11 @@ puffs_vnop_access(void *v)
 
 static void
 update_va(struct vnode *vp, struct vattr *vap, struct vattr *rvap,
-	  struct timespec *va_ttl, struct timespec *cn_ttl)
+	  struct timespec *va_ttl, struct timespec *cn_ttl, int flags)
 {
 	struct puffs_node *pn = VPTOPP(vp);
 
-	if (cn_ttl != NULL)
+	if (TTL_VALID(cn_ttl))
 		pn->pn_cn_timeout = TTL_TO_TIMEOUT(cn_ttl);
 
 	/*
@@ -946,7 +958,7 @@ update_va(struct vnode *vp, struct vattr
 			vap->va_size = pn->pn_mc_size;
 	}
 
-	if (!(pn->pn_stat & PNODE_METACACHE_SIZE)) {
+	if (!(pn->pn_stat & PNODE_METACACHE_SIZE) && (flags & SETATTR_CHSIZE)) {
 		if (rvap->va_size != VNOVAL
 		    && vp->v_type != VBLK && vp->v_type != VCHR) {
 			uvm_vnp_setsize(vp, rvap->va_size);
@@ -954,7 +966,7 @@ update_va(struct vnode *vp, struct vattr
 		}
 	}
 
-	if (va_ttl != NULL) {
+	if ((va_ttl != NULL) && TTL_VALID(va_ttl)) {
 		if (pn->pn_va_cache == NULL)
 			pn->pn_va_cache = pool_get(&puffs_vapool, PR_WAITOK);
 
@@ -1001,8 +1013,9 @@ puffs_vnop_getattr(void *v)
 	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);
+		if (!TIMED_OUT(pn->pn_va_timeout)) {
+			update_va(vp, vap, pn->pn_va_cache, 
+				  NULL, NULL, SETATTR_CHSIZE);
 			goto out2;
 		}
 	}
@@ -1023,7 +1036,7 @@ puffs_vnop_getattr(void *v)
 	if (PUFFS_USE_FS_TTL(pmp))
 		va_ttl = &getattr_msg->pvnr_va_ttl;
 
-	update_va(vp, vap, rvap, va_ttl, NULL);
+	update_va(vp, vap, rvap, va_ttl, NULL, SETATTR_CHSIZE);
 
  out:
 	PUFFS_MSG_RELEASE(getattr);
@@ -1036,8 +1049,6 @@ puffs_vnop_getattr(void *v)
 	return error;
 }
 
-#define SETATTR_CHSIZE	0x01
-#define SETATTR_ASYNC	0x02
 static int
 dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags)
 {
@@ -1103,7 +1114,7 @@ dosetattr(struct vnode *vp, struct vattr
 		struct timespec *va_ttl = &setattr_msg->pvnr_va_ttl;
 		struct vattr *rvap = &setattr_msg->pvnr_va;
 
-		update_va(vp, NULL, rvap, va_ttl, NULL);
+		update_va(vp, NULL, rvap, va_ttl, NULL, flags);
 	}
 
 	PUFFS_MSG_RELEASE(setattr);
@@ -1703,7 +1714,8 @@ puffs_vnop_mkdir(void *v)
 		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);
+		update_va(*ap->a_vpp, NULL, rvap, 
+			  va_ttl, cn_ttl, SETATTR_CHSIZE);
 	}
 
  out:
@@ -1866,7 +1878,8 @@ puffs_vnop_symlink(void *v)
 		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);
+		update_va(*ap->a_vpp, NULL, rvap, 
+			  va_ttl, cn_ttl, SETATTR_CHSIZE);
 	}
 
  out:

Reply via email to