Mon Aug 29 04:12:46 2011 UTC ()
Add a mutex for operations that touch size (setattr, getattr, write, fsync).

This is required to avoid data corruption bugs, where a getattr slices
itself within a setattr operation, and sets the size to the stall value
it got from the filesystem. That value is smaller than the one set by
setattr, and the call to uvm_vnp_setsize() trigged a spurious truncate.
The result is a chunk of zeroed data in the file.

Such a situation can easily happen when the ioflush thread issue a
VOP_FSYNC/puffs_vnop_sync/flushvncache/dosetattrn while andother process
do a sys_stat/VOP_GETATTR/puffs_vnop_getattr.

This mutex on size operation can be removed the day we decide VOP_GETATTR
has to operated on a locked vnode, since the other operations that touch
size already require that.


(manu)
diff -r1.19 -r1.20 src/sys/fs/puffs/puffs_node.c
diff -r1.77 -r1.78 src/sys/fs/puffs/puffs_sys.h
diff -r1.154 -r1.155 src/sys/fs/puffs/puffs_vnops.c

cvs diff -r1.19 -r1.20 src/sys/fs/puffs/puffs_node.c (expand / switch to unified diff)

--- src/sys/fs/puffs/puffs_node.c 2011/06/30 20:09:41 1.19
+++ src/sys/fs/puffs/puffs_node.c 2011/08/29 04:12:45 1.20
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: puffs_node.c,v 1.19 2011/06/30 20:09:41 wiz Exp $ */ 1/* $NetBSD: puffs_node.c,v 1.20 2011/08/29 04:12:45 manu Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Development of this software was supported by the 6 * Development of this software was supported by the
7 * Google Summer of Code program, the Ulla Tuominen Foundation 7 * Google Summer of Code program, the Ulla Tuominen Foundation
8 * and the Finnish Cultural Foundation. 8 * and the Finnish Cultural Foundation.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.19 2011/06/30 20:09:41 wiz Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.20 2011/08/29 04:12:45 manu Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/hash.h> 36#include <sys/hash.h>
37#include <sys/kmem.h> 37#include <sys/kmem.h>
38#include <sys/malloc.h> 38#include <sys/malloc.h>
39#include <sys/mount.h> 39#include <sys/mount.h>
40#include <sys/namei.h> 40#include <sys/namei.h>
41#include <sys/vnode.h> 41#include <sys/vnode.h>
42 42
43#include <fs/puffs/puffs_msgif.h> 43#include <fs/puffs/puffs_msgif.h>
44#include <fs/puffs/puffs_sys.h> 44#include <fs/puffs/puffs_sys.h>
45 45
46#include <miscfs/genfs/genfs_node.h> 46#include <miscfs/genfs/genfs_node.h>
@@ -145,26 +145,27 @@ puffs_getvnode(struct mount *mp, puffs_c @@ -145,26 +145,27 @@ puffs_getvnode(struct mount *mp, puffs_c
145 plist = puffs_cookie2hashlist(pmp, ck); 145 plist = puffs_cookie2hashlist(pmp, ck);
146 mutex_enter(&pmp->pmp_lock); 146 mutex_enter(&pmp->pmp_lock);
147 LIST_INSERT_HEAD(plist, pnode, pn_hashent); 147 LIST_INSERT_HEAD(plist, pnode, pn_hashent);
148 if (ck != pmp->pmp_root_cookie) { 148 if (ck != pmp->pmp_root_cookie) {
149 LIST_FOREACH(pnc, &pmp->pmp_newcookie, pnc_entries) { 149 LIST_FOREACH(pnc, &pmp->pmp_newcookie, pnc_entries) {
150 if (pnc->pnc_cookie == ck) { 150 if (pnc->pnc_cookie == ck) {
151 LIST_REMOVE(pnc, pnc_entries); 151 LIST_REMOVE(pnc, pnc_entries);
152 kmem_free(pnc, sizeof(struct puffs_newcookie)); 152 kmem_free(pnc, sizeof(struct puffs_newcookie));
153 break; 153 break;
154 } 154 }
155 } 155 }
156 KASSERT(pnc != NULL); 156 KASSERT(pnc != NULL);
157 } 157 }
 158 mutex_init(&pnode->pn_sizemtx, MUTEX_DEFAULT, IPL_NONE);
158 mutex_exit(&pmp->pmp_lock); 159 mutex_exit(&pmp->pmp_lock);
159 160
160 vp->v_data = pnode; 161 vp->v_data = pnode;
161 vp->v_type = type; 162 vp->v_type = type;
162 pnode->pn_vp = vp; 163 pnode->pn_vp = vp;
163 pnode->pn_serversize = vsize; 164 pnode->pn_serversize = vsize;
164 165
165 genfs_node_init(vp, &puffs_genfsops); 166 genfs_node_init(vp, &puffs_genfsops);
166 *vpp = vp; 167 *vpp = vp;
167 168
168 DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp, 169 DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp,
169 pnode, pnode->pn_cookie)); 170 pnode, pnode->pn_cookie));
170 171
@@ -453,19 +454,20 @@ puffs_referencenode(struct puffs_node *p @@ -453,19 +454,20 @@ puffs_referencenode(struct puffs_node *p
453 * puffs_node instead of the vnode. Can't use vref()/vrele() on 454 * puffs_node instead of the vnode. Can't use vref()/vrele() on
454 * the vnode there, since that causes the lovely VOP_INACTIVE(), 455 * the vnode there, since that causes the lovely VOP_INACTIVE(),
455 * which in turn causes the lovely deadlock when called by the one 456 * which in turn causes the lovely deadlock when called by the one
456 * who is supposed to handle it. 457 * who is supposed to handle it.
457 */ 458 */
458void 459void
459puffs_releasenode(struct puffs_node *pn) 460puffs_releasenode(struct puffs_node *pn)
460{ 461{
461 462
462 mutex_enter(&pn->pn_mtx); 463 mutex_enter(&pn->pn_mtx);
463 if (--pn->pn_refcount == 0) { 464 if (--pn->pn_refcount == 0) {
464 mutex_exit(&pn->pn_mtx); 465 mutex_exit(&pn->pn_mtx);
465 mutex_destroy(&pn->pn_mtx); 466 mutex_destroy(&pn->pn_mtx);
 467 mutex_destroy(&pn->pn_sizemtx);
466 seldestroy(&pn->pn_sel); 468 seldestroy(&pn->pn_sel);
467 pool_put(&puffs_pnpool, pn); 469 pool_put(&puffs_pnpool, pn);
468 } else { 470 } else {
469 mutex_exit(&pn->pn_mtx); 471 mutex_exit(&pn->pn_mtx);
470 } 472 }
471} 473}

