| @@ -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 |
897 | static int | | 912 | static int |
898 | dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags) | | 913 | dosetattr(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 | |
966 | int | | 983 | int |
967 | puffs_vnop_setattr(void *v) | | 984 | puffs_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 | |
979 | static __inline int | | 1002 | static __inline int |
980 | doinact(struct puffs_mount *pmp, int iaflag) | | 1003 | doinact(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 |
1013 | puffs_vnop_inactive(void *v) | | 1036 | puffs_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 | |
1053 | static void | | 1078 | static void |
1054 | callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck) | | 1079 | callreclaim(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 |
1318 | int | | 1343 | int |
1319 | puffs_vnop_fsync(void *v) | | 1344 | puffs_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 | |
| | | 1407 | out: |
| | | 1408 | mutex_exit(&pn->pn_sizemtx); |
1380 | return error; | | 1409 | return error; |
1381 | } | | 1410 | } |
1382 | | | 1411 | |
1383 | int | | 1412 | int |
1384 | puffs_vnop_seek(void *v) | | 1413 | puffs_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 | */ |
1893 | int | | 1922 | int |
1894 | puffs_vnop_write(void *v) | | 1923 | puffs_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 | |
2040 | int | | 2073 | int |
2041 | puffs_vnop_print(void *v) | | 2074 | puffs_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; |