cvs diff -r1.77 -r1.78 src/sys/fs/puffs/puffs_sys.h (expand / switch to unified diff)

--- src/sys/fs/puffs/puffs_sys.h 2011/01/11 14:04:54 1.77
+++ src/sys/fs/puffs/puffs_sys.h 2011/08/29 04:12:45 1.78
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: puffs_sys.h,v 1.77 2011/01/11 14:04:54 kefren Exp $ */ 1/* $NetBSD: puffs_sys.h,v 1.78 2011/08/29 04:12:45 manu Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Development of this software was supported by the 6 * Development of this software was supported by the
7 * Google Summer of Code program and the Ulla Tuominen Foundation. 7 * Google Summer of Code program and the Ulla Tuominen Foundation.
8 * The Google SoC project was mentored by Bill Studenmund. 8 * The Google SoC project was mentored by Bill Studenmund.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -199,26 +199,28 @@ struct puffs_node { @@ -199,26 +199,28 @@ struct puffs_node {
199 struct selinfo pn_sel; /* for selecting on the node */ 199 struct selinfo pn_sel; /* for selecting on the node */
200 short pn_revents; /* available events */ 200 short pn_revents; /* available events */
201 201
202 /* metacache */ 202 /* metacache */
203 struct timespec pn_mc_atime; 203 struct timespec pn_mc_atime;
204 struct timespec pn_mc_ctime; 204 struct timespec pn_mc_ctime;
205 struct timespec pn_mc_mtime; 205 struct timespec pn_mc_mtime;
206 u_quad_t pn_mc_size; 206 u_quad_t pn_mc_size;
207 207
208 voff_t pn_serversize; 208 voff_t pn_serversize;
209 209
210 struct lockf * pn_lockf; 210 struct lockf * pn_lockf;
211 211
 212 kmutex_t pn_sizemtx; /* size modification mutex */
 213
212 LIST_ENTRY(puffs_node) pn_hashent; 214 LIST_ENTRY(puffs_node) pn_hashent;
213}; 215};
214 216
215typedef void (*parkdone_fn)(struct puffs_mount *, struct puffs_req *, void *); 217typedef void (*parkdone_fn)(struct puffs_mount *, struct puffs_req *, void *);
216 218
217struct puffs_msgpark; 219struct puffs_msgpark;
218void puffs_msgif_init(void); 220void puffs_msgif_init(void);
219void puffs_msgif_destroy(void); 221void puffs_msgif_destroy(void);
220int puffs_msgmem_alloc(size_t, struct puffs_msgpark **, void **, int); 222int puffs_msgmem_alloc(size_t, struct puffs_msgpark **, void **, int);
221void puffs_msgmem_release(struct puffs_msgpark *); 223void puffs_msgmem_release(struct puffs_msgpark *);
222 224
223void puffs_sop_thread(void *); 225void puffs_sop_thread(void *);
224 226

cvs diff -r1.154 -r1.155 src/sys/fs/puffs/puffs_vnops.c (expand / switch to unified diff)

--- src/sys/fs/puffs/puffs_vnops.c 2011/07/04 08:07:30 1.154
+++ src/sys/fs/puffs/puffs_vnops.c 2011/08/29 04:12:45 1.155
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: puffs_vnops.c,v 1.154 2011/07/04 08:07:30 manu Exp $ */ 1/* $NetBSD: puffs_vnops.c,v 1.155 2011/08/29 04:12:45 manu Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Development of this software was supported by the 6 * Development of this software was supported by the
7 * Google Summer of Code program and the Ulla Tuominen Foundation. 7 * Google Summer of Code program and the Ulla Tuominen Foundation.
8 * The Google SoC project was mentored by Bill Studenmund. 8 * The Google SoC project was mentored by Bill Studenmund.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.154 2011/07/04 08:07:30 manu Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.155 2011/08/29 04:12:45 manu Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/buf.h> 36#include <sys/buf.h>
37#include <sys/lockf.h> 37#include <sys/lockf.h>
38#include <sys/malloc.h> 38#include <sys/malloc.h>
39#include <sys/mount.h> 39#include <sys/mount.h>
40#include <sys/namei.h> 40#include <sys/namei.h>
41#include <sys/vnode.h> 41#include <sys/vnode.h>
42#include <sys/proc.h> 42#include <sys/proc.h>
43 43
44#include <uvm/uvm.h> 44#include <uvm/uvm.h>
45 45
46#include <fs/puffs/puffs_msgif.h> 46#include <fs/puffs/puffs_msgif.h>
@@ -829,26 +829,38 @@ puffs_vnop_getattr(void *v) @@ -829,26 +829,38 @@ puffs_vnop_getattr(void *v)
829 const struct vnodeop_desc *a_desc; 829 const struct vnodeop_desc *a_desc;
830 struct vnode *a_vp; 830 struct vnode *a_vp;
831 struct vattr *a_vap; 831 struct vattr *a_vap;
832 kauth_cred_t a_cred; 832 kauth_cred_t a_cred;
833 } */ *ap = v; 833 } */ *ap = v;
834 PUFFS_MSG_VARS(vn, getattr); 834 PUFFS_MSG_VARS(vn, getattr);
835 struct vnode *vp = ap->a_vp; 835 struct vnode *vp = ap->a_vp;
836 struct mount *mp = vp->v_mount; 836 struct mount *mp = vp->v_mount;
837 struct puffs_mount *pmp = MPTOPUFFSMP(mp); 837 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
838 struct vattr *vap, *rvap; 838 struct vattr *vap, *rvap;
839 struct puffs_node *pn = VPTOPP(vp); 839 struct puffs_node *pn = VPTOPP(vp);
840 int error = 0; 840 int error = 0;
841 841
 842 /*
 843 * A lock is required so that we do not race with
 844 * setattr, write and fsync when changing vp->v_size.
 845 * This is critical, since setting a stall smaler value
 846 * triggers a file truncate in uvm_vnp_setsize(), which
 847 * most of the time means data corruption (a chunk of
 848 * data is replaced by zeroes). This can be removed if
 849 * we decide one day that VOP_GETATTR must operate on
 850 * a locked vnode.
 851 */
 852 mutex_enter(&pn->pn_sizemtx);
 853
842 REFPN(pn); 854 REFPN(pn);
843 vap = ap->a_vap; 855 vap = ap->a_vap;
844 856
845 PUFFS_MSG_ALLOC(vn, getattr); 857 PUFFS_MSG_ALLOC(vn, getattr);
846 vattr_null(&getattr_msg->pvnr_va); 858 vattr_null(&getattr_msg->pvnr_va);
847 puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred); 859 puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred);
848 puffs_msg_setinfo(park_getattr, PUFFSOP_VN, 860 puffs_msg_setinfo(park_getattr, PUFFSOP_VN,
849 PUFFS_VN_GETATTR, VPTOPNC(vp)); 861 PUFFS_VN_GETATTR, VPTOPNC(vp));
850 862
851 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error); 863 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error);
852 error = checkerr(pmp, error, __func__); 864 error = checkerr(pmp, error, __func__);
853 if (error) 865 if (error)
854 goto out; 866 goto out;
@@ -879,39 +891,44 @@ puffs_vnop_getattr(void *v) @@ -879,39 +891,44 @@ puffs_vnop_getattr(void *v)
879 if (pn->pn_stat & PNODE_METACACHE_SIZE) { 891 if (pn->pn_stat & PNODE_METACACHE_SIZE) {
880 vap->va_size = pn->pn_mc_size; 892 vap->va_size = pn->pn_mc_size;
881 } else { 893 } else {
882 if (rvap->va_size != VNOVAL 894 if (rvap->va_size != VNOVAL
883 && vp->v_type != VBLK && vp->v_type != VCHR) { 895 && vp->v_type != VBLK && vp->v_type != VCHR) {
884 uvm_vnp_setsize(vp, rvap->va_size); 896 uvm_vnp_setsize(vp, rvap->va_size);
885 pn->pn_serversize = rvap->va_size; 897 pn->pn_serversize = rvap->va_size;
886 } 898 }
887 } 899 }
888 900
889 out: 901 out:
890 puffs_releasenode(pn); 902 puffs_releasenode(pn);
891 PUFFS_MSG_RELEASE(getattr); 903 PUFFS_MSG_RELEASE(getattr);
 904
 905 mutex_exit(&pn->pn_sizemtx);
 906
892 return error; 907 return error;
893} 908}
894 909
895#define SETATTR_CHSIZE 0x01 910#define SETATTR_CHSIZE 0x01
896#define SETATTR_ASYNC 0x02 911#define SETATTR_ASYNC 0x02
897static int 912static int
898dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags) 913dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags)
899{ 914{
900 PUFFS_MSG_VARS(vn, setattr); 915 PUFFS_MSG_VARS(vn, setattr);
901 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 916 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
902 struct puffs_node *pn = vp->v_data; 917 struct puffs_node *pn = vp->v_data;
903 int error = 0; 918 int error = 0;
904 919
 920 KASSERT(!(flags & SETATTR_CHSIZE) || mutex_owned(&pn->pn_sizemtx));
 921
905 if ((vp->v_mount->mnt_flag & MNT_RDONLY) && 922 if ((vp->v_mount->mnt_flag & MNT_RDONLY) &&
906 (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL 923 (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL
907 || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL 924 || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL
908 || vap->va_mode != (mode_t)VNOVAL)) 925 || vap->va_mode != (mode_t)VNOVAL))
909 return EROFS; 926 return EROFS;
910 927
911 if ((vp->v_mount->mnt_flag & MNT_RDONLY) 928 if ((vp->v_mount->mnt_flag & MNT_RDONLY)
912 && vp->v_type == VREG && vap->va_size != VNOVAL) 929 && vp->v_type == VREG && vap->va_size != VNOVAL)
913 return EROFS; 930 return EROFS;
914 931
915 /* 932 /*
916 * Flush metacache first. If we are called with some explicit 933 * Flush metacache first. If we are called with some explicit
917 * parameters, treat them as information overriding metacache 934 * parameters, treat them as information overriding metacache
@@ -962,28 +979,34 @@ dosetattr(struct vnode *vp, struct vattr @@ -962,28 +979,34 @@ dosetattr(struct vnode *vp, struct vattr
962 979
963 return 0; 980 return 0;
964} 981}
965 982
966int 983int
967puffs_vnop_setattr(void *v) 984puffs_vnop_setattr(void *v)
968{ 985{
969 struct vop_getattr_args /* { 986 struct vop_getattr_args /* {
970 const struct vnodeop_desc *a_desc; 987 const struct vnodeop_desc *a_desc;
971 struct vnode *a_vp; 988 struct vnode *a_vp;
972 struct vattr *a_vap; 989 struct vattr *a_vap;
973 kauth_cred_t a_cred; 990 kauth_cred_t a_cred;
974 } */ *ap = v; 991 } */ *ap = v;
 992 struct puffs_node *pn = ap->a_vp->v_data;
 993 int error;
975 994
976 return dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE); 995 mutex_enter(&pn->pn_sizemtx);
 996 error = dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE);
 997 mutex_exit(&pn->pn_sizemtx);
 998
 999 return error;
977} 1000}
978 1001
979static __inline int 1002static __inline int
980doinact(struct puffs_mount *pmp, int iaflag) 1003doinact(struct puffs_mount *pmp, int iaflag)
981{ 1004{
982 1005
983 if (EXISTSOP(pmp, INACTIVE)) 1006 if (EXISTSOP(pmp, INACTIVE))
984 if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND) 1007 if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND)
985 if (iaflag || ALLOPS(pmp)) 1008 if (iaflag || ALLOPS(pmp))
986 return 1; 1009 return 1;
987 else 1010 else
988 return 0; 1011 return 0;
989 else 1012 else
@@ -1013,48 +1036,50 @@ int @@ -1013,48 +1036,50 @@ int
1013puffs_vnop_inactive(void *v) 1036puffs_vnop_inactive(void *v)
1014{ 1037{
1015 struct vop_inactive_args /* { 1038 struct vop_inactive_args /* {
1016 const struct vnodeop_desc *a_desc; 1039 const struct vnodeop_desc *a_desc;
1017 struct vnode *a_vp; 1040 struct vnode *a_vp;
1018 } */ *ap = v; 1041 } */ *ap = v;
1019 PUFFS_MSG_VARS(vn, inactive); 1042 PUFFS_MSG_VARS(vn, inactive);
1020 struct vnode *vp = ap->a_vp; 1043 struct vnode *vp = ap->a_vp;
1021 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1044 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1022 struct puffs_node *pnode; 1045 struct puffs_node *pnode;
1023 int error; 1046 int error;
1024 1047
1025 pnode = vp->v_data; 1048 pnode = vp->v_data;
 1049 mutex_enter(&pnode->pn_sizemtx);
1026 1050
1027 if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) { 1051 if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) {
1028 flushvncache(vp, 0, 0, false); 1052 flushvncache(vp, 0, 0, false);
1029 PUFFS_MSG_ALLOC(vn, inactive); 1053 PUFFS_MSG_ALLOC(vn, inactive);
1030 puffs_msg_setinfo(park_inactive, PUFFSOP_VN, 1054 puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
1031 PUFFS_VN_INACTIVE, VPTOPNC(vp)); 1055 PUFFS_VN_INACTIVE, VPTOPNC(vp));
1032 1056
1033 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_inactive, vp->v_data, 1057 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_inactive, vp->v_data,
1034 NULL, error); 1058 NULL, error);
1035 PUFFS_MSG_RELEASE(inactive); 1059 PUFFS_MSG_RELEASE(inactive);
1036 } 1060 }
1037 pnode->pn_stat &= ~PNODE_DOINACT; 1061 pnode->pn_stat &= ~PNODE_DOINACT;
1038 1062
1039 /* 1063 /*
1040 * file server thinks it's gone? then don't be afraid care, 1064 * file server thinks it's gone? then don't be afraid care,
1041 * node's life was already all it would ever be 1065 * node's life was already all it would ever be
1042 */ 1066 */
1043 if (pnode->pn_stat & PNODE_NOREFS) { 1067 if (pnode->pn_stat & PNODE_NOREFS) {
1044 pnode->pn_stat |= PNODE_DYING; 1068 pnode->pn_stat |= PNODE_DYING;
1045 *ap->a_recycle = true; 1069 *ap->a_recycle = true;
1046 } 1070 }
1047 1071
 1072 mutex_exit(&pnode->pn_sizemtx);
1048 VOP_UNLOCK(vp); 1073 VOP_UNLOCK(vp);
1049 1074
1050 return 0; 1075 return 0;
1051} 1076}
1052 1077
1053static void 1078static void
1054callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck) 1079callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck)
1055{ 1080{
1056 PUFFS_MSG_VARS(vn, reclaim); 1081 PUFFS_MSG_VARS(vn, reclaim);
1057 1082
1058 if (!EXISTSOP(pmp, RECLAIM)) 1083 if (!EXISTSOP(pmp, RECLAIM))
1059 return; 1084 return;
1060 1085
@@ -1318,43 +1343,45 @@ flushvncache(struct vnode *vp, off_t off @@ -1318,43 +1343,45 @@ flushvncache(struct vnode *vp, off_t off
1318int 1343int
1319puffs_vnop_fsync(void *v) 1344puffs_vnop_fsync(void *v)
1320{ 1345{
1321 struct vop_fsync_args /* { 1346 struct vop_fsync_args /* {
1322 const struct vnodeop_desc *a_desc; 1347 const struct vnodeop_desc *a_desc;
1323 struct vnode *a_vp; 1348 struct vnode *a_vp;
1324 kauth_cred_t a_cred; 1349 kauth_cred_t a_cred;
1325 int a_flags; 1350 int a_flags;
1326 off_t a_offlo; 1351 off_t a_offlo;
1327 off_t a_offhi; 1352 off_t a_offhi;
1328 } */ *ap = v; 1353 } */ *ap = v;
1329 PUFFS_MSG_VARS(vn, fsync); 1354 PUFFS_MSG_VARS(vn, fsync);
1330 struct vnode *vp = ap->a_vp; 1355 struct vnode *vp = ap->a_vp;
1331 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 
1332 struct puffs_node *pn = VPTOPP(vp); 1356 struct puffs_node *pn = VPTOPP(vp);
 1357 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1333 int error, dofaf; 1358 int error, dofaf;
1334 1359
 1360 mutex_enter(&pn->pn_sizemtx);
1335 error = flushvncache(vp, ap->a_offlo, ap->a_offhi, 1361 error = flushvncache(vp, ap->a_offlo, ap->a_offhi,
1336 (ap->a_flags & FSYNC_WAIT) == FSYNC_WAIT); 1362 (ap->a_flags & FSYNC_WAIT) == FSYNC_WAIT);
1337 if (error) 1363 if (error)
1338 return error; 1364 goto out;
1339 1365
1340 /* 1366 /*
1341 * HELLO! We exit already here if the user server does not 1367 * HELLO! We exit already here if the user server does not
1342 * support fsync OR if we should call fsync for a node which 1368 * support fsync OR if we should call fsync for a node which
1343 * has references neither in the kernel or the fs server. 1369 * has references neither in the kernel or the fs server.
1344 * Otherwise we continue to issue fsync() forward. 1370 * Otherwise we continue to issue fsync() forward.
1345 */ 1371 */
 1372 error = 0;
1346 if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING)) 1373 if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING))
1347 return 0; 1374 goto out;
1348 1375
1349 dofaf = (ap->a_flags & FSYNC_WAIT) == 0 || ap->a_flags == FSYNC_LAZY; 1376 dofaf = (ap->a_flags & FSYNC_WAIT) == 0 || ap->a_flags == FSYNC_LAZY;
1350 /* 1377 /*
1351 * We abuse VXLOCK to mean "vnode is going to die", so we issue 1378 * We abuse VXLOCK to mean "vnode is going to die", so we issue
1352 * only FAFs for those. Otherwise there's a danger of deadlock, 1379 * only FAFs for those. Otherwise there's a danger of deadlock,
1353 * since the execution context here might be the user server 1380 * since the execution context here might be the user server
1354 * doing some operation on another fs, which in turn caused a 1381 * doing some operation on another fs, which in turn caused a
1355 * vnode to be reclaimed from the freelist for this fs. 1382 * vnode to be reclaimed from the freelist for this fs.
1356 */ 1383 */
1357 if (dofaf == 0) { 1384 if (dofaf == 0) {
1358 mutex_enter(vp->v_interlock); 1385 mutex_enter(vp->v_interlock);
1359 if (vp->v_iflag & VI_XLOCK) 1386 if (vp->v_iflag & VI_XLOCK)
1360 dofaf = 1; 1387 dofaf = 1;
@@ -1367,26 +1394,28 @@ puffs_vnop_fsync(void *v) @@ -1367,26 +1394,28 @@ puffs_vnop_fsync(void *v)
1367 1394
1368 puffs_credcvt(&fsync_msg->pvnr_cred, ap->a_cred); 1395 puffs_credcvt(&fsync_msg->pvnr_cred, ap->a_cred);
1369 fsync_msg->pvnr_flags = ap->a_flags; 1396 fsync_msg->pvnr_flags = ap->a_flags;
1370 fsync_msg->pvnr_offlo = ap->a_offlo; 1397 fsync_msg->pvnr_offlo = ap->a_offlo;
1371 fsync_msg->pvnr_offhi = ap->a_offhi; 1398 fsync_msg->pvnr_offhi = ap->a_offhi;
1372 puffs_msg_setinfo(park_fsync, PUFFSOP_VN, 1399 puffs_msg_setinfo(park_fsync, PUFFSOP_VN,
1373 PUFFS_VN_FSYNC, VPTOPNC(vp)); 1400 PUFFS_VN_FSYNC, VPTOPNC(vp));
1374 1401
1375 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error); 1402 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error);
1376 PUFFS_MSG_RELEASE(fsync); 1403 PUFFS_MSG_RELEASE(fsync);
1377 1404
1378 error = checkerr(pmp, error, __func__); 1405 error = checkerr(pmp, error, __func__);
1379 1406
 1407out:
 1408 mutex_exit(&pn->pn_sizemtx);
1380 return error; 1409 return error;
1381} 1410}
1382 1411
1383int 1412int
1384puffs_vnop_seek(void *v) 1413puffs_vnop_seek(void *v)
1385{ 1414{
1386 struct vop_seek_args /* { 1415 struct vop_seek_args /* {
1387 const struct vnodeop_desc *a_desc; 1416 const struct vnodeop_desc *a_desc;
1388 struct vnode *a_vp; 1417 struct vnode *a_vp;
1389 off_t a_oldoff; 1418 off_t a_oldoff;
1390 off_t a_newoff; 1419 off_t a_newoff;
1391 kauth_cred_t a_cred; 1420 kauth_cred_t a_cred;
1392 } */ *ap = v; 1421 } */ *ap = v;
@@ -1892,37 +1921,40 @@ puffs_vnop_read(void *v) @@ -1892,37 +1921,40 @@ puffs_vnop_read(void *v)
1892 */ 1921 */
1893int 1922int
1894puffs_vnop_write(void *v) 1923puffs_vnop_write(void *v)
1895{ 1924{
1896 struct vop_write_args /* { 1925 struct vop_write_args /* {
1897 const struct vnodeop_desc *a_desc; 1926 const struct vnodeop_desc *a_desc;
1898 struct vnode *a_vp; 1927 struct vnode *a_vp;
1899 struct uio *a_uio; 1928 struct uio *a_uio;
1900 int a_ioflag; 1929 int a_ioflag;
1901 kauth_cred_t a_cred; 1930 kauth_cred_t a_cred;
1902 } */ *ap = v; 1931 } */ *ap = v;
1903 PUFFS_MSG_VARS(vn, write); 1932 PUFFS_MSG_VARS(vn, write);
1904 struct vnode *vp = ap->a_vp; 1933 struct vnode *vp = ap->a_vp;
 1934 struct puffs_node *pn = VPTOPP(vp);
1905 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1935 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1906 struct uio *uio = ap->a_uio; 1936 struct uio *uio = ap->a_uio;
1907 size_t tomove, argsize; 1937 size_t tomove, argsize;
1908 off_t oldoff, newoff, origoff; 1938 off_t oldoff, newoff, origoff;
1909 vsize_t bytelen; 1939 vsize_t bytelen;
1910 int error, uflags; 1940 int error, uflags;
1911 int ubcflags; 1941 int ubcflags;
1912 1942
1913 error = uflags = 0; 1943 error = uflags = 0;
1914 write_msg = NULL; 1944 write_msg = NULL;
1915 1945
 1946 mutex_enter(&pn->pn_sizemtx);
 1947
1916 if (vp->v_type == VREG && PUFFS_USE_PAGECACHE(pmp)) { 1948 if (vp->v_type == VREG && PUFFS_USE_PAGECACHE(pmp)) {
1917 ubcflags = UBC_WRITE | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp); 1949 ubcflags = UBC_WRITE | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp);
1918 1950
1919 /* 1951 /*
1920 * userspace *should* be allowed to control this, 1952 * userspace *should* be allowed to control this,
1921 * but with UBC it's a bit unclear how to handle it 1953 * but with UBC it's a bit unclear how to handle it
1922 */ 1954 */
1923 if (ap->a_ioflag & IO_APPEND) 1955 if (ap->a_ioflag & IO_APPEND)
1924 uio->uio_offset = vp->v_size; 1956 uio->uio_offset = vp->v_size;
1925 1957
1926 origoff = uio->uio_offset; 1958 origoff = uio->uio_offset;
1927 while (uio->uio_resid > 0) { 1959 while (uio->uio_resid > 0) {
1928 uflags |= PUFFS_UPDATECTIME; 1960 uflags |= PUFFS_UPDATECTIME;
@@ -2024,26 +2056,27 @@ puffs_vnop_write(void *v) @@ -2024,26 +2056,27 @@ puffs_vnop_write(void *v)
2024 /* adjust file size */ 2056 /* adjust file size */
2025 if (vp->v_size < uio->uio_offset) 2057 if (vp->v_size < uio->uio_offset)
2026 uvm_vnp_setsize(vp, uio->uio_offset); 2058 uvm_vnp_setsize(vp, uio->uio_offset);
2027 2059
2028 /* didn't move everything? bad userspace. bail */ 2060 /* didn't move everything? bad userspace. bail */
2029 if (write_msg->pvnr_resid != 0) { 2061 if (write_msg->pvnr_resid != 0) {
2030 error = EIO; 2062 error = EIO;
2031 break; 2063 break;
2032 } 2064 }
2033 } 2065 }
2034 puffs_msgmem_release(park_write); 2066 puffs_msgmem_release(park_write);
2035 } 2067 }
2036 2068
 2069 mutex_exit(&pn->pn_sizemtx);
2037 return error; 2070 return error;
2038} 2071}
2039 2072
2040int 2073int
2041puffs_vnop_print(void *v) 2074puffs_vnop_print(void *v)
2042{ 2075{
2043 struct vop_print_args /* { 2076 struct vop_print_args /* {
2044 struct vnode *a_vp; 2077 struct vnode *a_vp;
2045 } */ *ap = v; 2078 } */ *ap = v;
2046 PUFFS_MSG_VARS(vn, print); 2079 PUFFS_MSG_VARS(vn, print);
2047 struct vnode *vp = ap->a_vp; 2080 struct vnode *vp = ap->a_vp;
2048 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 2081 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
2049 struct puffs_node *pn = vp->v_data; 2082 struct puffs_node *pn = vp->v_data;