Tue Jan 17 09:30:16 2012 UTC ()
Add a few KASSERT() - I have a crash that likely will cause one of them to
fire...


(martin)
diff -r1.162 -r1.163 src/sys/fs/puffs/puffs_vnops.c

cvs diff -r1.162 -r1.163 src/sys/fs/puffs/puffs_vnops.c (switch to unified diff)

--- src/sys/fs/puffs/puffs_vnops.c 2011/11/18 21:18:50 1.162
+++ src/sys/fs/puffs/puffs_vnops.c 2012/01/17 09:30:16 1.163
@@ -1,2362 +1,2367 @@ @@ -1,2362 +1,2367 @@
1/* $NetBSD: puffs_vnops.c,v 1.162 2011/11/18 21:18:50 christos Exp $ */ 1/* $NetBSD: puffs_vnops.c,v 1.163 2012/01/17 09:30:16 martin 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
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.162 2011/11/18 21:18:50 christos Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.163 2012/01/17 09:30:16 martin 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>
47#include <fs/puffs/puffs_sys.h> 47#include <fs/puffs/puffs_sys.h>
48 48
49#include <miscfs/fifofs/fifo.h> 49#include <miscfs/fifofs/fifo.h>
50#include <miscfs/genfs/genfs.h> 50#include <miscfs/genfs/genfs.h>
51#include <miscfs/specfs/specdev.h> 51#include <miscfs/specfs/specdev.h>
52 52
53int puffs_vnop_lookup(void *); 53int puffs_vnop_lookup(void *);
54int puffs_vnop_create(void *); 54int puffs_vnop_create(void *);
55int puffs_vnop_access(void *); 55int puffs_vnop_access(void *);
56int puffs_vnop_mknod(void *); 56int puffs_vnop_mknod(void *);
57int puffs_vnop_open(void *); 57int puffs_vnop_open(void *);
58int puffs_vnop_close(void *); 58int puffs_vnop_close(void *);
59int puffs_vnop_getattr(void *); 59int puffs_vnop_getattr(void *);
60int puffs_vnop_setattr(void *); 60int puffs_vnop_setattr(void *);
61int puffs_vnop_reclaim(void *); 61int puffs_vnop_reclaim(void *);
62int puffs_vnop_readdir(void *); 62int puffs_vnop_readdir(void *);
63int puffs_vnop_poll(void *); 63int puffs_vnop_poll(void *);
64int puffs_vnop_fsync(void *); 64int puffs_vnop_fsync(void *);
65int puffs_vnop_seek(void *); 65int puffs_vnop_seek(void *);
66int puffs_vnop_remove(void *); 66int puffs_vnop_remove(void *);
67int puffs_vnop_mkdir(void *); 67int puffs_vnop_mkdir(void *);
68int puffs_vnop_rmdir(void *); 68int puffs_vnop_rmdir(void *);
69int puffs_vnop_link(void *); 69int puffs_vnop_link(void *);
70int puffs_vnop_readlink(void *); 70int puffs_vnop_readlink(void *);
71int puffs_vnop_symlink(void *); 71int puffs_vnop_symlink(void *);
72int puffs_vnop_rename(void *); 72int puffs_vnop_rename(void *);
73int puffs_vnop_read(void *); 73int puffs_vnop_read(void *);
74int puffs_vnop_write(void *); 74int puffs_vnop_write(void *);
75int puffs_vnop_fcntl(void *); 75int puffs_vnop_fcntl(void *);
76int puffs_vnop_ioctl(void *); 76int puffs_vnop_ioctl(void *);
77int puffs_vnop_inactive(void *); 77int puffs_vnop_inactive(void *);
78int puffs_vnop_print(void *); 78int puffs_vnop_print(void *);
79int puffs_vnop_pathconf(void *); 79int puffs_vnop_pathconf(void *);
80int puffs_vnop_advlock(void *); 80int puffs_vnop_advlock(void *);
81int puffs_vnop_strategy(void *); 81int puffs_vnop_strategy(void *);
82int puffs_vnop_bmap(void *); 82int puffs_vnop_bmap(void *);
83int puffs_vnop_mmap(void *); 83int puffs_vnop_mmap(void *);
84int puffs_vnop_getpages(void *); 84int puffs_vnop_getpages(void *);
85int puffs_vnop_abortop(void *); 85int puffs_vnop_abortop(void *);
86int puffs_vnop_getextattr(void *); 86int puffs_vnop_getextattr(void *);
87int puffs_vnop_setextattr(void *); 87int puffs_vnop_setextattr(void *);
88int puffs_vnop_listextattr(void *); 88int puffs_vnop_listextattr(void *);
89int puffs_vnop_deleteextattr(void *); 89int puffs_vnop_deleteextattr(void *);
90 90
91int puffs_vnop_spec_read(void *); 91int puffs_vnop_spec_read(void *);
92int puffs_vnop_spec_write(void *); 92int puffs_vnop_spec_write(void *);
93int puffs_vnop_fifo_read(void *); 93int puffs_vnop_fifo_read(void *);
94int puffs_vnop_fifo_write(void *); 94int puffs_vnop_fifo_write(void *);
95 95
96int puffs_vnop_checkop(void *); 96int puffs_vnop_checkop(void *);
97 97
98#define puffs_vnop_lock genfs_lock 98#define puffs_vnop_lock genfs_lock
99#define puffs_vnop_unlock genfs_unlock 99#define puffs_vnop_unlock genfs_unlock
100#define puffs_vnop_islocked genfs_islocked 100#define puffs_vnop_islocked genfs_islocked
101 101
102int (**puffs_vnodeop_p)(void *); 102int (**puffs_vnodeop_p)(void *);
103const struct vnodeopv_entry_desc puffs_vnodeop_entries[] = { 103const struct vnodeopv_entry_desc puffs_vnodeop_entries[] = {
104 { &vop_default_desc, vn_default_error }, 104 { &vop_default_desc, vn_default_error },
105 { &vop_lookup_desc, puffs_vnop_lookup }, /* REAL lookup */ 105 { &vop_lookup_desc, puffs_vnop_lookup }, /* REAL lookup */
106 { &vop_create_desc, puffs_vnop_checkop }, /* create */ 106 { &vop_create_desc, puffs_vnop_checkop }, /* create */
107 { &vop_mknod_desc, puffs_vnop_checkop }, /* mknod */ 107 { &vop_mknod_desc, puffs_vnop_checkop }, /* mknod */
108 { &vop_open_desc, puffs_vnop_open }, /* REAL open */ 108 { &vop_open_desc, puffs_vnop_open }, /* REAL open */
109 { &vop_close_desc, puffs_vnop_checkop }, /* close */ 109 { &vop_close_desc, puffs_vnop_checkop }, /* close */
110 { &vop_access_desc, puffs_vnop_access }, /* REAL access */ 110 { &vop_access_desc, puffs_vnop_access }, /* REAL access */
111 { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */ 111 { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
112 { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */ 112 { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
113 { &vop_read_desc, puffs_vnop_checkop }, /* read */ 113 { &vop_read_desc, puffs_vnop_checkop }, /* read */
114 { &vop_write_desc, puffs_vnop_checkop }, /* write */ 114 { &vop_write_desc, puffs_vnop_checkop }, /* write */
115 { &vop_fsync_desc, puffs_vnop_fsync }, /* REAL fsync */ 115 { &vop_fsync_desc, puffs_vnop_fsync }, /* REAL fsync */
116 { &vop_seek_desc, puffs_vnop_checkop }, /* seek */ 116 { &vop_seek_desc, puffs_vnop_checkop }, /* seek */
117 { &vop_remove_desc, puffs_vnop_checkop }, /* remove */ 117 { &vop_remove_desc, puffs_vnop_checkop }, /* remove */
118 { &vop_link_desc, puffs_vnop_checkop }, /* link */ 118 { &vop_link_desc, puffs_vnop_checkop }, /* link */
119 { &vop_rename_desc, puffs_vnop_checkop }, /* rename */ 119 { &vop_rename_desc, puffs_vnop_checkop }, /* rename */
120 { &vop_mkdir_desc, puffs_vnop_checkop }, /* mkdir */ 120 { &vop_mkdir_desc, puffs_vnop_checkop }, /* mkdir */
121 { &vop_rmdir_desc, puffs_vnop_checkop }, /* rmdir */ 121 { &vop_rmdir_desc, puffs_vnop_checkop }, /* rmdir */
122 { &vop_symlink_desc, puffs_vnop_checkop }, /* symlink */ 122 { &vop_symlink_desc, puffs_vnop_checkop }, /* symlink */
123 { &vop_readdir_desc, puffs_vnop_checkop }, /* readdir */ 123 { &vop_readdir_desc, puffs_vnop_checkop }, /* readdir */
124 { &vop_readlink_desc, puffs_vnop_checkop }, /* readlink */ 124 { &vop_readlink_desc, puffs_vnop_checkop }, /* readlink */
125 { &vop_getpages_desc, puffs_vnop_checkop }, /* getpages */ 125 { &vop_getpages_desc, puffs_vnop_checkop }, /* getpages */
126 { &vop_putpages_desc, genfs_putpages }, /* REAL putpages */ 126 { &vop_putpages_desc, genfs_putpages }, /* REAL putpages */
127 { &vop_pathconf_desc, puffs_vnop_checkop }, /* pathconf */ 127 { &vop_pathconf_desc, puffs_vnop_checkop }, /* pathconf */
128 { &vop_advlock_desc, puffs_vnop_advlock }, /* advlock */ 128 { &vop_advlock_desc, puffs_vnop_advlock }, /* advlock */
129 { &vop_strategy_desc, puffs_vnop_strategy }, /* REAL strategy */ 129 { &vop_strategy_desc, puffs_vnop_strategy }, /* REAL strategy */
130 { &vop_revoke_desc, genfs_revoke }, /* REAL revoke */ 130 { &vop_revoke_desc, genfs_revoke }, /* REAL revoke */
131 { &vop_abortop_desc, puffs_vnop_abortop }, /* REAL abortop */ 131 { &vop_abortop_desc, puffs_vnop_abortop }, /* REAL abortop */
132 { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */ 132 { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */
133 { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */ 133 { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */
134 { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */ 134 { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */
135 { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */ 135 { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */
136 { &vop_bmap_desc, puffs_vnop_bmap }, /* REAL bmap */ 136 { &vop_bmap_desc, puffs_vnop_bmap }, /* REAL bmap */
137 { &vop_print_desc, puffs_vnop_print }, /* REAL print */ 137 { &vop_print_desc, puffs_vnop_print }, /* REAL print */
138 { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */ 138 { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */
139 { &vop_bwrite_desc, genfs_nullop }, /* REAL bwrite */ 139 { &vop_bwrite_desc, genfs_nullop }, /* REAL bwrite */
140 { &vop_mmap_desc, puffs_vnop_mmap }, /* REAL mmap */ 140 { &vop_mmap_desc, puffs_vnop_mmap }, /* REAL mmap */
141 { &vop_poll_desc, puffs_vnop_poll }, /* REAL poll */ 141 { &vop_poll_desc, puffs_vnop_poll }, /* REAL poll */
142 { &vop_getextattr_desc, puffs_vnop_getextattr }, /* getextattr */ 142 { &vop_getextattr_desc, puffs_vnop_getextattr }, /* getextattr */
143 { &vop_setextattr_desc, puffs_vnop_setextattr }, /* setextattr */ 143 { &vop_setextattr_desc, puffs_vnop_setextattr }, /* setextattr */
144 { &vop_listextattr_desc, puffs_vnop_listextattr }, /* listextattr */ 144 { &vop_listextattr_desc, puffs_vnop_listextattr }, /* listextattr */
145 { &vop_deleteextattr_desc, puffs_vnop_deleteextattr },/* deleteextattr */ 145 { &vop_deleteextattr_desc, puffs_vnop_deleteextattr },/* deleteextattr */
146#if 0 146#if 0
147 { &vop_openextattr_desc, puffs_vnop_checkop }, /* openextattr */ 147 { &vop_openextattr_desc, puffs_vnop_checkop }, /* openextattr */
148 { &vop_closeextattr_desc, puffs_vnop_checkop }, /* closeextattr */ 148 { &vop_closeextattr_desc, puffs_vnop_checkop }, /* closeextattr */
149#endif 149#endif
150 { &vop_kqfilter_desc, genfs_eopnotsupp }, /* kqfilter XXX */ 150 { &vop_kqfilter_desc, genfs_eopnotsupp }, /* kqfilter XXX */
151 { NULL, NULL } 151 { NULL, NULL }
152}; 152};
153const struct vnodeopv_desc puffs_vnodeop_opv_desc = 153const struct vnodeopv_desc puffs_vnodeop_opv_desc =
154 { &puffs_vnodeop_p, puffs_vnodeop_entries }; 154 { &puffs_vnodeop_p, puffs_vnodeop_entries };
155 155
156 156
157int (**puffs_specop_p)(void *); 157int (**puffs_specop_p)(void *);
158const struct vnodeopv_entry_desc puffs_specop_entries[] = { 158const struct vnodeopv_entry_desc puffs_specop_entries[] = {
159 { &vop_default_desc, vn_default_error }, 159 { &vop_default_desc, vn_default_error },
160 { &vop_lookup_desc, spec_lookup }, /* lookup, ENOTDIR */ 160 { &vop_lookup_desc, spec_lookup }, /* lookup, ENOTDIR */
161 { &vop_create_desc, spec_create }, /* genfs_badop */ 161 { &vop_create_desc, spec_create }, /* genfs_badop */
162 { &vop_mknod_desc, spec_mknod }, /* genfs_badop */ 162 { &vop_mknod_desc, spec_mknod }, /* genfs_badop */
163 { &vop_open_desc, spec_open }, /* spec_open */ 163 { &vop_open_desc, spec_open }, /* spec_open */
164 { &vop_close_desc, spec_close }, /* spec_close */ 164 { &vop_close_desc, spec_close }, /* spec_close */
165 { &vop_access_desc, puffs_vnop_checkop }, /* access */ 165 { &vop_access_desc, puffs_vnop_checkop }, /* access */
166 { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */ 166 { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
167 { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */ 167 { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
168 { &vop_read_desc, puffs_vnop_spec_read }, /* update, read */ 168 { &vop_read_desc, puffs_vnop_spec_read }, /* update, read */
169 { &vop_write_desc, puffs_vnop_spec_write }, /* update, write */ 169 { &vop_write_desc, puffs_vnop_spec_write }, /* update, write */
170 { &vop_ioctl_desc, spec_ioctl }, /* spec_ioctl */ 170 { &vop_ioctl_desc, spec_ioctl }, /* spec_ioctl */
171 { &vop_fcntl_desc, genfs_fcntl }, /* dummy */ 171 { &vop_fcntl_desc, genfs_fcntl }, /* dummy */
172 { &vop_poll_desc, spec_poll }, /* spec_poll */ 172 { &vop_poll_desc, spec_poll }, /* spec_poll */
173 { &vop_kqfilter_desc, spec_kqfilter }, /* spec_kqfilter */ 173 { &vop_kqfilter_desc, spec_kqfilter }, /* spec_kqfilter */
174 { &vop_revoke_desc, spec_revoke }, /* genfs_revoke */ 174 { &vop_revoke_desc, spec_revoke }, /* genfs_revoke */
175 { &vop_mmap_desc, spec_mmap }, /* spec_mmap */ 175 { &vop_mmap_desc, spec_mmap }, /* spec_mmap */
176 { &vop_fsync_desc, spec_fsync }, /* vflushbuf */ 176 { &vop_fsync_desc, spec_fsync }, /* vflushbuf */
177 { &vop_seek_desc, spec_seek }, /* genfs_nullop */ 177 { &vop_seek_desc, spec_seek }, /* genfs_nullop */
178 { &vop_remove_desc, spec_remove }, /* genfs_badop */ 178 { &vop_remove_desc, spec_remove }, /* genfs_badop */
179 { &vop_link_desc, spec_link }, /* genfs_badop */ 179 { &vop_link_desc, spec_link }, /* genfs_badop */
180 { &vop_rename_desc, spec_rename }, /* genfs_badop */ 180 { &vop_rename_desc, spec_rename }, /* genfs_badop */
181 { &vop_mkdir_desc, spec_mkdir }, /* genfs_badop */ 181 { &vop_mkdir_desc, spec_mkdir }, /* genfs_badop */
182 { &vop_rmdir_desc, spec_rmdir }, /* genfs_badop */ 182 { &vop_rmdir_desc, spec_rmdir }, /* genfs_badop */
183 { &vop_symlink_desc, spec_symlink }, /* genfs_badop */ 183 { &vop_symlink_desc, spec_symlink }, /* genfs_badop */
184 { &vop_readdir_desc, spec_readdir }, /* genfs_badop */ 184 { &vop_readdir_desc, spec_readdir }, /* genfs_badop */
185 { &vop_readlink_desc, spec_readlink }, /* genfs_badop */ 185 { &vop_readlink_desc, spec_readlink }, /* genfs_badop */
186 { &vop_abortop_desc, spec_abortop }, /* genfs_badop */ 186 { &vop_abortop_desc, spec_abortop }, /* genfs_badop */
187 { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */ 187 { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */
188 { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */ 188 { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */
189 { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */ 189 { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */
190 { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */ 190 { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */
191 { &vop_bmap_desc, spec_bmap }, /* dummy */ 191 { &vop_bmap_desc, spec_bmap }, /* dummy */
192 { &vop_strategy_desc, spec_strategy }, /* dev strategy */ 192 { &vop_strategy_desc, spec_strategy }, /* dev strategy */
193 { &vop_print_desc, puffs_vnop_print }, /* REAL print */ 193 { &vop_print_desc, puffs_vnop_print }, /* REAL print */
194 { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */ 194 { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */
195 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 195 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
196 { &vop_advlock_desc, spec_advlock }, /* lf_advlock */ 196 { &vop_advlock_desc, spec_advlock }, /* lf_advlock */
197 { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 197 { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
198 { &vop_getpages_desc, spec_getpages }, /* genfs_getpages */ 198 { &vop_getpages_desc, spec_getpages }, /* genfs_getpages */
199 { &vop_putpages_desc, spec_putpages }, /* genfs_putpages */ 199 { &vop_putpages_desc, spec_putpages }, /* genfs_putpages */
200 { &vop_getextattr_desc, puffs_vnop_checkop }, /* getextattr */ 200 { &vop_getextattr_desc, puffs_vnop_checkop }, /* getextattr */
201 { &vop_setextattr_desc, puffs_vnop_checkop }, /* setextattr */ 201 { &vop_setextattr_desc, puffs_vnop_checkop }, /* setextattr */
202 { &vop_listextattr_desc, puffs_vnop_checkop }, /* listextattr */ 202 { &vop_listextattr_desc, puffs_vnop_checkop }, /* listextattr */
203 { &vop_deleteextattr_desc, puffs_vnop_checkop },/* deleteextattr */ 203 { &vop_deleteextattr_desc, puffs_vnop_checkop },/* deleteextattr */
204#if 0 204#if 0
205 { &vop_openextattr_desc, _openextattr }, /* openextattr */ 205 { &vop_openextattr_desc, _openextattr }, /* openextattr */
206 { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */ 206 { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */
207#endif 207#endif
208 { NULL, NULL } 208 { NULL, NULL }
209}; 209};
210const struct vnodeopv_desc puffs_specop_opv_desc = 210const struct vnodeopv_desc puffs_specop_opv_desc =
211 { &puffs_specop_p, puffs_specop_entries }; 211 { &puffs_specop_p, puffs_specop_entries };
212 212
213 213
214int (**puffs_fifoop_p)(void *); 214int (**puffs_fifoop_p)(void *);
215const struct vnodeopv_entry_desc puffs_fifoop_entries[] = { 215const struct vnodeopv_entry_desc puffs_fifoop_entries[] = {
216 { &vop_default_desc, vn_default_error }, 216 { &vop_default_desc, vn_default_error },
217 { &vop_lookup_desc, vn_fifo_bypass }, /* lookup, ENOTDIR */ 217 { &vop_lookup_desc, vn_fifo_bypass }, /* lookup, ENOTDIR */
218 { &vop_create_desc, vn_fifo_bypass }, /* genfs_badop */ 218 { &vop_create_desc, vn_fifo_bypass }, /* genfs_badop */
219 { &vop_mknod_desc, vn_fifo_bypass }, /* genfs_badop */ 219 { &vop_mknod_desc, vn_fifo_bypass }, /* genfs_badop */
220 { &vop_open_desc, vn_fifo_bypass }, /* open */ 220 { &vop_open_desc, vn_fifo_bypass }, /* open */
221 { &vop_close_desc, vn_fifo_bypass }, /* close */ 221 { &vop_close_desc, vn_fifo_bypass }, /* close */
222 { &vop_access_desc, puffs_vnop_checkop }, /* access */ 222 { &vop_access_desc, puffs_vnop_checkop }, /* access */
223 { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */ 223 { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
224 { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */ 224 { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
225 { &vop_read_desc, puffs_vnop_fifo_read }, /* read, update */ 225 { &vop_read_desc, puffs_vnop_fifo_read }, /* read, update */
226 { &vop_write_desc, puffs_vnop_fifo_write }, /* write, update */ 226 { &vop_write_desc, puffs_vnop_fifo_write }, /* write, update */
227 { &vop_ioctl_desc, vn_fifo_bypass }, /* ioctl */ 227 { &vop_ioctl_desc, vn_fifo_bypass }, /* ioctl */
228 { &vop_fcntl_desc, genfs_fcntl }, /* dummy */ 228 { &vop_fcntl_desc, genfs_fcntl }, /* dummy */
229 { &vop_poll_desc, vn_fifo_bypass }, /* poll */ 229 { &vop_poll_desc, vn_fifo_bypass }, /* poll */
230 { &vop_kqfilter_desc, vn_fifo_bypass }, /* kqfilter */ 230 { &vop_kqfilter_desc, vn_fifo_bypass }, /* kqfilter */
231 { &vop_revoke_desc, vn_fifo_bypass }, /* genfs_revoke */ 231 { &vop_revoke_desc, vn_fifo_bypass }, /* genfs_revoke */
232 { &vop_mmap_desc, vn_fifo_bypass }, /* genfs_badop */ 232 { &vop_mmap_desc, vn_fifo_bypass }, /* genfs_badop */
233 { &vop_fsync_desc, vn_fifo_bypass }, /* genfs_nullop*/ 233 { &vop_fsync_desc, vn_fifo_bypass }, /* genfs_nullop*/
234 { &vop_seek_desc, vn_fifo_bypass }, /* genfs_badop */ 234 { &vop_seek_desc, vn_fifo_bypass }, /* genfs_badop */
235 { &vop_remove_desc, vn_fifo_bypass }, /* genfs_badop */ 235 { &vop_remove_desc, vn_fifo_bypass }, /* genfs_badop */
236 { &vop_link_desc, vn_fifo_bypass }, /* genfs_badop */ 236 { &vop_link_desc, vn_fifo_bypass }, /* genfs_badop */
237 { &vop_rename_desc, vn_fifo_bypass }, /* genfs_badop */ 237 { &vop_rename_desc, vn_fifo_bypass }, /* genfs_badop */
238 { &vop_mkdir_desc, vn_fifo_bypass }, /* genfs_badop */ 238 { &vop_mkdir_desc, vn_fifo_bypass }, /* genfs_badop */
239 { &vop_rmdir_desc, vn_fifo_bypass }, /* genfs_badop */ 239 { &vop_rmdir_desc, vn_fifo_bypass }, /* genfs_badop */
240 { &vop_symlink_desc, vn_fifo_bypass }, /* genfs_badop */ 240 { &vop_symlink_desc, vn_fifo_bypass }, /* genfs_badop */
241 { &vop_readdir_desc, vn_fifo_bypass }, /* genfs_badop */ 241 { &vop_readdir_desc, vn_fifo_bypass }, /* genfs_badop */
242 { &vop_readlink_desc, vn_fifo_bypass }, /* genfs_badop */ 242 { &vop_readlink_desc, vn_fifo_bypass }, /* genfs_badop */
243 { &vop_abortop_desc, vn_fifo_bypass }, /* genfs_badop */ 243 { &vop_abortop_desc, vn_fifo_bypass }, /* genfs_badop */
244 { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */ 244 { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */
245 { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */ 245 { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */
246 { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */ 246 { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */
247 { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */ 247 { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */
248 { &vop_bmap_desc, vn_fifo_bypass }, /* dummy */ 248 { &vop_bmap_desc, vn_fifo_bypass }, /* dummy */
249 { &vop_strategy_desc, vn_fifo_bypass }, /* genfs_badop */ 249 { &vop_strategy_desc, vn_fifo_bypass }, /* genfs_badop */
250 { &vop_print_desc, puffs_vnop_print }, /* REAL print */ 250 { &vop_print_desc, puffs_vnop_print }, /* REAL print */
251 { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */ 251 { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */
252 { &vop_pathconf_desc, vn_fifo_bypass }, /* pathconf */ 252 { &vop_pathconf_desc, vn_fifo_bypass }, /* pathconf */
253 { &vop_advlock_desc, vn_fifo_bypass }, /* genfs_einval */ 253 { &vop_advlock_desc, vn_fifo_bypass }, /* genfs_einval */
254 { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 254 { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
255 { &vop_putpages_desc, vn_fifo_bypass }, /* genfs_null_putpages*/ 255 { &vop_putpages_desc, vn_fifo_bypass }, /* genfs_null_putpages*/
256#if 0 256#if 0
257 { &vop_openextattr_desc, _openextattr }, /* openextattr */ 257 { &vop_openextattr_desc, _openextattr }, /* openextattr */
258 { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */ 258 { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */
259#endif 259#endif
260 { &vop_getextattr_desc, puffs_vnop_checkop }, /* getextattr */ 260 { &vop_getextattr_desc, puffs_vnop_checkop }, /* getextattr */
261 { &vop_setextattr_desc, puffs_vnop_checkop }, /* setextattr */ 261 { &vop_setextattr_desc, puffs_vnop_checkop }, /* setextattr */
262 { &vop_listextattr_desc, puffs_vnop_checkop }, /* listextattr */ 262 { &vop_listextattr_desc, puffs_vnop_checkop }, /* listextattr */
263 { &vop_deleteextattr_desc, puffs_vnop_checkop }, /* deleteextattr */ 263 { &vop_deleteextattr_desc, puffs_vnop_checkop }, /* deleteextattr */
264 { NULL, NULL } 264 { NULL, NULL }
265}; 265};
266const struct vnodeopv_desc puffs_fifoop_opv_desc = 266const struct vnodeopv_desc puffs_fifoop_opv_desc =
267 { &puffs_fifoop_p, puffs_fifoop_entries }; 267 { &puffs_fifoop_p, puffs_fifoop_entries };
268 268
269 269
270/* "real" vnode operations */ 270/* "real" vnode operations */
271int (**puffs_msgop_p)(void *); 271int (**puffs_msgop_p)(void *);
272const struct vnodeopv_entry_desc puffs_msgop_entries[] = { 272const struct vnodeopv_entry_desc puffs_msgop_entries[] = {
273 { &vop_default_desc, vn_default_error }, 273 { &vop_default_desc, vn_default_error },
274 { &vop_create_desc, puffs_vnop_create }, /* create */ 274 { &vop_create_desc, puffs_vnop_create }, /* create */
275 { &vop_mknod_desc, puffs_vnop_mknod }, /* mknod */ 275 { &vop_mknod_desc, puffs_vnop_mknod }, /* mknod */
276 { &vop_open_desc, puffs_vnop_open }, /* open */ 276 { &vop_open_desc, puffs_vnop_open }, /* open */
277 { &vop_close_desc, puffs_vnop_close }, /* close */ 277 { &vop_close_desc, puffs_vnop_close }, /* close */
278 { &vop_access_desc, puffs_vnop_access }, /* access */ 278 { &vop_access_desc, puffs_vnop_access }, /* access */
279 { &vop_getattr_desc, puffs_vnop_getattr }, /* getattr */ 279 { &vop_getattr_desc, puffs_vnop_getattr }, /* getattr */
280 { &vop_setattr_desc, puffs_vnop_setattr }, /* setattr */ 280 { &vop_setattr_desc, puffs_vnop_setattr }, /* setattr */
281 { &vop_read_desc, puffs_vnop_read }, /* read */ 281 { &vop_read_desc, puffs_vnop_read }, /* read */
282 { &vop_write_desc, puffs_vnop_write }, /* write */ 282 { &vop_write_desc, puffs_vnop_write }, /* write */
283 { &vop_seek_desc, puffs_vnop_seek }, /* seek */ 283 { &vop_seek_desc, puffs_vnop_seek }, /* seek */
284 { &vop_remove_desc, puffs_vnop_remove }, /* remove */ 284 { &vop_remove_desc, puffs_vnop_remove }, /* remove */
285 { &vop_link_desc, puffs_vnop_link }, /* link */ 285 { &vop_link_desc, puffs_vnop_link }, /* link */
286 { &vop_rename_desc, puffs_vnop_rename }, /* rename */ 286 { &vop_rename_desc, puffs_vnop_rename }, /* rename */
287 { &vop_mkdir_desc, puffs_vnop_mkdir }, /* mkdir */ 287 { &vop_mkdir_desc, puffs_vnop_mkdir }, /* mkdir */
288 { &vop_rmdir_desc, puffs_vnop_rmdir }, /* rmdir */ 288 { &vop_rmdir_desc, puffs_vnop_rmdir }, /* rmdir */
289 { &vop_symlink_desc, puffs_vnop_symlink }, /* symlink */ 289 { &vop_symlink_desc, puffs_vnop_symlink }, /* symlink */
290 { &vop_readdir_desc, puffs_vnop_readdir }, /* readdir */ 290 { &vop_readdir_desc, puffs_vnop_readdir }, /* readdir */
291 { &vop_readlink_desc, puffs_vnop_readlink }, /* readlink */ 291 { &vop_readlink_desc, puffs_vnop_readlink }, /* readlink */
292 { &vop_print_desc, puffs_vnop_print }, /* print */ 292 { &vop_print_desc, puffs_vnop_print }, /* print */
293 { &vop_islocked_desc, puffs_vnop_islocked }, /* islocked */ 293 { &vop_islocked_desc, puffs_vnop_islocked }, /* islocked */
294 { &vop_pathconf_desc, puffs_vnop_pathconf }, /* pathconf */ 294 { &vop_pathconf_desc, puffs_vnop_pathconf }, /* pathconf */
295 { &vop_getpages_desc, puffs_vnop_getpages }, /* getpages */ 295 { &vop_getpages_desc, puffs_vnop_getpages }, /* getpages */
296 { NULL, NULL } 296 { NULL, NULL }
297}; 297};
298const struct vnodeopv_desc puffs_msgop_opv_desc = 298const struct vnodeopv_desc puffs_msgop_opv_desc =
299 { &puffs_msgop_p, puffs_msgop_entries }; 299 { &puffs_msgop_p, puffs_msgop_entries };
300 300
301 301
302#define ERROUT(err) \ 302#define ERROUT(err) \
303do { \ 303do { \
304 error = err; \ 304 error = err; \
305 goto out; \ 305 goto out; \
306} while (/*CONSTCOND*/0) 306} while (/*CONSTCOND*/0)
307 307
308/* 308/*
309 * This is a generic vnode operation handler. It checks if the necessary 309 * This is a generic vnode operation handler. It checks if the necessary
310 * operations for the called vnode operation are implemented by userspace 310 * operations for the called vnode operation are implemented by userspace
311 * and either returns a dummy return value or proceeds to call the real 311 * and either returns a dummy return value or proceeds to call the real
312 * vnode operation from puffs_msgop_v. 312 * vnode operation from puffs_msgop_v.
313 * 313 *
314 * XXX: this should described elsewhere and autogenerated, the complexity 314 * XXX: this should described elsewhere and autogenerated, the complexity
315 * of the vnode operations vectors and their interrelationships is also 315 * of the vnode operations vectors and their interrelationships is also
316 * getting a bit out of hand. Another problem is that we need this same 316 * getting a bit out of hand. Another problem is that we need this same
317 * information in the fs server code, so keeping the two in sync manually 317 * information in the fs server code, so keeping the two in sync manually
318 * is not a viable (long term) plan. 318 * is not a viable (long term) plan.
319 */ 319 */
320 320
321/* not supported, handle locking protocol */ 321/* not supported, handle locking protocol */
322#define CHECKOP_NOTSUPP(op) \ 322#define CHECKOP_NOTSUPP(op) \
323case VOP_##op##_DESCOFFSET: \ 323case VOP_##op##_DESCOFFSET: \
324 if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0) \ 324 if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0) \
325 return genfs_eopnotsupp(v); \ 325 return genfs_eopnotsupp(v); \
326 break 326 break
327 327
328/* always succeed, no locking */ 328/* always succeed, no locking */
329#define CHECKOP_SUCCESS(op) \ 329#define CHECKOP_SUCCESS(op) \
330case VOP_##op##_DESCOFFSET: \ 330case VOP_##op##_DESCOFFSET: \
331 if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0) \ 331 if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0) \
332 return 0; \ 332 return 0; \
333 break 333 break
334 334
335int 335int
336puffs_vnop_checkop(void *v) 336puffs_vnop_checkop(void *v)
337{ 337{
338 struct vop_generic_args /* { 338 struct vop_generic_args /* {
339 struct vnodeop_desc *a_desc; 339 struct vnodeop_desc *a_desc;
340 spooky mystery contents; 340 spooky mystery contents;
341 } */ *ap = v; 341 } */ *ap = v;
342 struct vnodeop_desc *desc = ap->a_desc; 342 struct vnodeop_desc *desc = ap->a_desc;
343 struct puffs_mount *pmp; 343 struct puffs_mount *pmp;
344 struct vnode *vp; 344 struct vnode *vp;
345 int offset, rv; 345 int offset, rv;
346 346
347 offset = ap->a_desc->vdesc_vp_offsets[0]; 347 offset = ap->a_desc->vdesc_vp_offsets[0];
348#ifdef DIAGNOSTIC 348#ifdef DIAGNOSTIC
349 if (offset == VDESC_NO_OFFSET) 349 if (offset == VDESC_NO_OFFSET)
350 panic("puffs_checkop: no vnode, why did you call me?"); 350 panic("puffs_checkop: no vnode, why did you call me?");
351#endif 351#endif
352 vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap); 352 vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap);
353 pmp = MPTOPUFFSMP(vp->v_mount); 353 pmp = MPTOPUFFSMP(vp->v_mount);
354 354
355 DPRINTF_VERBOSE(("checkop call %s (%d), vp %p\n", 355 DPRINTF_VERBOSE(("checkop call %s (%d), vp %p\n",
356 ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset, vp)); 356 ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset, vp));
357 357
358 if (!ALLOPS(pmp)) { 358 if (!ALLOPS(pmp)) {
359 switch (desc->vdesc_offset) { 359 switch (desc->vdesc_offset) {
360 CHECKOP_NOTSUPP(CREATE); 360 CHECKOP_NOTSUPP(CREATE);
361 CHECKOP_NOTSUPP(MKNOD); 361 CHECKOP_NOTSUPP(MKNOD);
362 CHECKOP_NOTSUPP(GETATTR); 362 CHECKOP_NOTSUPP(GETATTR);
363 CHECKOP_NOTSUPP(SETATTR); 363 CHECKOP_NOTSUPP(SETATTR);
364 CHECKOP_NOTSUPP(READ); 364 CHECKOP_NOTSUPP(READ);
365 CHECKOP_NOTSUPP(WRITE); 365 CHECKOP_NOTSUPP(WRITE);
366 CHECKOP_NOTSUPP(FCNTL); 366 CHECKOP_NOTSUPP(FCNTL);
367 CHECKOP_NOTSUPP(IOCTL); 367 CHECKOP_NOTSUPP(IOCTL);
368 CHECKOP_NOTSUPP(REMOVE); 368 CHECKOP_NOTSUPP(REMOVE);
369 CHECKOP_NOTSUPP(LINK); 369 CHECKOP_NOTSUPP(LINK);
370 CHECKOP_NOTSUPP(RENAME); 370 CHECKOP_NOTSUPP(RENAME);
371 CHECKOP_NOTSUPP(MKDIR); 371 CHECKOP_NOTSUPP(MKDIR);
372 CHECKOP_NOTSUPP(RMDIR); 372 CHECKOP_NOTSUPP(RMDIR);
373 CHECKOP_NOTSUPP(SYMLINK); 373 CHECKOP_NOTSUPP(SYMLINK);
374 CHECKOP_NOTSUPP(READDIR); 374 CHECKOP_NOTSUPP(READDIR);
375 CHECKOP_NOTSUPP(READLINK); 375 CHECKOP_NOTSUPP(READLINK);
376 CHECKOP_NOTSUPP(PRINT); 376 CHECKOP_NOTSUPP(PRINT);
377 CHECKOP_NOTSUPP(PATHCONF); 377 CHECKOP_NOTSUPP(PATHCONF);
378 CHECKOP_NOTSUPP(GETEXTATTR); 378 CHECKOP_NOTSUPP(GETEXTATTR);
379 CHECKOP_NOTSUPP(SETEXTATTR); 379 CHECKOP_NOTSUPP(SETEXTATTR);
380 CHECKOP_NOTSUPP(LISTEXTATTR); 380 CHECKOP_NOTSUPP(LISTEXTATTR);
381 CHECKOP_NOTSUPP(DELETEEXTATTR); 381 CHECKOP_NOTSUPP(DELETEEXTATTR);
382 382
383 CHECKOP_SUCCESS(ACCESS); 383 CHECKOP_SUCCESS(ACCESS);
384 CHECKOP_SUCCESS(CLOSE); 384 CHECKOP_SUCCESS(CLOSE);
385 CHECKOP_SUCCESS(SEEK); 385 CHECKOP_SUCCESS(SEEK);
386 386
387 case VOP_GETPAGES_DESCOFFSET: 387 case VOP_GETPAGES_DESCOFFSET:
388 if (!EXISTSOP(pmp, READ)) 388 if (!EXISTSOP(pmp, READ))
389 return genfs_eopnotsupp(v); 389 return genfs_eopnotsupp(v);
390 break; 390 break;
391 391
392 default: 392 default:
393 panic("puffs_checkop: unhandled vnop %d", 393 panic("puffs_checkop: unhandled vnop %d",
394 desc->vdesc_offset); 394 desc->vdesc_offset);
395 } 395 }
396 } 396 }
397 397
398 rv = VOCALL(puffs_msgop_p, ap->a_desc->vdesc_offset, v); 398 rv = VOCALL(puffs_msgop_p, ap->a_desc->vdesc_offset, v);
399 399
400 DPRINTF_VERBOSE(("checkop return %s (%d), vp %p: %d\n", 400 DPRINTF_VERBOSE(("checkop return %s (%d), vp %p: %d\n",
401 ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset, vp, rv)); 401 ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset, vp, rv));
402 402
403 return rv; 403 return rv;
404} 404}
405 405
406static int callremove(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t, 406static int callremove(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t,
407 struct componentname *); 407 struct componentname *);
408static int callrmdir(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t, 408static int callrmdir(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t,
409 struct componentname *); 409 struct componentname *);
410static void callinactive(struct puffs_mount *, puffs_cookie_t, int); 410static void callinactive(struct puffs_mount *, puffs_cookie_t, int);
411static void callreclaim(struct puffs_mount *, puffs_cookie_t); 411static void callreclaim(struct puffs_mount *, puffs_cookie_t);
412static int flushvncache(struct vnode *, off_t, off_t, bool); 412static int flushvncache(struct vnode *, off_t, off_t, bool);
413 413
414 414
415#define PUFFS_ABORT_LOOKUP 1 415#define PUFFS_ABORT_LOOKUP 1
416#define PUFFS_ABORT_CREATE 2 416#define PUFFS_ABORT_CREATE 2
417#define PUFFS_ABORT_MKNOD 3 417#define PUFFS_ABORT_MKNOD 3
418#define PUFFS_ABORT_MKDIR 4 418#define PUFFS_ABORT_MKDIR 4
419#define PUFFS_ABORT_SYMLINK 5 419#define PUFFS_ABORT_SYMLINK 5
420 420
421/* 421/*
422 * Press the pani^Wabort button! Kernel resource allocation failed. 422 * Press the pani^Wabort button! Kernel resource allocation failed.
423 */ 423 */
424static void 424static void
425puffs_abortbutton(struct puffs_mount *pmp, int what, 425puffs_abortbutton(struct puffs_mount *pmp, int what,
426 puffs_cookie_t dck, puffs_cookie_t ck, struct componentname *cnp) 426 puffs_cookie_t dck, puffs_cookie_t ck, struct componentname *cnp)
427{ 427{
428 428
429 switch (what) { 429 switch (what) {
430 case PUFFS_ABORT_CREATE: 430 case PUFFS_ABORT_CREATE:
431 case PUFFS_ABORT_MKNOD: 431 case PUFFS_ABORT_MKNOD:
432 case PUFFS_ABORT_SYMLINK: 432 case PUFFS_ABORT_SYMLINK:
433 callremove(pmp, dck, ck, cnp); 433 callremove(pmp, dck, ck, cnp);
434 break; 434 break;
435 case PUFFS_ABORT_MKDIR: 435 case PUFFS_ABORT_MKDIR:
436 callrmdir(pmp, dck, ck, cnp); 436 callrmdir(pmp, dck, ck, cnp);
437 break; 437 break;
438 } 438 }
439 439
440 callinactive(pmp, ck, 0); 440 callinactive(pmp, ck, 0);
441 callreclaim(pmp, ck); 441 callreclaim(pmp, ck);
442} 442}
443 443
444/* 444/*
445 * Begin vnode operations. 445 * Begin vnode operations.
446 * 446 *
447 * A word from the keymaster about locks: generally we don't want 447 * A word from the keymaster about locks: generally we don't want
448 * to use the vnode locks at all: it creates an ugly dependency between 448 * to use the vnode locks at all: it creates an ugly dependency between
449 * the userlandia file server and the kernel. But we'll play along with 449 * the userlandia file server and the kernel. But we'll play along with
450 * the kernel vnode locks for now. However, even currently we attempt 450 * the kernel vnode locks for now. However, even currently we attempt
451 * to release locks as early as possible. This is possible for some 451 * to release locks as early as possible. This is possible for some
452 * operations which a) don't need a locked vnode after the userspace op 452 * operations which a) don't need a locked vnode after the userspace op
453 * and b) return with the vnode unlocked. Theoretically we could 453 * and b) return with the vnode unlocked. Theoretically we could
454 * unlock-do op-lock for others and order the graph in userspace, but I 454 * unlock-do op-lock for others and order the graph in userspace, but I
455 * don't want to think of the consequences for the time being. 455 * don't want to think of the consequences for the time being.
456 */ 456 */
457 457
458int 458int
459puffs_vnop_lookup(void *v) 459puffs_vnop_lookup(void *v)
460{ 460{
461 struct vop_lookup_args /* { 461 struct vop_lookup_args /* {
462 const struct vnodeop_desc *a_desc; 462 const struct vnodeop_desc *a_desc;
463 struct vnode *a_dvp; 463 struct vnode *a_dvp;
464 struct vnode **a_vpp; 464 struct vnode **a_vpp;
465 struct componentname *a_cnp; 465 struct componentname *a_cnp;
466 } */ *ap = v; 466 } */ *ap = v;
467 PUFFS_MSG_VARS(vn, lookup); 467 PUFFS_MSG_VARS(vn, lookup);
468 struct puffs_mount *pmp; 468 struct puffs_mount *pmp;
469 struct componentname *cnp; 469 struct componentname *cnp;
470 struct vnode *vp, *dvp; 470 struct vnode *vp, *dvp;
471 struct puffs_node *dpn; 471 struct puffs_node *dpn;
472 int isdot; 472 int isdot;
473 int error; 473 int error;
474 474
475 pmp = MPTOPUFFSMP(ap->a_dvp->v_mount); 475 pmp = MPTOPUFFSMP(ap->a_dvp->v_mount);
476 cnp = ap->a_cnp; 476 cnp = ap->a_cnp;
477 dvp = ap->a_dvp; 477 dvp = ap->a_dvp;
478 *ap->a_vpp = NULL; 478 *ap->a_vpp = NULL;
479 479
480 /* r/o fs? we check create later to handle EEXIST */ 480 /* r/o fs? we check create later to handle EEXIST */
481 if ((cnp->cn_flags & ISLASTCN) 481 if ((cnp->cn_flags & ISLASTCN)
482 && (dvp->v_mount->mnt_flag & MNT_RDONLY) 482 && (dvp->v_mount->mnt_flag & MNT_RDONLY)
483 && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 483 && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
484 return EROFS; 484 return EROFS;
485 485
486 isdot = cnp->cn_namelen == 1 && *cnp->cn_nameptr == '.'; 486 isdot = cnp->cn_namelen == 1 && *cnp->cn_nameptr == '.';
487 487
488 DPRINTF(("puffs_lookup: \"%s\", parent vnode %p, op: %x\n", 488 DPRINTF(("puffs_lookup: \"%s\", parent vnode %p, op: %x\n",
489 cnp->cn_nameptr, dvp, cnp->cn_nameiop)); 489 cnp->cn_nameptr, dvp, cnp->cn_nameiop));
490 490
491 /* 491 /*
492 * Check if someone fed it into the cache 492 * Check if someone fed it into the cache
493 */ 493 */
494 if (PUFFS_USE_NAMECACHE(pmp)) { 494 if (PUFFS_USE_NAMECACHE(pmp)) {
495 error = cache_lookup(dvp, ap->a_vpp, cnp); 495 error = cache_lookup(dvp, ap->a_vpp, cnp);
496 496
497 if (error >= 0) 497 if (error >= 0)
498 return error; 498 return error;
499 } 499 }
500 500
501 if (isdot) { 501 if (isdot) {
502 /* deal with rename lookup semantics */ 502 /* deal with rename lookup semantics */
503 if (cnp->cn_nameiop == RENAME && (cnp->cn_flags & ISLASTCN)) 503 if (cnp->cn_nameiop == RENAME && (cnp->cn_flags & ISLASTCN))
504 return EISDIR; 504 return EISDIR;
505 505
506 vp = ap->a_dvp; 506 vp = ap->a_dvp;
507 vref(vp); 507 vref(vp);
508 *ap->a_vpp = vp; 508 *ap->a_vpp = vp;
509 return 0; 509 return 0;
510 } 510 }
511 511
512 PUFFS_MSG_ALLOC(vn, lookup); 512 PUFFS_MSG_ALLOC(vn, lookup);
513 puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred, 513 puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred,
514 cnp, PUFFS_USE_FULLPNBUF(pmp)); 514 cnp, PUFFS_USE_FULLPNBUF(pmp));
515 515
516 if (cnp->cn_flags & ISDOTDOT) 516 if (cnp->cn_flags & ISDOTDOT)
517 VOP_UNLOCK(dvp); 517 VOP_UNLOCK(dvp);
518 518
519 puffs_msg_setinfo(park_lookup, PUFFSOP_VN, 519 puffs_msg_setinfo(park_lookup, PUFFSOP_VN,
520 PUFFS_VN_LOOKUP, VPTOPNC(dvp)); 520 PUFFS_VN_LOOKUP, VPTOPNC(dvp));
521 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_lookup, dvp->v_data, NULL, error); 521 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_lookup, dvp->v_data, NULL, error);
522 DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error)); 522 DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error));
523 523
524 /* 524 /*
525 * In case of error, there is no new vnode to play with, so be 525 * In case of error, there is no new vnode to play with, so be
526 * happy with the NULL value given to vpp in the beginning. 526 * happy with the NULL value given to vpp in the beginning.
527 * Also, check if this really was an error or the target was not 527 * Also, check if this really was an error or the target was not
528 * present. Either treat it as a non-error for CREATE/RENAME or 528 * present. Either treat it as a non-error for CREATE/RENAME or
529 * enter the component into the negative name cache (if desired). 529 * enter the component into the negative name cache (if desired).
530 */ 530 */
531 if (error) { 531 if (error) {
532 error = checkerr(pmp, error, __func__); 532 error = checkerr(pmp, error, __func__);
533 if (error == ENOENT) { 533 if (error == ENOENT) {
534 /* don't allow to create files on r/o fs */ 534 /* don't allow to create files on r/o fs */
535 if ((dvp->v_mount->mnt_flag & MNT_RDONLY) 535 if ((dvp->v_mount->mnt_flag & MNT_RDONLY)
536 && cnp->cn_nameiop == CREATE) { 536 && cnp->cn_nameiop == CREATE) {
537 error = EROFS; 537 error = EROFS;
538 538
539 /* adjust values if we are creating */ 539 /* adjust values if we are creating */
540 } else if ((cnp->cn_flags & ISLASTCN) 540 } else if ((cnp->cn_flags & ISLASTCN)
541 && (cnp->cn_nameiop == CREATE 541 && (cnp->cn_nameiop == CREATE
542 || cnp->cn_nameiop == RENAME)) { 542 || cnp->cn_nameiop == RENAME)) {
543 error = EJUSTRETURN; 543 error = EJUSTRETURN;
544 544
545 /* save negative cache entry */ 545 /* save negative cache entry */
546 } else { 546 } else {
547 if ((cnp->cn_flags & MAKEENTRY) 547 if ((cnp->cn_flags & MAKEENTRY)
548 && PUFFS_USE_NAMECACHE(pmp)) 548 && PUFFS_USE_NAMECACHE(pmp))
549 cache_enter(dvp, NULL, cnp); 549 cache_enter(dvp, NULL, cnp);
550 } 550 }
551 } 551 }
552 goto out; 552 goto out;
553 } 553 }
554 554
555 /* 555 /*
556 * Check that we don't get our parent node back, that would cause 556 * Check that we don't get our parent node back, that would cause
557 * a pretty obvious deadlock. 557 * a pretty obvious deadlock.
558 */ 558 */
559 dpn = dvp->v_data; 559 dpn = dvp->v_data;
560 if (lookup_msg->pvnr_newnode == dpn->pn_cookie) { 560 if (lookup_msg->pvnr_newnode == dpn->pn_cookie) {
561 puffs_senderr(pmp, PUFFS_ERR_LOOKUP, EINVAL, 561 puffs_senderr(pmp, PUFFS_ERR_LOOKUP, EINVAL,
562 "lookup produced parent cookie", lookup_msg->pvnr_newnode); 562 "lookup produced parent cookie", lookup_msg->pvnr_newnode);
563 error = EPROTO; 563 error = EPROTO;
564 goto out; 564 goto out;
565 } 565 }
566 566
567 error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, 1, 1, &vp); 567 error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, 1, 1, &vp);
568 if (error == PUFFS_NOSUCHCOOKIE) { 568 if (error == PUFFS_NOSUCHCOOKIE) {
569 error = puffs_getvnode(dvp->v_mount, 569 error = puffs_getvnode(dvp->v_mount,
570 lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype, 570 lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,
571 lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp); 571 lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp);
572 if (error) { 572 if (error) {
573 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), 573 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
574 lookup_msg->pvnr_newnode, ap->a_cnp); 574 lookup_msg->pvnr_newnode, ap->a_cnp);
575 goto out; 575 goto out;
576 } 576 }
577 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 577 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
578 } else if (error) { 578 } else if (error) {
579 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), 579 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
580 lookup_msg->pvnr_newnode, ap->a_cnp); 580 lookup_msg->pvnr_newnode, ap->a_cnp);
581 goto out; 581 goto out;
582 } 582 }
583 583
584 *ap->a_vpp = vp; 584 *ap->a_vpp = vp;
585 585
586 if ((cnp->cn_flags & MAKEENTRY) != 0 && PUFFS_USE_NAMECACHE(pmp)) 586 if ((cnp->cn_flags & MAKEENTRY) != 0 && PUFFS_USE_NAMECACHE(pmp))
587 cache_enter(dvp, vp, cnp); 587 cache_enter(dvp, vp, cnp);
588 588
589 /* XXX */ 589 /* XXX */
590 if ((lookup_msg->pvnr_cn.pkcn_flags & REQUIREDIR) == 0) 590 if ((lookup_msg->pvnr_cn.pkcn_flags & REQUIREDIR) == 0)
591 cnp->cn_flags &= ~REQUIREDIR; 591 cnp->cn_flags &= ~REQUIREDIR;
592 if (lookup_msg->pvnr_cn.pkcn_consume) 592 if (lookup_msg->pvnr_cn.pkcn_consume)
593 cnp->cn_consume = MIN(lookup_msg->pvnr_cn.pkcn_consume, 593 cnp->cn_consume = MIN(lookup_msg->pvnr_cn.pkcn_consume,
594 strlen(cnp->cn_nameptr) - cnp->cn_namelen); 594 strlen(cnp->cn_nameptr) - cnp->cn_namelen);
595 595
596 out: 596 out:
597 if (cnp->cn_flags & ISDOTDOT) 597 if (cnp->cn_flags & ISDOTDOT)
598 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); 598 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
599 599
600 DPRINTF(("puffs_lookup: returning %d %p\n", error, *ap->a_vpp)); 600 DPRINTF(("puffs_lookup: returning %d %p\n", error, *ap->a_vpp));
601 PUFFS_MSG_RELEASE(lookup); 601 PUFFS_MSG_RELEASE(lookup);
602 return error; 602 return error;
603} 603}
604 604
605#define REFPN_AND_UNLOCKVP(a, b) \ 605#define REFPN_AND_UNLOCKVP(a, b) \
606do { \ 606do { \
607 mutex_enter(&b->pn_mtx); \ 607 mutex_enter(&b->pn_mtx); \
608 puffs_referencenode(b); \ 608 puffs_referencenode(b); \
609 mutex_exit(&b->pn_mtx); \ 609 mutex_exit(&b->pn_mtx); \
610 VOP_UNLOCK(a); \ 610 VOP_UNLOCK(a); \
611} while (/*CONSTCOND*/0) 611} while (/*CONSTCOND*/0)
612 612
613#define REFPN(b) \ 613#define REFPN(b) \
614do { \ 614do { \
615 mutex_enter(&b->pn_mtx); \ 615 mutex_enter(&b->pn_mtx); \
616 puffs_referencenode(b); \ 616 puffs_referencenode(b); \
617 mutex_exit(&b->pn_mtx); \ 617 mutex_exit(&b->pn_mtx); \
618} while (/*CONSTCOND*/0) 618} while (/*CONSTCOND*/0)
619 619
620#define RELEPN_AND_VP(a, b) \ 620#define RELEPN_AND_VP(a, b) \
621do { \ 621do { \
622 puffs_releasenode(b); \ 622 puffs_releasenode(b); \
623 vrele(a); \ 623 vrele(a); \
624} while (/*CONSTCOND*/0) 624} while (/*CONSTCOND*/0)
625 625
626int 626int
627puffs_vnop_create(void *v) 627puffs_vnop_create(void *v)
628{ 628{
629 struct vop_create_args /* { 629 struct vop_create_args /* {
630 const struct vnodeop_desc *a_desc; 630 const struct vnodeop_desc *a_desc;
631 struct vnode *a_dvp; 631 struct vnode *a_dvp;
632 struct vnode **a_vpp; 632 struct vnode **a_vpp;
633 struct componentname *a_cnp; 633 struct componentname *a_cnp;
634 struct vattr *a_vap; 634 struct vattr *a_vap;
635 } */ *ap = v; 635 } */ *ap = v;
636 PUFFS_MSG_VARS(vn, create); 636 PUFFS_MSG_VARS(vn, create);
637 struct vnode *dvp = ap->a_dvp; 637 struct vnode *dvp = ap->a_dvp;
638 struct puffs_node *dpn = VPTOPP(dvp); 638 struct puffs_node *dpn = VPTOPP(dvp);
639 struct componentname *cnp = ap->a_cnp; 639 struct componentname *cnp = ap->a_cnp;
640 struct mount *mp = dvp->v_mount; 640 struct mount *mp = dvp->v_mount;
641 struct puffs_mount *pmp = MPTOPUFFSMP(mp); 641 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
642 int error; 642 int error;
643 643
644 DPRINTF(("puffs_create: dvp %p, cnp: %s\n", 644 DPRINTF(("puffs_create: dvp %p, cnp: %s\n",
645 dvp, ap->a_cnp->cn_nameptr)); 645 dvp, ap->a_cnp->cn_nameptr));
646 646
647 PUFFS_MSG_ALLOC(vn, create); 647 PUFFS_MSG_ALLOC(vn, create);
648 puffs_makecn(&create_msg->pvnr_cn, &create_msg->pvnr_cn_cred, 648 puffs_makecn(&create_msg->pvnr_cn, &create_msg->pvnr_cn_cred,
649 cnp, PUFFS_USE_FULLPNBUF(pmp)); 649 cnp, PUFFS_USE_FULLPNBUF(pmp));
650 create_msg->pvnr_va = *ap->a_vap; 650 create_msg->pvnr_va = *ap->a_vap;
651 puffs_msg_setinfo(park_create, PUFFSOP_VN, 651 puffs_msg_setinfo(park_create, PUFFSOP_VN,
652 PUFFS_VN_CREATE, VPTOPNC(dvp)); 652 PUFFS_VN_CREATE, VPTOPNC(dvp));
653 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_create, dvp->v_data, NULL, error); 653 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_create, dvp->v_data, NULL, error);
654 654
655 error = checkerr(pmp, error, __func__); 655 error = checkerr(pmp, error, __func__);
656 if (error) 656 if (error)
657 goto out; 657 goto out;
658 658
659 error = puffs_newnode(mp, dvp, ap->a_vpp, 659 error = puffs_newnode(mp, dvp, ap->a_vpp,
660 create_msg->pvnr_newnode, cnp, ap->a_vap->va_type, 0); 660 create_msg->pvnr_newnode, cnp, ap->a_vap->va_type, 0);
661 if (error) 661 if (error)
662 puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie, 662 puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie,
663 create_msg->pvnr_newnode, cnp); 663 create_msg->pvnr_newnode, cnp);
664 664
665 out: 665 out:
666 vput(dvp); 666 vput(dvp);
667 667
668 DPRINTF(("puffs_create: return %d\n", error)); 668 DPRINTF(("puffs_create: return %d\n", error));
669 PUFFS_MSG_RELEASE(create); 669 PUFFS_MSG_RELEASE(create);
670 return error; 670 return error;
671} 671}
672 672
673int 673int
674puffs_vnop_mknod(void *v) 674puffs_vnop_mknod(void *v)
675{ 675{
676 struct vop_mknod_args /* { 676 struct vop_mknod_args /* {
677 const struct vnodeop_desc *a_desc; 677 const struct vnodeop_desc *a_desc;
678 struct vnode *a_dvp; 678 struct vnode *a_dvp;
679 struct vnode **a_vpp; 679 struct vnode **a_vpp;
680 struct componentname *a_cnp; 680 struct componentname *a_cnp;
681 struct vattr *a_vap; 681 struct vattr *a_vap;
682 } */ *ap = v; 682 } */ *ap = v;
683 PUFFS_MSG_VARS(vn, mknod); 683 PUFFS_MSG_VARS(vn, mknod);
684 struct vnode *dvp = ap->a_dvp; 684 struct vnode *dvp = ap->a_dvp;
685 struct puffs_node *dpn = VPTOPP(dvp); 685 struct puffs_node *dpn = VPTOPP(dvp);
686 struct componentname *cnp = ap->a_cnp; 686 struct componentname *cnp = ap->a_cnp;
687 struct mount *mp = dvp->v_mount; 687 struct mount *mp = dvp->v_mount;
688 struct puffs_mount *pmp = MPTOPUFFSMP(mp); 688 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
689 int error; 689 int error;
690 690
691 PUFFS_MSG_ALLOC(vn, mknod); 691 PUFFS_MSG_ALLOC(vn, mknod);
692 puffs_makecn(&mknod_msg->pvnr_cn, &mknod_msg->pvnr_cn_cred, 692 puffs_makecn(&mknod_msg->pvnr_cn, &mknod_msg->pvnr_cn_cred,
693 cnp, PUFFS_USE_FULLPNBUF(pmp)); 693 cnp, PUFFS_USE_FULLPNBUF(pmp));
694 mknod_msg->pvnr_va = *ap->a_vap; 694 mknod_msg->pvnr_va = *ap->a_vap;
695 puffs_msg_setinfo(park_mknod, PUFFSOP_VN, 695 puffs_msg_setinfo(park_mknod, PUFFSOP_VN,
696 PUFFS_VN_MKNOD, VPTOPNC(dvp)); 696 PUFFS_VN_MKNOD, VPTOPNC(dvp));
697 697
698 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mknod, dvp->v_data, NULL, error); 698 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mknod, dvp->v_data, NULL, error);
699 699
700 error = checkerr(pmp, error, __func__); 700 error = checkerr(pmp, error, __func__);
701 if (error) 701 if (error)
702 goto out; 702 goto out;
703 703
704 error = puffs_newnode(mp, dvp, ap->a_vpp, 704 error = puffs_newnode(mp, dvp, ap->a_vpp,
705 mknod_msg->pvnr_newnode, cnp, ap->a_vap->va_type, 705 mknod_msg->pvnr_newnode, cnp, ap->a_vap->va_type,
706 ap->a_vap->va_rdev); 706 ap->a_vap->va_rdev);
707 if (error) 707 if (error)
708 puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie, 708 puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie,
709 mknod_msg->pvnr_newnode, cnp); 709 mknod_msg->pvnr_newnode, cnp);
710 710
711 out: 711 out:
712 vput(dvp); 712 vput(dvp);
713 PUFFS_MSG_RELEASE(mknod); 713 PUFFS_MSG_RELEASE(mknod);
714 return error; 714 return error;
715} 715}
716 716
717int 717int
718puffs_vnop_open(void *v) 718puffs_vnop_open(void *v)
719{ 719{
720 struct vop_open_args /* { 720 struct vop_open_args /* {
721 const struct vnodeop_desc *a_desc; 721 const struct vnodeop_desc *a_desc;
722 struct vnode *a_vp; 722 struct vnode *a_vp;
723 int a_mode; 723 int a_mode;
724 kauth_cred_t a_cred; 724 kauth_cred_t a_cred;
725 } */ *ap = v; 725 } */ *ap = v;
726 PUFFS_MSG_VARS(vn, open); 726 PUFFS_MSG_VARS(vn, open);
727 struct vnode *vp = ap->a_vp; 727 struct vnode *vp = ap->a_vp;
728 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 728 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
729 int mode = ap->a_mode; 729 int mode = ap->a_mode;
730 int error; 730 int error;
731 731
732 DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode)); 732 DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode));
733 733
734 if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE)) 734 if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE))
735 ERROUT(EROFS); 735 ERROUT(EROFS);
736 736
737 if (!EXISTSOP(pmp, OPEN)) 737 if (!EXISTSOP(pmp, OPEN))
738 ERROUT(0); 738 ERROUT(0);
739 739
740 PUFFS_MSG_ALLOC(vn, open); 740 PUFFS_MSG_ALLOC(vn, open);
741 open_msg->pvnr_mode = mode; 741 open_msg->pvnr_mode = mode;
742 puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred); 742 puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred);
743 puffs_msg_setinfo(park_open, PUFFSOP_VN, 743 puffs_msg_setinfo(park_open, PUFFSOP_VN,
744 PUFFS_VN_OPEN, VPTOPNC(vp)); 744 PUFFS_VN_OPEN, VPTOPNC(vp));
745 745
746 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_open, vp->v_data, NULL, error); 746 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_open, vp->v_data, NULL, error);
747 error = checkerr(pmp, error, __func__); 747 error = checkerr(pmp, error, __func__);
748 748
749 out: 749 out:
750 DPRINTF(("puffs_open: returning %d\n", error)); 750 DPRINTF(("puffs_open: returning %d\n", error));
751 PUFFS_MSG_RELEASE(open); 751 PUFFS_MSG_RELEASE(open);
752 return error; 752 return error;
753} 753}
754 754
755int 755int
756puffs_vnop_close(void *v) 756puffs_vnop_close(void *v)
757{ 757{
758 struct vop_close_args /* { 758 struct vop_close_args /* {
759 const struct vnodeop_desc *a_desc; 759 const struct vnodeop_desc *a_desc;
760 struct vnode *a_vp; 760 struct vnode *a_vp;
761 int a_fflag; 761 int a_fflag;
762 kauth_cred_t a_cred; 762 kauth_cred_t a_cred;
763 } */ *ap = v; 763 } */ *ap = v;
764 PUFFS_MSG_VARS(vn, close); 764 PUFFS_MSG_VARS(vn, close);
765 struct vnode *vp = ap->a_vp; 765 struct vnode *vp = ap->a_vp;
766 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 766 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
767 767
768 PUFFS_MSG_ALLOC(vn, close); 768 PUFFS_MSG_ALLOC(vn, close);
769 puffs_msg_setfaf(park_close); 769 puffs_msg_setfaf(park_close);
770 close_msg->pvnr_fflag = ap->a_fflag; 770 close_msg->pvnr_fflag = ap->a_fflag;
771 puffs_credcvt(&close_msg->pvnr_cred, ap->a_cred); 771 puffs_credcvt(&close_msg->pvnr_cred, ap->a_cred);
772 puffs_msg_setinfo(park_close, PUFFSOP_VN, 772 puffs_msg_setinfo(park_close, PUFFSOP_VN,
773 PUFFS_VN_CLOSE, VPTOPNC(vp)); 773 PUFFS_VN_CLOSE, VPTOPNC(vp));
774 774
775 puffs_msg_enqueue(pmp, park_close); 775 puffs_msg_enqueue(pmp, park_close);
776 PUFFS_MSG_RELEASE(close); 776 PUFFS_MSG_RELEASE(close);
777 return 0; 777 return 0;
778} 778}
779 779
780int 780int
781puffs_vnop_access(void *v) 781puffs_vnop_access(void *v)
782{ 782{
783 struct vop_access_args /* { 783 struct vop_access_args /* {
784 const struct vnodeop_desc *a_desc; 784 const struct vnodeop_desc *a_desc;
785 struct vnode *a_vp; 785 struct vnode *a_vp;
786 int a_mode; 786 int a_mode;
787 kauth_cred_t a_cred; 787 kauth_cred_t a_cred;
788 } */ *ap = v; 788 } */ *ap = v;
789 PUFFS_MSG_VARS(vn, access); 789 PUFFS_MSG_VARS(vn, access);
790 struct vnode *vp = ap->a_vp; 790 struct vnode *vp = ap->a_vp;
791 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 791 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
792 int mode = ap->a_mode; 792 int mode = ap->a_mode;
793 int error; 793 int error;
794 794
795 if (mode & VWRITE) { 795 if (mode & VWRITE) {
796 switch (vp->v_type) { 796 switch (vp->v_type) {
797 case VDIR: 797 case VDIR:
798 case VLNK: 798 case VLNK:
799 case VREG: 799 case VREG:
800 if ((vp->v_mount->mnt_flag & MNT_RDONLY) 800 if ((vp->v_mount->mnt_flag & MNT_RDONLY)
801 || !EXISTSOP(pmp, WRITE)) 801 || !EXISTSOP(pmp, WRITE))
802 return EROFS; 802 return EROFS;
803 break; 803 break;
804 default: 804 default:
805 break; 805 break;
806 } 806 }
807 } 807 }
808 808
809 if (!EXISTSOP(pmp, ACCESS)) 809 if (!EXISTSOP(pmp, ACCESS))
810 return 0; 810 return 0;
811 811
812 PUFFS_MSG_ALLOC(vn, access); 812 PUFFS_MSG_ALLOC(vn, access);
813 access_msg->pvnr_mode = ap->a_mode; 813 access_msg->pvnr_mode = ap->a_mode;
814 puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred); 814 puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred);
815 puffs_msg_setinfo(park_access, PUFFSOP_VN, 815 puffs_msg_setinfo(park_access, PUFFSOP_VN,
816 PUFFS_VN_ACCESS, VPTOPNC(vp)); 816 PUFFS_VN_ACCESS, VPTOPNC(vp));
817 817
818 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_access, vp->v_data, NULL, error); 818 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_access, vp->v_data, NULL, error);
819 error = checkerr(pmp, error, __func__); 819 error = checkerr(pmp, error, __func__);
820 PUFFS_MSG_RELEASE(access); 820 PUFFS_MSG_RELEASE(access);
821 821
822 return error; 822 return error;
823} 823}
824 824
825int 825int
826puffs_vnop_getattr(void *v) 826puffs_vnop_getattr(void *v)
827{ 827{
828 struct vop_getattr_args /* { 828 struct vop_getattr_args /* {
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 /* 842 /*
843 * A lock is required so that we do not race with  843 * A lock is required so that we do not race with
844 * setattr, write and fsync when changing vp->v_size. 844 * setattr, write and fsync when changing vp->v_size.
845 * This is critical, since setting a stall smaler value 845 * This is critical, since setting a stall smaler value
846 * triggers a file truncate in uvm_vnp_setsize(), which 846 * triggers a file truncate in uvm_vnp_setsize(), which
847 * most of the time means data corruption (a chunk of 847 * most of the time means data corruption (a chunk of
848 * data is replaced by zeroes). This can be removed if 848 * data is replaced by zeroes). This can be removed if
849 * we decide one day that VOP_GETATTR must operate on  849 * we decide one day that VOP_GETATTR must operate on
850 * a locked vnode. 850 * a locked vnode.
851 * 851 *
852 * XXX Should be useless now that VOP_GETATTR has been 852 * XXX Should be useless now that VOP_GETATTR has been
853 * fixed to always require a shared lock at least. 853 * fixed to always require a shared lock at least.
854 */ 854 */
855 mutex_enter(&pn->pn_sizemtx); 855 mutex_enter(&pn->pn_sizemtx);
856 856
857 REFPN(pn); 857 REFPN(pn);
858 vap = ap->a_vap; 858 vap = ap->a_vap;
859 859
860 PUFFS_MSG_ALLOC(vn, getattr); 860 PUFFS_MSG_ALLOC(vn, getattr);
861 vattr_null(&getattr_msg->pvnr_va); 861 vattr_null(&getattr_msg->pvnr_va);
862 puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred); 862 puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred);
863 puffs_msg_setinfo(park_getattr, PUFFSOP_VN, 863 puffs_msg_setinfo(park_getattr, PUFFSOP_VN,
864 PUFFS_VN_GETATTR, VPTOPNC(vp)); 864 PUFFS_VN_GETATTR, VPTOPNC(vp));
865 865
866 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error); 866 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error);
867 error = checkerr(pmp, error, __func__); 867 error = checkerr(pmp, error, __func__);
868 if (error) 868 if (error)
869 goto out; 869 goto out;
870 870
871 rvap = &getattr_msg->pvnr_va; 871 rvap = &getattr_msg->pvnr_va;
872 /* 872 /*
873 * Don't listen to the file server regarding special device 873 * Don't listen to the file server regarding special device
874 * size info, the file server doesn't know anything about them. 874 * size info, the file server doesn't know anything about them.
875 */ 875 */
876 if (vp->v_type == VBLK || vp->v_type == VCHR) 876 if (vp->v_type == VBLK || vp->v_type == VCHR)
877 rvap->va_size = vp->v_size; 877 rvap->va_size = vp->v_size;
878 878
879 /* Ditto for blocksize (ufs comment: this doesn't belong here) */ 879 /* Ditto for blocksize (ufs comment: this doesn't belong here) */
880 if (vp->v_type == VBLK) 880 if (vp->v_type == VBLK)
881 rvap->va_blocksize = BLKDEV_IOSIZE; 881 rvap->va_blocksize = BLKDEV_IOSIZE;
882 else if (vp->v_type == VCHR) 882 else if (vp->v_type == VCHR)
883 rvap->va_blocksize = MAXBSIZE; 883 rvap->va_blocksize = MAXBSIZE;
884 884
885 (void) memcpy(vap, rvap, sizeof(struct vattr)); 885 (void) memcpy(vap, rvap, sizeof(struct vattr));
886 vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 886 vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
887 887
888 if (pn->pn_stat & PNODE_METACACHE_ATIME) 888 if (pn->pn_stat & PNODE_METACACHE_ATIME)
889 vap->va_atime = pn->pn_mc_atime; 889 vap->va_atime = pn->pn_mc_atime;
890 if (pn->pn_stat & PNODE_METACACHE_CTIME) 890 if (pn->pn_stat & PNODE_METACACHE_CTIME)
891 vap->va_ctime = pn->pn_mc_ctime; 891 vap->va_ctime = pn->pn_mc_ctime;
892 if (pn->pn_stat & PNODE_METACACHE_MTIME) 892 if (pn->pn_stat & PNODE_METACACHE_MTIME)
893 vap->va_mtime = pn->pn_mc_mtime; 893 vap->va_mtime = pn->pn_mc_mtime;
894 if (pn->pn_stat & PNODE_METACACHE_SIZE) { 894 if (pn->pn_stat & PNODE_METACACHE_SIZE) {
895 vap->va_size = pn->pn_mc_size; 895 vap->va_size = pn->pn_mc_size;
896 } else { 896 } else {
897 if (rvap->va_size != VNOVAL 897 if (rvap->va_size != VNOVAL
898 && vp->v_type != VBLK && vp->v_type != VCHR) { 898 && vp->v_type != VBLK && vp->v_type != VCHR) {
899 uvm_vnp_setsize(vp, rvap->va_size); 899 uvm_vnp_setsize(vp, rvap->va_size);
900 pn->pn_serversize = rvap->va_size; 900 pn->pn_serversize = rvap->va_size;
901 } 901 }
902 } 902 }
903 903
904 out: 904 out:
905 puffs_releasenode(pn); 905 puffs_releasenode(pn);
906 PUFFS_MSG_RELEASE(getattr); 906 PUFFS_MSG_RELEASE(getattr);
907  907
908 mutex_exit(&pn->pn_sizemtx); 908 mutex_exit(&pn->pn_sizemtx);
909 909
910 return error; 910 return error;
911} 911}
912 912
913#define SETATTR_CHSIZE 0x01 913#define SETATTR_CHSIZE 0x01
914#define SETATTR_ASYNC 0x02 914#define SETATTR_ASYNC 0x02
915static int 915static int
916dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags) 916dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags)
917{ 917{
918 PUFFS_MSG_VARS(vn, setattr); 918 PUFFS_MSG_VARS(vn, setattr);
919 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 919 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
920 struct puffs_node *pn = vp->v_data; 920 struct puffs_node *pn = vp->v_data;
921 int error = 0; 921 int error = 0;
922 922
923 KASSERT(!(flags & SETATTR_CHSIZE) || mutex_owned(&pn->pn_sizemtx)); 923 KASSERT(!(flags & SETATTR_CHSIZE) || mutex_owned(&pn->pn_sizemtx));
924 924
925 if ((vp->v_mount->mnt_flag & MNT_RDONLY) && 925 if ((vp->v_mount->mnt_flag & MNT_RDONLY) &&
926 (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL 926 (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL
927 || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL 927 || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL
928 || vap->va_mode != (mode_t)VNOVAL)) 928 || vap->va_mode != (mode_t)VNOVAL))
929 return EROFS; 929 return EROFS;
930 930
931 if ((vp->v_mount->mnt_flag & MNT_RDONLY) 931 if ((vp->v_mount->mnt_flag & MNT_RDONLY)
932 && vp->v_type == VREG && vap->va_size != VNOVAL) 932 && vp->v_type == VREG && vap->va_size != VNOVAL)
933 return EROFS; 933 return EROFS;
934 934
935 /* 935 /*
936 * Flush metacache first. If we are called with some explicit 936 * Flush metacache first. If we are called with some explicit
937 * parameters, treat them as information overriding metacache 937 * parameters, treat them as information overriding metacache
938 * information. 938 * information.
939 */ 939 */
940 if (pn->pn_stat & PNODE_METACACHE_MASK) { 940 if (pn->pn_stat & PNODE_METACACHE_MASK) {
941 if ((pn->pn_stat & PNODE_METACACHE_ATIME) 941 if ((pn->pn_stat & PNODE_METACACHE_ATIME)
942 && vap->va_atime.tv_sec == VNOVAL) 942 && vap->va_atime.tv_sec == VNOVAL)
943 vap->va_atime = pn->pn_mc_atime; 943 vap->va_atime = pn->pn_mc_atime;
944 if ((pn->pn_stat & PNODE_METACACHE_CTIME) 944 if ((pn->pn_stat & PNODE_METACACHE_CTIME)
945 && vap->va_ctime.tv_sec == VNOVAL) 945 && vap->va_ctime.tv_sec == VNOVAL)
946 vap->va_ctime = pn->pn_mc_ctime; 946 vap->va_ctime = pn->pn_mc_ctime;
947 if ((pn->pn_stat & PNODE_METACACHE_MTIME) 947 if ((pn->pn_stat & PNODE_METACACHE_MTIME)
948 && vap->va_mtime.tv_sec == VNOVAL) 948 && vap->va_mtime.tv_sec == VNOVAL)
949 vap->va_mtime = pn->pn_mc_mtime; 949 vap->va_mtime = pn->pn_mc_mtime;
950 if ((pn->pn_stat & PNODE_METACACHE_SIZE) 950 if ((pn->pn_stat & PNODE_METACACHE_SIZE)
951 && vap->va_size == VNOVAL) 951 && vap->va_size == VNOVAL)
952 vap->va_size = pn->pn_mc_size; 952 vap->va_size = pn->pn_mc_size;
953 953
954 pn->pn_stat &= ~PNODE_METACACHE_MASK; 954 pn->pn_stat &= ~PNODE_METACACHE_MASK;
955 } 955 }
956 956
957 PUFFS_MSG_ALLOC(vn, setattr); 957 PUFFS_MSG_ALLOC(vn, setattr);
958 (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr)); 958 (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr));
959 puffs_credcvt(&setattr_msg->pvnr_cred, cred); 959 puffs_credcvt(&setattr_msg->pvnr_cred, cred);
960 puffs_msg_setinfo(park_setattr, PUFFSOP_VN, 960 puffs_msg_setinfo(park_setattr, PUFFSOP_VN,
961 PUFFS_VN_SETATTR, VPTOPNC(vp)); 961 PUFFS_VN_SETATTR, VPTOPNC(vp));
962 if (flags & SETATTR_ASYNC) 962 if (flags & SETATTR_ASYNC)
963 puffs_msg_setfaf(park_setattr); 963 puffs_msg_setfaf(park_setattr);
964 964
965 puffs_msg_enqueue(pmp, park_setattr); 965 puffs_msg_enqueue(pmp, park_setattr);
966 if ((flags & SETATTR_ASYNC) == 0) 966 if ((flags & SETATTR_ASYNC) == 0)
967 error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL); 967 error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL);
968 PUFFS_MSG_RELEASE(setattr); 968 PUFFS_MSG_RELEASE(setattr);
969 if ((flags & SETATTR_ASYNC) == 0) { 969 if ((flags & SETATTR_ASYNC) == 0) {
970 error = checkerr(pmp, error, __func__); 970 error = checkerr(pmp, error, __func__);
971 if (error) 971 if (error)
972 return error; 972 return error;
973 } else { 973 } else {
974 error = 0; 974 error = 0;
975 } 975 }
976 976
977 if (vap->va_size != VNOVAL) { 977 if (vap->va_size != VNOVAL) {
978 pn->pn_serversize = vap->va_size; 978 pn->pn_serversize = vap->va_size;
979 if (flags & SETATTR_CHSIZE) 979 if (flags & SETATTR_CHSIZE)
980 uvm_vnp_setsize(vp, vap->va_size); 980 uvm_vnp_setsize(vp, vap->va_size);
981 } 981 }
982 982
983 return 0; 983 return 0;
984} 984}
985 985
986int 986int
987puffs_vnop_setattr(void *v) 987puffs_vnop_setattr(void *v)
988{ 988{
989 struct vop_getattr_args /* { 989 struct vop_getattr_args /* {
990 const struct vnodeop_desc *a_desc; 990 const struct vnodeop_desc *a_desc;
991 struct vnode *a_vp; 991 struct vnode *a_vp;
992 struct vattr *a_vap; 992 struct vattr *a_vap;
993 kauth_cred_t a_cred; 993 kauth_cred_t a_cred;
994 } */ *ap = v; 994 } */ *ap = v;
995 struct puffs_node *pn = ap->a_vp->v_data; 995 struct puffs_node *pn = ap->a_vp->v_data;
996 int error; 996 int error;
997 997
998 mutex_enter(&pn->pn_sizemtx); 998 mutex_enter(&pn->pn_sizemtx);
999 error = dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE); 999 error = dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE);
1000 mutex_exit(&pn->pn_sizemtx); 1000 mutex_exit(&pn->pn_sizemtx);
1001 1001
1002 return error; 1002 return error;
1003} 1003}
1004 1004
1005static __inline int 1005static __inline int
1006doinact(struct puffs_mount *pmp, int iaflag) 1006doinact(struct puffs_mount *pmp, int iaflag)
1007{ 1007{
1008 1008
1009 if (EXISTSOP(pmp, INACTIVE)) 1009 if (EXISTSOP(pmp, INACTIVE))
1010 if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND) 1010 if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND)
1011 if (iaflag || ALLOPS(pmp)) 1011 if (iaflag || ALLOPS(pmp))
1012 return 1; 1012 return 1;
1013 else 1013 else
1014 return 0; 1014 return 0;
1015 else 1015 else
1016 return 1; 1016 return 1;
1017 else 1017 else
1018 return 0; 1018 return 0;
1019} 1019}
1020 1020
1021static void 1021static void
1022callinactive(struct puffs_mount *pmp, puffs_cookie_t ck, int iaflag) 1022callinactive(struct puffs_mount *pmp, puffs_cookie_t ck, int iaflag)
1023{ 1023{
1024 int error; 1024 int error;
1025 PUFFS_MSG_VARS(vn, inactive); 1025 PUFFS_MSG_VARS(vn, inactive);
1026 1026
1027 if (doinact(pmp, iaflag)) { 1027 if (doinact(pmp, iaflag)) {
1028 PUFFS_MSG_ALLOC(vn, inactive); 1028 PUFFS_MSG_ALLOC(vn, inactive);
1029 puffs_msg_setinfo(park_inactive, PUFFSOP_VN, 1029 puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
1030 PUFFS_VN_INACTIVE, ck); 1030 PUFFS_VN_INACTIVE, ck);
1031 1031
1032 PUFFS_MSG_ENQUEUEWAIT(pmp, park_inactive, error); 1032 PUFFS_MSG_ENQUEUEWAIT(pmp, park_inactive, error);
1033 PUFFS_MSG_RELEASE(inactive); 1033 PUFFS_MSG_RELEASE(inactive);
1034 } 1034 }
1035} 1035}
1036 1036
1037/* XXX: callinactive can't setback */ 1037/* XXX: callinactive can't setback */
1038int 1038int
1039puffs_vnop_inactive(void *v) 1039puffs_vnop_inactive(void *v)
1040{ 1040{
1041 struct vop_inactive_args /* { 1041 struct vop_inactive_args /* {
1042 const struct vnodeop_desc *a_desc; 1042 const struct vnodeop_desc *a_desc;
1043 struct vnode *a_vp; 1043 struct vnode *a_vp;
1044 } */ *ap = v; 1044 } */ *ap = v;
1045 PUFFS_MSG_VARS(vn, inactive); 1045 PUFFS_MSG_VARS(vn, inactive);
1046 struct vnode *vp = ap->a_vp; 1046 struct vnode *vp = ap->a_vp;
1047 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1047 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1048 struct puffs_node *pnode; 1048 struct puffs_node *pnode;
1049 int error; 1049 int error;
1050 1050
1051 pnode = vp->v_data; 1051 pnode = vp->v_data;
1052 mutex_enter(&pnode->pn_sizemtx); 1052 mutex_enter(&pnode->pn_sizemtx);
1053 1053
1054 if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) { 1054 if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) {
1055 flushvncache(vp, 0, 0, false); 1055 flushvncache(vp, 0, 0, false);
1056 PUFFS_MSG_ALLOC(vn, inactive); 1056 PUFFS_MSG_ALLOC(vn, inactive);
1057 puffs_msg_setinfo(park_inactive, PUFFSOP_VN, 1057 puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
1058 PUFFS_VN_INACTIVE, VPTOPNC(vp)); 1058 PUFFS_VN_INACTIVE, VPTOPNC(vp));
1059 1059
1060 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_inactive, vp->v_data, 1060 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_inactive, vp->v_data,
1061 NULL, error); 1061 NULL, error);
1062 PUFFS_MSG_RELEASE(inactive); 1062 PUFFS_MSG_RELEASE(inactive);
1063 } 1063 }
1064 pnode->pn_stat &= ~PNODE_DOINACT; 1064 pnode->pn_stat &= ~PNODE_DOINACT;
1065 1065
1066 /* 1066 /*
1067 * file server thinks it's gone? then don't be afraid care, 1067 * file server thinks it's gone? then don't be afraid care,
1068 * node's life was already all it would ever be 1068 * node's life was already all it would ever be
1069 */ 1069 */
1070 if (pnode->pn_stat & PNODE_NOREFS) { 1070 if (pnode->pn_stat & PNODE_NOREFS) {
1071 pnode->pn_stat |= PNODE_DYING; 1071 pnode->pn_stat |= PNODE_DYING;
1072 *ap->a_recycle = true; 1072 *ap->a_recycle = true;
1073 } 1073 }
1074 1074
1075 mutex_exit(&pnode->pn_sizemtx); 1075 mutex_exit(&pnode->pn_sizemtx);
1076 VOP_UNLOCK(vp); 1076 VOP_UNLOCK(vp);
1077 1077
1078 return 0; 1078 return 0;
1079} 1079}
1080 1080
1081static void 1081static void
1082callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck) 1082callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck)
1083{ 1083{
1084 PUFFS_MSG_VARS(vn, reclaim); 1084 PUFFS_MSG_VARS(vn, reclaim);
1085 1085
1086 if (!EXISTSOP(pmp, RECLAIM)) 1086 if (!EXISTSOP(pmp, RECLAIM))
1087 return; 1087 return;
1088 1088
1089 PUFFS_MSG_ALLOC(vn, reclaim); 1089 PUFFS_MSG_ALLOC(vn, reclaim);
1090 puffs_msg_setfaf(park_reclaim); 1090 puffs_msg_setfaf(park_reclaim);
1091 puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck); 1091 puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck);
1092 1092
1093 puffs_msg_enqueue(pmp, park_reclaim); 1093 puffs_msg_enqueue(pmp, park_reclaim);
1094 PUFFS_MSG_RELEASE(reclaim); 1094 PUFFS_MSG_RELEASE(reclaim);
1095} 1095}
1096 1096
1097/* 1097/*
1098 * always FAF, we don't really care if the server wants to fail to 1098 * always FAF, we don't really care if the server wants to fail to
1099 * reclaim the node or not 1099 * reclaim the node or not
1100 */ 1100 */
1101int 1101int
1102puffs_vnop_reclaim(void *v) 1102puffs_vnop_reclaim(void *v)
1103{ 1103{
1104 struct vop_reclaim_args /* { 1104 struct vop_reclaim_args /* {
1105 const struct vnodeop_desc *a_desc; 1105 const struct vnodeop_desc *a_desc;
1106 struct vnode *a_vp; 1106 struct vnode *a_vp;
1107 } */ *ap = v; 1107 } */ *ap = v;
1108 struct vnode *vp = ap->a_vp; 1108 struct vnode *vp = ap->a_vp;
1109 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1109 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1110 struct puffs_node *pnode = vp->v_data; 1110 struct puffs_node *pnode = vp->v_data;
1111 bool notifyserver = true; 1111 bool notifyserver = true;
1112 1112
1113 /* 1113 /*
1114 * first things first: check if someone is trying to reclaim the 1114 * first things first: check if someone is trying to reclaim the
1115 * root vnode. do not allow that to travel to userspace. 1115 * root vnode. do not allow that to travel to userspace.
1116 * Note that we don't need to take the lock similarly to 1116 * Note that we don't need to take the lock similarly to
1117 * puffs_root(), since there is only one of us. 1117 * puffs_root(), since there is only one of us.
1118 */ 1118 */
1119 if (vp->v_vflag & VV_ROOT) { 1119 if (vp->v_vflag & VV_ROOT) {
1120 mutex_enter(&pmp->pmp_lock); 1120 mutex_enter(&pmp->pmp_lock);
1121 KASSERT(pmp->pmp_root != NULL); 1121 KASSERT(pmp->pmp_root != NULL);
1122 pmp->pmp_root = NULL; 1122 pmp->pmp_root = NULL;
1123 mutex_exit(&pmp->pmp_lock); 1123 mutex_exit(&pmp->pmp_lock);
1124 notifyserver = false; 1124 notifyserver = false;
1125 } 1125 }
1126 1126
1127 /* 1127 /*
1128 * purge info from kernel before issueing FAF, since we 1128 * purge info from kernel before issueing FAF, since we
1129 * don't really know when we'll get around to it after 1129 * don't really know when we'll get around to it after
1130 * that and someone might race us into node creation 1130 * that and someone might race us into node creation
1131 */ 1131 */
1132 mutex_enter(&pmp->pmp_lock); 1132 mutex_enter(&pmp->pmp_lock);
1133 LIST_REMOVE(pnode, pn_hashent); 1133 LIST_REMOVE(pnode, pn_hashent);
1134 mutex_exit(&pmp->pmp_lock); 1134 mutex_exit(&pmp->pmp_lock);
1135 1135
1136 if (notifyserver) 1136 if (notifyserver)
1137 callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp)); 1137 callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp));
1138 1138
1139 puffs_putvnode(vp); 1139 puffs_putvnode(vp);
1140 vp->v_data = NULL; 1140 vp->v_data = NULL;
1141 1141
1142 return 0; 1142 return 0;
1143} 1143}
1144 1144
1145#define CSIZE sizeof(**ap->a_cookies) 1145#define CSIZE sizeof(**ap->a_cookies)
1146int 1146int
1147puffs_vnop_readdir(void *v) 1147puffs_vnop_readdir(void *v)
1148{ 1148{
1149 struct vop_readdir_args /* { 1149 struct vop_readdir_args /* {
1150 const struct vnodeop_desc *a_desc; 1150 const struct vnodeop_desc *a_desc;
1151 struct vnode *a_vp; 1151 struct vnode *a_vp;
1152 struct uio *a_uio; 1152 struct uio *a_uio;
1153 kauth_cred_t a_cred; 1153 kauth_cred_t a_cred;
1154 int *a_eofflag; 1154 int *a_eofflag;
1155 off_t **a_cookies; 1155 off_t **a_cookies;
1156 int *a_ncookies; 1156 int *a_ncookies;
1157 } */ *ap = v; 1157 } */ *ap = v;
1158 PUFFS_MSG_VARS(vn, readdir); 1158 PUFFS_MSG_VARS(vn, readdir);
1159 struct vnode *vp = ap->a_vp; 1159 struct vnode *vp = ap->a_vp;
1160 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1160 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1161 size_t argsize, tomove, cookiemem, cookiesmax; 1161 size_t argsize, tomove, cookiemem, cookiesmax;
1162 struct uio *uio = ap->a_uio; 1162 struct uio *uio = ap->a_uio;
1163 size_t howmuch, resid; 1163 size_t howmuch, resid;
1164 int error; 1164 int error;
1165 1165
1166 /* 1166 /*
1167 * ok, so we need: resid + cookiemem = maxreq 1167 * ok, so we need: resid + cookiemem = maxreq
1168 * => resid + cookiesize * (resid/minsize) = maxreq 1168 * => resid + cookiesize * (resid/minsize) = maxreq
1169 * => resid + cookiesize/minsize * resid = maxreq 1169 * => resid + cookiesize/minsize * resid = maxreq
1170 * => (cookiesize/minsize + 1) * resid = maxreq 1170 * => (cookiesize/minsize + 1) * resid = maxreq
1171 * => resid = maxreq / (cookiesize/minsize + 1) 1171 * => resid = maxreq / (cookiesize/minsize + 1)
1172 *  1172 *
1173 * Since cookiesize <= minsize and we're not very big on floats, 1173 * Since cookiesize <= minsize and we're not very big on floats,
1174 * we approximate that to be 1. Therefore: 1174 * we approximate that to be 1. Therefore:
1175 *  1175 *
1176 * resid = maxreq / 2; 1176 * resid = maxreq / 2;
1177 * 1177 *
1178 * Well, at least we didn't have to use differential equations 1178 * Well, at least we didn't have to use differential equations
1179 * or the Gram-Schmidt process. 1179 * or the Gram-Schmidt process.
1180 * 1180 *
1181 * (yes, I'm very afraid of this) 1181 * (yes, I'm very afraid of this)
1182 */ 1182 */
1183 KASSERT(CSIZE <= _DIRENT_MINSIZE((struct dirent *)0)); 1183 KASSERT(CSIZE <= _DIRENT_MINSIZE((struct dirent *)0));
1184 1184
1185 if (ap->a_cookies) { 1185 if (ap->a_cookies) {
1186 KASSERT(ap->a_ncookies != NULL); 1186 KASSERT(ap->a_ncookies != NULL);
1187 if (pmp->pmp_args.pa_fhsize == 0) 1187 if (pmp->pmp_args.pa_fhsize == 0)
1188 return EOPNOTSUPP; 1188 return EOPNOTSUPP;
1189 resid = PUFFS_TOMOVE(uio->uio_resid, pmp) / 2; 1189 resid = PUFFS_TOMOVE(uio->uio_resid, pmp) / 2;
1190 cookiesmax = resid/_DIRENT_MINSIZE((struct dirent *)0); 1190 cookiesmax = resid/_DIRENT_MINSIZE((struct dirent *)0);
1191 cookiemem = ALIGN(cookiesmax*CSIZE); /* play safe */ 1191 cookiemem = ALIGN(cookiesmax*CSIZE); /* play safe */
1192 } else { 1192 } else {
1193 resid = PUFFS_TOMOVE(uio->uio_resid, pmp); 1193 resid = PUFFS_TOMOVE(uio->uio_resid, pmp);
1194 cookiesmax = 0; 1194 cookiesmax = 0;
1195 cookiemem = 0; 1195 cookiemem = 0;
1196 } 1196 }
1197 1197
1198 argsize = sizeof(struct puffs_vnmsg_readdir); 1198 argsize = sizeof(struct puffs_vnmsg_readdir);
1199 tomove = resid + cookiemem; 1199 tomove = resid + cookiemem;
1200 puffs_msgmem_alloc(argsize + tomove, &park_readdir, 1200 puffs_msgmem_alloc(argsize + tomove, &park_readdir,
1201 (void *)&readdir_msg, 1); 1201 (void *)&readdir_msg, 1);
1202 1202
1203 puffs_credcvt(&readdir_msg->pvnr_cred, ap->a_cred); 1203 puffs_credcvt(&readdir_msg->pvnr_cred, ap->a_cred);
1204 readdir_msg->pvnr_offset = uio->uio_offset; 1204 readdir_msg->pvnr_offset = uio->uio_offset;
1205 readdir_msg->pvnr_resid = resid; 1205 readdir_msg->pvnr_resid = resid;
1206 readdir_msg->pvnr_ncookies = cookiesmax; 1206 readdir_msg->pvnr_ncookies = cookiesmax;
1207 readdir_msg->pvnr_eofflag = 0; 1207 readdir_msg->pvnr_eofflag = 0;
1208 readdir_msg->pvnr_dentoff = cookiemem; 1208 readdir_msg->pvnr_dentoff = cookiemem;
1209 puffs_msg_setinfo(park_readdir, PUFFSOP_VN, 1209 puffs_msg_setinfo(park_readdir, PUFFSOP_VN,
1210 PUFFS_VN_READDIR, VPTOPNC(vp)); 1210 PUFFS_VN_READDIR, VPTOPNC(vp));
1211 puffs_msg_setdelta(park_readdir, tomove); 1211 puffs_msg_setdelta(park_readdir, tomove);
1212 1212
1213 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readdir, vp->v_data, NULL, error); 1213 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readdir, vp->v_data, NULL, error);
1214 error = checkerr(pmp, error, __func__); 1214 error = checkerr(pmp, error, __func__);
1215 if (error) 1215 if (error)
1216 goto out; 1216 goto out;
1217 1217
1218 /* userspace is cheating? */ 1218 /* userspace is cheating? */
1219 if (readdir_msg->pvnr_resid > resid) { 1219 if (readdir_msg->pvnr_resid > resid) {
1220 puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG, 1220 puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
1221 "resid grew", VPTOPNC(vp)); 1221 "resid grew", VPTOPNC(vp));
1222 ERROUT(EPROTO); 1222 ERROUT(EPROTO);
1223 } 1223 }
1224 if (readdir_msg->pvnr_ncookies > cookiesmax) { 1224 if (readdir_msg->pvnr_ncookies > cookiesmax) {
1225 puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG, 1225 puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
1226 "too many cookies", VPTOPNC(vp)); 1226 "too many cookies", VPTOPNC(vp));
1227 ERROUT(EPROTO); 1227 ERROUT(EPROTO);
1228 } 1228 }
1229 1229
1230 /* check eof */ 1230 /* check eof */
1231 if (readdir_msg->pvnr_eofflag) 1231 if (readdir_msg->pvnr_eofflag)
1232 *ap->a_eofflag = 1; 1232 *ap->a_eofflag = 1;
1233 1233
1234 /* bouncy-wouncy with the directory data */ 1234 /* bouncy-wouncy with the directory data */
1235 howmuch = resid - readdir_msg->pvnr_resid; 1235 howmuch = resid - readdir_msg->pvnr_resid;
1236 1236
1237 /* force eof if no data was returned (getcwd() needs this) */ 1237 /* force eof if no data was returned (getcwd() needs this) */
1238 if (howmuch == 0) { 1238 if (howmuch == 0) {
1239 *ap->a_eofflag = 1; 1239 *ap->a_eofflag = 1;
1240 goto out; 1240 goto out;
1241 } 1241 }
1242 1242
1243 error = uiomove(readdir_msg->pvnr_data + cookiemem, howmuch, uio); 1243 error = uiomove(readdir_msg->pvnr_data + cookiemem, howmuch, uio);
1244 if (error) 1244 if (error)
1245 goto out; 1245 goto out;
1246 1246
1247 /* provide cookies to caller if so desired */ 1247 /* provide cookies to caller if so desired */
1248 if (ap->a_cookies) { 1248 if (ap->a_cookies) {
1249 KASSERT(curlwp != uvm.pagedaemon_lwp); 1249 KASSERT(curlwp != uvm.pagedaemon_lwp);
1250 *ap->a_cookies = malloc(readdir_msg->pvnr_ncookies*CSIZE, 1250 *ap->a_cookies = malloc(readdir_msg->pvnr_ncookies*CSIZE,
1251 M_TEMP, M_WAITOK); 1251 M_TEMP, M_WAITOK);
1252 *ap->a_ncookies = readdir_msg->pvnr_ncookies; 1252 *ap->a_ncookies = readdir_msg->pvnr_ncookies;
1253 memcpy(*ap->a_cookies, readdir_msg->pvnr_data, 1253 memcpy(*ap->a_cookies, readdir_msg->pvnr_data,
1254 *ap->a_ncookies*CSIZE); 1254 *ap->a_ncookies*CSIZE);
1255 } 1255 }
1256 1256
1257 /* next readdir starts here */ 1257 /* next readdir starts here */
1258 uio->uio_offset = readdir_msg->pvnr_offset; 1258 uio->uio_offset = readdir_msg->pvnr_offset;
1259 1259
1260 out: 1260 out:
1261 puffs_msgmem_release(park_readdir); 1261 puffs_msgmem_release(park_readdir);
1262 return error; 1262 return error;
1263} 1263}
1264#undef CSIZE 1264#undef CSIZE
1265 1265
1266/* 1266/*
1267 * poll works by consuming the bitmask in pn_revents. If there are 1267 * poll works by consuming the bitmask in pn_revents. If there are
1268 * events available, poll returns immediately. If not, it issues a 1268 * events available, poll returns immediately. If not, it issues a
1269 * poll to userspace, selrecords itself and returns with no available 1269 * poll to userspace, selrecords itself and returns with no available
1270 * events. When the file server returns, it executes puffs_parkdone_poll(), 1270 * events. When the file server returns, it executes puffs_parkdone_poll(),
1271 * where available events are added to the bitmask. selnotify() is 1271 * where available events are added to the bitmask. selnotify() is
1272 * then also executed by that function causing us to enter here again 1272 * then also executed by that function causing us to enter here again
1273 * and hopefully find the missing bits (unless someone got them first, 1273 * and hopefully find the missing bits (unless someone got them first,
1274 * in which case it starts all over again). 1274 * in which case it starts all over again).
1275 */ 1275 */
1276int 1276int
1277puffs_vnop_poll(void *v) 1277puffs_vnop_poll(void *v)
1278{ 1278{
1279 struct vop_poll_args /* { 1279 struct vop_poll_args /* {
1280 const struct vnodeop_desc *a_desc; 1280 const struct vnodeop_desc *a_desc;
1281 struct vnode *a_vp; 1281 struct vnode *a_vp;
1282 int a_events; 1282 int a_events;
1283 } */ *ap = v; 1283 } */ *ap = v;
1284 PUFFS_MSG_VARS(vn, poll); 1284 PUFFS_MSG_VARS(vn, poll);
1285 struct vnode *vp = ap->a_vp; 1285 struct vnode *vp = ap->a_vp;
1286 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1286 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1287 struct puffs_node *pn = vp->v_data; 1287 struct puffs_node *pn = vp->v_data;
1288 int events, error; 1288 int events, error;
1289 1289
1290 if (EXISTSOP(pmp, POLL)) { 1290 if (EXISTSOP(pmp, POLL)) {
1291 mutex_enter(&pn->pn_mtx); 1291 mutex_enter(&pn->pn_mtx);
1292 events = pn->pn_revents & ap->a_events; 1292 events = pn->pn_revents & ap->a_events;
1293 if (events & ap->a_events) { 1293 if (events & ap->a_events) {
1294 pn->pn_revents &= ~ap->a_events; 1294 pn->pn_revents &= ~ap->a_events;
1295 mutex_exit(&pn->pn_mtx); 1295 mutex_exit(&pn->pn_mtx);
1296 1296
1297 return events; 1297 return events;
1298 } else { 1298 } else {
1299 puffs_referencenode(pn); 1299 puffs_referencenode(pn);
1300 mutex_exit(&pn->pn_mtx); 1300 mutex_exit(&pn->pn_mtx);
1301 1301
1302 PUFFS_MSG_ALLOC(vn, poll); 1302 PUFFS_MSG_ALLOC(vn, poll);
1303 poll_msg->pvnr_events = ap->a_events; 1303 poll_msg->pvnr_events = ap->a_events;
1304 puffs_msg_setinfo(park_poll, PUFFSOP_VN, 1304 puffs_msg_setinfo(park_poll, PUFFSOP_VN,
1305 PUFFS_VN_POLL, VPTOPNC(vp)); 1305 PUFFS_VN_POLL, VPTOPNC(vp));
1306 puffs_msg_setcall(park_poll, puffs_parkdone_poll, pn); 1306 puffs_msg_setcall(park_poll, puffs_parkdone_poll, pn);
1307 selrecord(curlwp, &pn->pn_sel); 1307 selrecord(curlwp, &pn->pn_sel);
1308 1308
1309 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_poll, vp->v_data, 1309 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_poll, vp->v_data,
1310 NULL, error); 1310 NULL, error);
1311 PUFFS_MSG_RELEASE(poll); 1311 PUFFS_MSG_RELEASE(poll);
1312 1312
1313 return 0; 1313 return 0;
1314 } 1314 }
1315 } else { 1315 } else {
1316 return genfs_poll(v); 1316 return genfs_poll(v);
1317 } 1317 }
1318} 1318}
1319 1319
1320static int 1320static int
1321flushvncache(struct vnode *vp, off_t offlo, off_t offhi, bool wait) 1321flushvncache(struct vnode *vp, off_t offlo, off_t offhi, bool wait)
1322{ 1322{
1323 struct puffs_node *pn = VPTOPP(vp); 1323 struct puffs_node *pn = VPTOPP(vp);
1324 struct vattr va; 1324 struct vattr va;
1325 int pflags, error; 1325 int pflags, error;
1326 1326
1327 /* flush out information from our metacache, see vop_setattr */ 1327 /* flush out information from our metacache, see vop_setattr */
1328 if (pn->pn_stat & PNODE_METACACHE_MASK 1328 if (pn->pn_stat & PNODE_METACACHE_MASK
1329 && (pn->pn_stat & PNODE_DYING) == 0) { 1329 && (pn->pn_stat & PNODE_DYING) == 0) {
1330 vattr_null(&va); 1330 vattr_null(&va);
1331 error = dosetattr(vp, &va, FSCRED, 1331 error = dosetattr(vp, &va, FSCRED,
1332 SETATTR_CHSIZE | (wait ? 0 : SETATTR_ASYNC)); 1332 SETATTR_CHSIZE | (wait ? 0 : SETATTR_ASYNC));
1333 if (error) 1333 if (error)
1334 return error; 1334 return error;
1335 } 1335 }
1336 1336
1337 /* 1337 /*
1338 * flush pages to avoid being overly dirty 1338 * flush pages to avoid being overly dirty
1339 */ 1339 */
1340 pflags = PGO_CLEANIT; 1340 pflags = PGO_CLEANIT;
1341 if (wait) 1341 if (wait)
1342 pflags |= PGO_SYNCIO; 1342 pflags |= PGO_SYNCIO;
1343 mutex_enter(vp->v_interlock); 1343 mutex_enter(vp->v_interlock);
1344 return VOP_PUTPAGES(vp, trunc_page(offlo), round_page(offhi), pflags); 1344 return VOP_PUTPAGES(vp, trunc_page(offlo), round_page(offhi), pflags);
1345} 1345}
1346 1346
1347int 1347int
1348puffs_vnop_fsync(void *v) 1348puffs_vnop_fsync(void *v)
1349{ 1349{
1350 struct vop_fsync_args /* { 1350 struct vop_fsync_args /* {
1351 const struct vnodeop_desc *a_desc; 1351 const struct vnodeop_desc *a_desc;
1352 struct vnode *a_vp; 1352 struct vnode *a_vp;
1353 kauth_cred_t a_cred; 1353 kauth_cred_t a_cred;
1354 int a_flags; 1354 int a_flags;
1355 off_t a_offlo; 1355 off_t a_offlo;
1356 off_t a_offhi; 1356 off_t a_offhi;
1357 } */ *ap = v; 1357 } */ *ap = v;
1358 PUFFS_MSG_VARS(vn, fsync); 1358 PUFFS_MSG_VARS(vn, fsync);
1359 struct vnode *vp = ap->a_vp; 1359 struct vnode *vp;
1360 struct puffs_node *pn = VPTOPP(vp); 1360 struct puffs_node *pn;
1361 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1361 struct puffs_mount *pmp;
1362 int error, dofaf; 1362 int error, dofaf;
1363 1363
 1364 vp = ap->a_vp;
 1365 KASSERT(vp != NULL);
 1366 pn = VPTOPP(vp);
 1367 KASSERT(pn != NULL);
 1368 pmp = MPTOPUFFSMP(vp->v_mount);
1364 if (ap->a_flags & FSYNC_WAIT) { 1369 if (ap->a_flags & FSYNC_WAIT) {
1365 mutex_enter(&pn->pn_sizemtx); 1370 mutex_enter(&pn->pn_sizemtx);
1366 } else { 1371 } else {
1367 if (mutex_tryenter(&pn->pn_sizemtx) == 0) 1372 if (mutex_tryenter(&pn->pn_sizemtx) == 0)
1368 return EDEADLK; 1373 return EDEADLK;
1369 } 1374 }
1370 1375
1371 error = flushvncache(vp, ap->a_offlo, ap->a_offhi, 1376 error = flushvncache(vp, ap->a_offlo, ap->a_offhi,
1372 (ap->a_flags & FSYNC_WAIT) == FSYNC_WAIT); 1377 (ap->a_flags & FSYNC_WAIT) == FSYNC_WAIT);
1373 if (error) 1378 if (error)
1374 goto out; 1379 goto out;
1375 1380
1376 /* 1381 /*
1377 * HELLO! We exit already here if the user server does not 1382 * HELLO! We exit already here if the user server does not
1378 * support fsync OR if we should call fsync for a node which 1383 * support fsync OR if we should call fsync for a node which
1379 * has references neither in the kernel or the fs server. 1384 * has references neither in the kernel or the fs server.
1380 * Otherwise we continue to issue fsync() forward. 1385 * Otherwise we continue to issue fsync() forward.
1381 */ 1386 */
1382 error = 0; 1387 error = 0;
1383 if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING)) 1388 if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING))
1384 goto out; 1389 goto out;
1385 1390
1386 dofaf = (ap->a_flags & FSYNC_WAIT) == 0 || ap->a_flags == FSYNC_LAZY; 1391 dofaf = (ap->a_flags & FSYNC_WAIT) == 0 || ap->a_flags == FSYNC_LAZY;
1387 /* 1392 /*
1388 * We abuse VXLOCK to mean "vnode is going to die", so we issue 1393 * We abuse VXLOCK to mean "vnode is going to die", so we issue
1389 * only FAFs for those. Otherwise there's a danger of deadlock, 1394 * only FAFs for those. Otherwise there's a danger of deadlock,
1390 * since the execution context here might be the user server 1395 * since the execution context here might be the user server
1391 * doing some operation on another fs, which in turn caused a 1396 * doing some operation on another fs, which in turn caused a
1392 * vnode to be reclaimed from the freelist for this fs. 1397 * vnode to be reclaimed from the freelist for this fs.
1393 */ 1398 */
1394 if (dofaf == 0) { 1399 if (dofaf == 0) {
1395 mutex_enter(vp->v_interlock); 1400 mutex_enter(vp->v_interlock);
1396 if (vp->v_iflag & VI_XLOCK) 1401 if (vp->v_iflag & VI_XLOCK)
1397 dofaf = 1; 1402 dofaf = 1;
1398 mutex_exit(vp->v_interlock); 1403 mutex_exit(vp->v_interlock);
1399 } 1404 }
1400 1405
1401 PUFFS_MSG_ALLOC(vn, fsync); 1406 PUFFS_MSG_ALLOC(vn, fsync);
1402 if (dofaf) 1407 if (dofaf)
1403 puffs_msg_setfaf(park_fsync); 1408 puffs_msg_setfaf(park_fsync);
1404 1409
1405 puffs_credcvt(&fsync_msg->pvnr_cred, ap->a_cred); 1410 puffs_credcvt(&fsync_msg->pvnr_cred, ap->a_cred);
1406 fsync_msg->pvnr_flags = ap->a_flags; 1411 fsync_msg->pvnr_flags = ap->a_flags;
1407 fsync_msg->pvnr_offlo = ap->a_offlo; 1412 fsync_msg->pvnr_offlo = ap->a_offlo;
1408 fsync_msg->pvnr_offhi = ap->a_offhi; 1413 fsync_msg->pvnr_offhi = ap->a_offhi;
1409 puffs_msg_setinfo(park_fsync, PUFFSOP_VN, 1414 puffs_msg_setinfo(park_fsync, PUFFSOP_VN,
1410 PUFFS_VN_FSYNC, VPTOPNC(vp)); 1415 PUFFS_VN_FSYNC, VPTOPNC(vp));
1411 1416
1412 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error); 1417 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error);
1413 PUFFS_MSG_RELEASE(fsync); 1418 PUFFS_MSG_RELEASE(fsync);
1414 1419
1415 error = checkerr(pmp, error, __func__); 1420 error = checkerr(pmp, error, __func__);
1416 1421
1417out: 1422out:
1418 mutex_exit(&pn->pn_sizemtx); 1423 mutex_exit(&pn->pn_sizemtx);
1419 return error; 1424 return error;
1420} 1425}
1421 1426
1422int 1427int
1423puffs_vnop_seek(void *v) 1428puffs_vnop_seek(void *v)
1424{ 1429{
1425 struct vop_seek_args /* { 1430 struct vop_seek_args /* {
1426 const struct vnodeop_desc *a_desc; 1431 const struct vnodeop_desc *a_desc;
1427 struct vnode *a_vp; 1432 struct vnode *a_vp;
1428 off_t a_oldoff; 1433 off_t a_oldoff;
1429 off_t a_newoff; 1434 off_t a_newoff;
1430 kauth_cred_t a_cred; 1435 kauth_cred_t a_cred;
1431 } */ *ap = v; 1436 } */ *ap = v;
1432 PUFFS_MSG_VARS(vn, seek); 1437 PUFFS_MSG_VARS(vn, seek);
1433 struct vnode *vp = ap->a_vp; 1438 struct vnode *vp = ap->a_vp;
1434 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1439 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1435 int error; 1440 int error;
1436 1441
1437 PUFFS_MSG_ALLOC(vn, seek); 1442 PUFFS_MSG_ALLOC(vn, seek);
1438 seek_msg->pvnr_oldoff = ap->a_oldoff; 1443 seek_msg->pvnr_oldoff = ap->a_oldoff;
1439 seek_msg->pvnr_newoff = ap->a_newoff; 1444 seek_msg->pvnr_newoff = ap->a_newoff;
1440 puffs_credcvt(&seek_msg->pvnr_cred, ap->a_cred); 1445 puffs_credcvt(&seek_msg->pvnr_cred, ap->a_cred);
1441 puffs_msg_setinfo(park_seek, PUFFSOP_VN, 1446 puffs_msg_setinfo(park_seek, PUFFSOP_VN,
1442 PUFFS_VN_SEEK, VPTOPNC(vp)); 1447 PUFFS_VN_SEEK, VPTOPNC(vp));
1443 1448
1444 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_seek, vp->v_data, NULL, error); 1449 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_seek, vp->v_data, NULL, error);
1445 PUFFS_MSG_RELEASE(seek); 1450 PUFFS_MSG_RELEASE(seek);
1446 return checkerr(pmp, error, __func__); 1451 return checkerr(pmp, error, __func__);
1447} 1452}
1448 1453
1449static int 1454static int
1450callremove(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck, 1455callremove(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
1451 struct componentname *cnp) 1456 struct componentname *cnp)
1452{ 1457{
1453 PUFFS_MSG_VARS(vn, remove); 1458 PUFFS_MSG_VARS(vn, remove);
1454 int error; 1459 int error;
1455 1460
1456 PUFFS_MSG_ALLOC(vn, remove); 1461 PUFFS_MSG_ALLOC(vn, remove);
1457 remove_msg->pvnr_cookie_targ = ck; 1462 remove_msg->pvnr_cookie_targ = ck;
1458 puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred, 1463 puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
1459 cnp, PUFFS_USE_FULLPNBUF(pmp)); 1464 cnp, PUFFS_USE_FULLPNBUF(pmp));
1460 puffs_msg_setinfo(park_remove, PUFFSOP_VN, PUFFS_VN_REMOVE, dck); 1465 puffs_msg_setinfo(park_remove, PUFFSOP_VN, PUFFS_VN_REMOVE, dck);
1461 1466
1462 PUFFS_MSG_ENQUEUEWAIT(pmp, park_remove, error); 1467 PUFFS_MSG_ENQUEUEWAIT(pmp, park_remove, error);
1463 PUFFS_MSG_RELEASE(remove); 1468 PUFFS_MSG_RELEASE(remove);
1464 1469
1465 return checkerr(pmp, error, __func__); 1470 return checkerr(pmp, error, __func__);
1466} 1471}
1467 1472
1468/* 1473/*
1469 * XXX: can't use callremove now because can't catch setbacks with 1474 * XXX: can't use callremove now because can't catch setbacks with
1470 * it due to lack of a pnode argument. 1475 * it due to lack of a pnode argument.
1471 */ 1476 */
1472int 1477int
1473puffs_vnop_remove(void *v) 1478puffs_vnop_remove(void *v)
1474{ 1479{
1475 struct vop_remove_args /* { 1480 struct vop_remove_args /* {
1476 const struct vnodeop_desc *a_desc; 1481 const struct vnodeop_desc *a_desc;
1477 struct vnode *a_dvp; 1482 struct vnode *a_dvp;
1478 struct vnode *a_vp; 1483 struct vnode *a_vp;
1479 struct componentname *a_cnp; 1484 struct componentname *a_cnp;
1480 } */ *ap = v; 1485 } */ *ap = v;
1481 PUFFS_MSG_VARS(vn, remove); 1486 PUFFS_MSG_VARS(vn, remove);
1482 struct vnode *dvp = ap->a_dvp; 1487 struct vnode *dvp = ap->a_dvp;
1483 struct vnode *vp = ap->a_vp; 1488 struct vnode *vp = ap->a_vp;
1484 struct puffs_node *dpn = VPTOPP(dvp); 1489 struct puffs_node *dpn = VPTOPP(dvp);
1485 struct puffs_node *pn = VPTOPP(vp); 1490 struct puffs_node *pn = VPTOPP(vp);
1486 struct componentname *cnp = ap->a_cnp; 1491 struct componentname *cnp = ap->a_cnp;
1487 struct mount *mp = dvp->v_mount; 1492 struct mount *mp = dvp->v_mount;
1488 struct puffs_mount *pmp = MPTOPUFFSMP(mp); 1493 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1489 int error; 1494 int error;
1490 1495
1491 PUFFS_MSG_ALLOC(vn, remove); 1496 PUFFS_MSG_ALLOC(vn, remove);
1492 remove_msg->pvnr_cookie_targ = VPTOPNC(vp); 1497 remove_msg->pvnr_cookie_targ = VPTOPNC(vp);
1493 puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred, 1498 puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
1494 cnp, PUFFS_USE_FULLPNBUF(pmp)); 1499 cnp, PUFFS_USE_FULLPNBUF(pmp));
1495 puffs_msg_setinfo(park_remove, PUFFSOP_VN, 1500 puffs_msg_setinfo(park_remove, PUFFSOP_VN,
1496 PUFFS_VN_REMOVE, VPTOPNC(dvp)); 1501 PUFFS_VN_REMOVE, VPTOPNC(dvp));
1497 1502
1498 puffs_msg_enqueue(pmp, park_remove); 1503 puffs_msg_enqueue(pmp, park_remove);
1499 REFPN_AND_UNLOCKVP(dvp, dpn); 1504 REFPN_AND_UNLOCKVP(dvp, dpn);
1500 if (dvp == vp) 1505 if (dvp == vp)
1501 REFPN(pn); 1506 REFPN(pn);
1502 else 1507 else
1503 REFPN_AND_UNLOCKVP(vp, pn); 1508 REFPN_AND_UNLOCKVP(vp, pn);
1504 error = puffs_msg_wait2(pmp, park_remove, dpn, pn); 1509 error = puffs_msg_wait2(pmp, park_remove, dpn, pn);
1505 1510
1506 PUFFS_MSG_RELEASE(remove); 1511 PUFFS_MSG_RELEASE(remove);
1507 1512
1508 RELEPN_AND_VP(dvp, dpn); 1513 RELEPN_AND_VP(dvp, dpn);
1509 RELEPN_AND_VP(vp, pn); 1514 RELEPN_AND_VP(vp, pn);
1510 1515
1511 error = checkerr(pmp, error, __func__); 1516 error = checkerr(pmp, error, __func__);
1512 return error; 1517 return error;
1513} 1518}
1514 1519
1515int 1520int
1516puffs_vnop_mkdir(void *v) 1521puffs_vnop_mkdir(void *v)
1517{ 1522{
1518 struct vop_mkdir_args /* { 1523 struct vop_mkdir_args /* {
1519 const struct vnodeop_desc *a_desc; 1524 const struct vnodeop_desc *a_desc;
1520 struct vnode *a_dvp; 1525 struct vnode *a_dvp;
1521 struct vnode **a_vpp; 1526 struct vnode **a_vpp;
1522 struct componentname *a_cnp; 1527 struct componentname *a_cnp;
1523 struct vattr *a_vap; 1528 struct vattr *a_vap;
1524 } */ *ap = v; 1529 } */ *ap = v;
1525 PUFFS_MSG_VARS(vn, mkdir); 1530 PUFFS_MSG_VARS(vn, mkdir);
1526 struct vnode *dvp = ap->a_dvp; 1531 struct vnode *dvp = ap->a_dvp;
1527 struct puffs_node *dpn = VPTOPP(dvp); 1532 struct puffs_node *dpn = VPTOPP(dvp);
1528 struct componentname *cnp = ap->a_cnp; 1533 struct componentname *cnp = ap->a_cnp;
1529 struct mount *mp = dvp->v_mount; 1534 struct mount *mp = dvp->v_mount;
1530 struct puffs_mount *pmp = MPTOPUFFSMP(mp); 1535 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1531 int error; 1536 int error;
1532 1537
1533 PUFFS_MSG_ALLOC(vn, mkdir); 1538 PUFFS_MSG_ALLOC(vn, mkdir);
1534 puffs_makecn(&mkdir_msg->pvnr_cn, &mkdir_msg->pvnr_cn_cred, 1539 puffs_makecn(&mkdir_msg->pvnr_cn, &mkdir_msg->pvnr_cn_cred,
1535 cnp, PUFFS_USE_FULLPNBUF(pmp)); 1540 cnp, PUFFS_USE_FULLPNBUF(pmp));
1536 mkdir_msg->pvnr_va = *ap->a_vap; 1541 mkdir_msg->pvnr_va = *ap->a_vap;
1537 puffs_msg_setinfo(park_mkdir, PUFFSOP_VN, 1542 puffs_msg_setinfo(park_mkdir, PUFFSOP_VN,
1538 PUFFS_VN_MKDIR, VPTOPNC(dvp)); 1543 PUFFS_VN_MKDIR, VPTOPNC(dvp));
1539 1544
1540 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mkdir, dvp->v_data, NULL, error); 1545 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mkdir, dvp->v_data, NULL, error);
1541 1546
1542 error = checkerr(pmp, error, __func__); 1547 error = checkerr(pmp, error, __func__);
1543 if (error) 1548 if (error)
1544 goto out; 1549 goto out;
1545 1550
1546 error = puffs_newnode(mp, dvp, ap->a_vpp, 1551 error = puffs_newnode(mp, dvp, ap->a_vpp,
1547 mkdir_msg->pvnr_newnode, cnp, VDIR, 0); 1552 mkdir_msg->pvnr_newnode, cnp, VDIR, 0);
1548 if (error) 1553 if (error)
1549 puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie, 1554 puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie,
1550 mkdir_msg->pvnr_newnode, cnp); 1555 mkdir_msg->pvnr_newnode, cnp);
1551 1556
1552 out: 1557 out:
1553 vput(dvp); 1558 vput(dvp);
1554 PUFFS_MSG_RELEASE(mkdir); 1559 PUFFS_MSG_RELEASE(mkdir);
1555 return error; 1560 return error;
1556} 1561}
1557 1562
1558static int 1563static int
1559callrmdir(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck, 1564callrmdir(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
1560 struct componentname *cnp) 1565 struct componentname *cnp)
1561{ 1566{
1562 PUFFS_MSG_VARS(vn, rmdir); 1567 PUFFS_MSG_VARS(vn, rmdir);
1563 int error; 1568 int error;
1564 1569
1565 PUFFS_MSG_ALLOC(vn, rmdir); 1570 PUFFS_MSG_ALLOC(vn, rmdir);
1566 rmdir_msg->pvnr_cookie_targ = ck; 1571 rmdir_msg->pvnr_cookie_targ = ck;
1567 puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred, 1572 puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1568 cnp, PUFFS_USE_FULLPNBUF(pmp)); 1573 cnp, PUFFS_USE_FULLPNBUF(pmp));
1569 puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, PUFFS_VN_RMDIR, dck); 1574 puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, PUFFS_VN_RMDIR, dck);
1570 1575
1571 PUFFS_MSG_ENQUEUEWAIT(pmp, park_rmdir, error); 1576 PUFFS_MSG_ENQUEUEWAIT(pmp, park_rmdir, error);
1572 PUFFS_MSG_RELEASE(rmdir); 1577 PUFFS_MSG_RELEASE(rmdir);
1573 1578
1574 return checkerr(pmp, error, __func__); 1579 return checkerr(pmp, error, __func__);
1575} 1580}
1576 1581
1577int 1582int
1578puffs_vnop_rmdir(void *v) 1583puffs_vnop_rmdir(void *v)
1579{ 1584{
1580 struct vop_rmdir_args /* { 1585 struct vop_rmdir_args /* {
1581 const struct vnodeop_desc *a_desc; 1586 const struct vnodeop_desc *a_desc;
1582 struct vnode *a_dvp; 1587 struct vnode *a_dvp;
1583 struct vnode *a_vp; 1588 struct vnode *a_vp;
1584 struct componentname *a_cnp; 1589 struct componentname *a_cnp;
1585 } */ *ap = v; 1590 } */ *ap = v;
1586 PUFFS_MSG_VARS(vn, rmdir); 1591 PUFFS_MSG_VARS(vn, rmdir);
1587 struct vnode *dvp = ap->a_dvp; 1592 struct vnode *dvp = ap->a_dvp;
1588 struct vnode *vp = ap->a_vp; 1593 struct vnode *vp = ap->a_vp;
1589 struct puffs_node *dpn = VPTOPP(dvp); 1594 struct puffs_node *dpn = VPTOPP(dvp);
1590 struct puffs_node *pn = VPTOPP(vp); 1595 struct puffs_node *pn = VPTOPP(vp);
1591 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount); 1596 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1592 struct componentname *cnp = ap->a_cnp; 1597 struct componentname *cnp = ap->a_cnp;
1593 int error; 1598 int error;
1594 1599
1595 PUFFS_MSG_ALLOC(vn, rmdir); 1600 PUFFS_MSG_ALLOC(vn, rmdir);
1596 rmdir_msg->pvnr_cookie_targ = VPTOPNC(vp); 1601 rmdir_msg->pvnr_cookie_targ = VPTOPNC(vp);
1597 puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred, 1602 puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1598 cnp, PUFFS_USE_FULLPNBUF(pmp)); 1603 cnp, PUFFS_USE_FULLPNBUF(pmp));
1599 puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, 1604 puffs_msg_setinfo(park_rmdir, PUFFSOP_VN,
1600 PUFFS_VN_RMDIR, VPTOPNC(dvp)); 1605 PUFFS_VN_RMDIR, VPTOPNC(dvp));
1601 1606
1602 puffs_msg_enqueue(pmp, park_rmdir); 1607 puffs_msg_enqueue(pmp, park_rmdir);
1603 REFPN_AND_UNLOCKVP(dvp, dpn); 1608 REFPN_AND_UNLOCKVP(dvp, dpn);
1604 REFPN_AND_UNLOCKVP(vp, pn); 1609 REFPN_AND_UNLOCKVP(vp, pn);
1605 error = puffs_msg_wait2(pmp, park_rmdir, dpn, pn); 1610 error = puffs_msg_wait2(pmp, park_rmdir, dpn, pn);
1606 1611
1607 PUFFS_MSG_RELEASE(rmdir); 1612 PUFFS_MSG_RELEASE(rmdir);
1608 1613
1609 /* XXX: some call cache_purge() *for both vnodes* here, investigate */ 1614 /* XXX: some call cache_purge() *for both vnodes* here, investigate */
1610 RELEPN_AND_VP(dvp, dpn); 1615 RELEPN_AND_VP(dvp, dpn);
1611 RELEPN_AND_VP(vp, pn); 1616 RELEPN_AND_VP(vp, pn);
1612 1617
1613 return error; 1618 return error;
1614} 1619}
1615 1620
1616int 1621int
1617puffs_vnop_link(void *v) 1622puffs_vnop_link(void *v)
1618{ 1623{
1619 struct vop_link_args /* { 1624 struct vop_link_args /* {
1620 const struct vnodeop_desc *a_desc; 1625 const struct vnodeop_desc *a_desc;
1621 struct vnode *a_dvp; 1626 struct vnode *a_dvp;
1622 struct vnode *a_vp; 1627 struct vnode *a_vp;
1623 struct componentname *a_cnp; 1628 struct componentname *a_cnp;
1624 } */ *ap = v; 1629 } */ *ap = v;
1625 PUFFS_MSG_VARS(vn, link); 1630 PUFFS_MSG_VARS(vn, link);
1626 struct vnode *dvp = ap->a_dvp; 1631 struct vnode *dvp = ap->a_dvp;
1627 struct vnode *vp = ap->a_vp; 1632 struct vnode *vp = ap->a_vp;
1628 struct puffs_node *dpn = VPTOPP(dvp); 1633 struct puffs_node *dpn = VPTOPP(dvp);
1629 struct puffs_node *pn = VPTOPP(vp); 1634 struct puffs_node *pn = VPTOPP(vp);
1630 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount); 1635 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1631 struct componentname *cnp = ap->a_cnp; 1636 struct componentname *cnp = ap->a_cnp;
1632 int error; 1637 int error;
1633 1638
1634 PUFFS_MSG_ALLOC(vn, link); 1639 PUFFS_MSG_ALLOC(vn, link);
1635 link_msg->pvnr_cookie_targ = VPTOPNC(vp); 1640 link_msg->pvnr_cookie_targ = VPTOPNC(vp);
1636 puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred, 1641 puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred,
1637 cnp, PUFFS_USE_FULLPNBUF(pmp)); 1642 cnp, PUFFS_USE_FULLPNBUF(pmp));
1638 puffs_msg_setinfo(park_link, PUFFSOP_VN, 1643 puffs_msg_setinfo(park_link, PUFFSOP_VN,
1639 PUFFS_VN_LINK, VPTOPNC(dvp)); 1644 PUFFS_VN_LINK, VPTOPNC(dvp));
1640 1645
1641 puffs_msg_enqueue(pmp, park_link); 1646 puffs_msg_enqueue(pmp, park_link);
1642 REFPN_AND_UNLOCKVP(dvp, dpn); 1647 REFPN_AND_UNLOCKVP(dvp, dpn);
1643 REFPN(pn); 1648 REFPN(pn);
1644 error = puffs_msg_wait2(pmp, park_link, dpn, pn); 1649 error = puffs_msg_wait2(pmp, park_link, dpn, pn);
1645 1650
1646 PUFFS_MSG_RELEASE(link); 1651 PUFFS_MSG_RELEASE(link);
1647 1652
1648 error = checkerr(pmp, error, __func__); 1653 error = checkerr(pmp, error, __func__);
1649 1654
1650 /* 1655 /*
1651 * XXX: stay in touch with the cache. I don't like this, but 1656 * XXX: stay in touch with the cache. I don't like this, but
1652 * don't have a better solution either. See also puffs_rename(). 1657 * don't have a better solution either. See also puffs_rename().
1653 */ 1658 */
1654 if (error == 0) 1659 if (error == 0)
1655 puffs_updatenode(pn, PUFFS_UPDATECTIME, 0); 1660 puffs_updatenode(pn, PUFFS_UPDATECTIME, 0);
1656 1661
1657 RELEPN_AND_VP(dvp, dpn); 1662 RELEPN_AND_VP(dvp, dpn);
1658 puffs_releasenode(pn); 1663 puffs_releasenode(pn);
1659 1664
1660 return error; 1665 return error;
1661} 1666}
1662 1667
1663int 1668int
1664puffs_vnop_symlink(void *v) 1669puffs_vnop_symlink(void *v)
1665{ 1670{
1666 struct vop_symlink_args /* { 1671 struct vop_symlink_args /* {
1667 const struct vnodeop_desc *a_desc; 1672 const struct vnodeop_desc *a_desc;
1668 struct vnode *a_dvp; 1673 struct vnode *a_dvp;
1669 struct vnode **a_vpp; 1674 struct vnode **a_vpp;
1670 struct componentname *a_cnp; 1675 struct componentname *a_cnp;
1671 struct vattr *a_vap; 1676 struct vattr *a_vap;
1672 char *a_target; 1677 char *a_target;
1673 } */ *ap = v; 1678 } */ *ap = v;
1674 PUFFS_MSG_VARS(vn, symlink); 1679 PUFFS_MSG_VARS(vn, symlink);
1675 struct vnode *dvp = ap->a_dvp; 1680 struct vnode *dvp = ap->a_dvp;
1676 struct puffs_node *dpn = VPTOPP(dvp); 1681 struct puffs_node *dpn = VPTOPP(dvp);
1677 struct mount *mp = dvp->v_mount; 1682 struct mount *mp = dvp->v_mount;
1678 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount); 1683 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1679 struct componentname *cnp = ap->a_cnp; 1684 struct componentname *cnp = ap->a_cnp;
1680 int error; 1685 int error;
1681 1686
1682 *ap->a_vpp = NULL; 1687 *ap->a_vpp = NULL;
1683 1688
1684 PUFFS_MSG_ALLOC(vn, symlink); 1689 PUFFS_MSG_ALLOC(vn, symlink);
1685 puffs_makecn(&symlink_msg->pvnr_cn, &symlink_msg->pvnr_cn_cred, 1690 puffs_makecn(&symlink_msg->pvnr_cn, &symlink_msg->pvnr_cn_cred,
1686 cnp, PUFFS_USE_FULLPNBUF(pmp)); 1691 cnp, PUFFS_USE_FULLPNBUF(pmp));
1687 symlink_msg->pvnr_va = *ap->a_vap; 1692 symlink_msg->pvnr_va = *ap->a_vap;
1688 (void)strlcpy(symlink_msg->pvnr_link, ap->a_target, 1693 (void)strlcpy(symlink_msg->pvnr_link, ap->a_target,
1689 sizeof(symlink_msg->pvnr_link)); 1694 sizeof(symlink_msg->pvnr_link));
1690 puffs_msg_setinfo(park_symlink, PUFFSOP_VN, 1695 puffs_msg_setinfo(park_symlink, PUFFSOP_VN,
1691 PUFFS_VN_SYMLINK, VPTOPNC(dvp)); 1696 PUFFS_VN_SYMLINK, VPTOPNC(dvp));
1692 1697
1693 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_symlink, dvp->v_data, NULL, error); 1698 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_symlink, dvp->v_data, NULL, error);
1694 1699
1695 error = checkerr(pmp, error, __func__); 1700 error = checkerr(pmp, error, __func__);
1696 if (error) 1701 if (error)
1697 goto out; 1702 goto out;
1698 1703
1699 error = puffs_newnode(mp, dvp, ap->a_vpp, 1704 error = puffs_newnode(mp, dvp, ap->a_vpp,
1700 symlink_msg->pvnr_newnode, cnp, VLNK, 0); 1705 symlink_msg->pvnr_newnode, cnp, VLNK, 0);
1701 if (error) 1706 if (error)
1702 puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie, 1707 puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie,
1703 symlink_msg->pvnr_newnode, cnp); 1708 symlink_msg->pvnr_newnode, cnp);
1704 1709
1705 out: 1710 out:
1706 vput(dvp); 1711 vput(dvp);
1707 PUFFS_MSG_RELEASE(symlink); 1712 PUFFS_MSG_RELEASE(symlink);
1708 1713
1709 return error; 1714 return error;
1710} 1715}
1711 1716
1712int 1717int
1713puffs_vnop_readlink(void *v) 1718puffs_vnop_readlink(void *v)
1714{ 1719{
1715 struct vop_readlink_args /* { 1720 struct vop_readlink_args /* {
1716 const struct vnodeop_desc *a_desc; 1721 const struct vnodeop_desc *a_desc;
1717 struct vnode *a_vp; 1722 struct vnode *a_vp;
1718 struct uio *a_uio; 1723 struct uio *a_uio;
1719 kauth_cred_t a_cred; 1724 kauth_cred_t a_cred;
1720 } */ *ap = v; 1725 } */ *ap = v;
1721 PUFFS_MSG_VARS(vn, readlink); 1726 PUFFS_MSG_VARS(vn, readlink);
1722 struct vnode *vp = ap->a_vp; 1727 struct vnode *vp = ap->a_vp;
1723 struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_vp->v_mount); 1728 struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1724 size_t linklen; 1729 size_t linklen;
1725 int error; 1730 int error;
1726 1731
1727 PUFFS_MSG_ALLOC(vn, readlink); 1732 PUFFS_MSG_ALLOC(vn, readlink);
1728 puffs_credcvt(&readlink_msg->pvnr_cred, ap->a_cred); 1733 puffs_credcvt(&readlink_msg->pvnr_cred, ap->a_cred);
1729 linklen = sizeof(readlink_msg->pvnr_link); 1734 linklen = sizeof(readlink_msg->pvnr_link);
1730 readlink_msg->pvnr_linklen = linklen; 1735 readlink_msg->pvnr_linklen = linklen;
1731 puffs_msg_setinfo(park_readlink, PUFFSOP_VN, 1736 puffs_msg_setinfo(park_readlink, PUFFSOP_VN,
1732 PUFFS_VN_READLINK, VPTOPNC(vp)); 1737 PUFFS_VN_READLINK, VPTOPNC(vp));
1733 1738
1734 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readlink, vp->v_data, NULL, error); 1739 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readlink, vp->v_data, NULL, error);
1735 error = checkerr(pmp, error, __func__); 1740 error = checkerr(pmp, error, __func__);
1736 if (error) 1741 if (error)
1737 goto out; 1742 goto out;
1738 1743
1739 /* bad bad user file server */ 1744 /* bad bad user file server */
1740 if (readlink_msg->pvnr_linklen > linklen) { 1745 if (readlink_msg->pvnr_linklen > linklen) {
1741 puffs_senderr(pmp, PUFFS_ERR_READLINK, E2BIG, 1746 puffs_senderr(pmp, PUFFS_ERR_READLINK, E2BIG,
1742 "linklen too big", VPTOPNC(ap->a_vp)); 1747 "linklen too big", VPTOPNC(ap->a_vp));
1743 error = EPROTO; 1748 error = EPROTO;
1744 goto out; 1749 goto out;
1745 } 1750 }
1746 1751
1747 error = uiomove(&readlink_msg->pvnr_link, readlink_msg->pvnr_linklen, 1752 error = uiomove(&readlink_msg->pvnr_link, readlink_msg->pvnr_linklen,
1748 ap->a_uio); 1753 ap->a_uio);
1749 out: 1754 out:
1750 PUFFS_MSG_RELEASE(readlink); 1755 PUFFS_MSG_RELEASE(readlink);
1751 return error; 1756 return error;
1752} 1757}
1753 1758
1754int 1759int
1755puffs_vnop_rename(void *v) 1760puffs_vnop_rename(void *v)
1756{ 1761{
1757 struct vop_rename_args /* { 1762 struct vop_rename_args /* {
1758 const struct vnodeop_desc *a_desc; 1763 const struct vnodeop_desc *a_desc;
1759 struct vnode *a_fdvp; 1764 struct vnode *a_fdvp;
1760 struct vnode *a_fvp; 1765 struct vnode *a_fvp;
1761 struct componentname *a_fcnp; 1766 struct componentname *a_fcnp;
1762 struct vnode *a_tdvp; 1767 struct vnode *a_tdvp;
1763 struct vnode *a_tvp; 1768 struct vnode *a_tvp;
1764 struct componentname *a_tcnp; 1769 struct componentname *a_tcnp;
1765 } */ *ap = v; 1770 } */ *ap = v;
1766 PUFFS_MSG_VARS(vn, rename); 1771 PUFFS_MSG_VARS(vn, rename);
1767 struct vnode *fdvp = ap->a_fdvp, *fvp = ap->a_fvp; 1772 struct vnode *fdvp = ap->a_fdvp, *fvp = ap->a_fvp;
1768 struct vnode *tdvp = ap->a_tdvp, *tvp = ap->a_tvp; 1773 struct vnode *tdvp = ap->a_tdvp, *tvp = ap->a_tvp;
1769 struct puffs_node *fpn = ap->a_fvp->v_data; 1774 struct puffs_node *fpn = ap->a_fvp->v_data;
1770 struct puffs_mount *pmp = MPTOPUFFSMP(fdvp->v_mount); 1775 struct puffs_mount *pmp = MPTOPUFFSMP(fdvp->v_mount);
1771 int error; 1776 int error;
1772 bool doabort = true; 1777 bool doabort = true;
1773 1778
1774 if ((fvp->v_mount != tdvp->v_mount) || 1779 if ((fvp->v_mount != tdvp->v_mount) ||
1775 (tvp && (fvp->v_mount != tvp->v_mount))) { 1780 (tvp && (fvp->v_mount != tvp->v_mount))) {
1776 ERROUT(EXDEV); 1781 ERROUT(EXDEV);
1777 } 1782 }
1778 1783
1779 PUFFS_MSG_ALLOC(vn, rename); 1784 PUFFS_MSG_ALLOC(vn, rename);
1780 rename_msg->pvnr_cookie_src = VPTOPNC(fvp); 1785 rename_msg->pvnr_cookie_src = VPTOPNC(fvp);
1781 rename_msg->pvnr_cookie_targdir = VPTOPNC(tdvp); 1786 rename_msg->pvnr_cookie_targdir = VPTOPNC(tdvp);
1782 if (tvp) 1787 if (tvp)
1783 rename_msg->pvnr_cookie_targ = VPTOPNC(tvp); 1788 rename_msg->pvnr_cookie_targ = VPTOPNC(tvp);
1784 else 1789 else
1785 rename_msg->pvnr_cookie_targ = NULL; 1790 rename_msg->pvnr_cookie_targ = NULL;
1786 puffs_makecn(&rename_msg->pvnr_cn_src, &rename_msg->pvnr_cn_src_cred, 1791 puffs_makecn(&rename_msg->pvnr_cn_src, &rename_msg->pvnr_cn_src_cred,
1787 ap->a_fcnp, PUFFS_USE_FULLPNBUF(pmp)); 1792 ap->a_fcnp, PUFFS_USE_FULLPNBUF(pmp));
1788 puffs_makecn(&rename_msg->pvnr_cn_targ, &rename_msg->pvnr_cn_targ_cred, 1793 puffs_makecn(&rename_msg->pvnr_cn_targ, &rename_msg->pvnr_cn_targ_cred,
1789 ap->a_tcnp, PUFFS_USE_FULLPNBUF(pmp)); 1794 ap->a_tcnp, PUFFS_USE_FULLPNBUF(pmp));
1790 puffs_msg_setinfo(park_rename, PUFFSOP_VN, 1795 puffs_msg_setinfo(park_rename, PUFFSOP_VN,
1791 PUFFS_VN_RENAME, VPTOPNC(fdvp)); 1796 PUFFS_VN_RENAME, VPTOPNC(fdvp));
1792 1797
1793 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rename, fdvp->v_data, NULL, error); 1798 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rename, fdvp->v_data, NULL, error);
1794 doabort = false; 1799 doabort = false;
1795 PUFFS_MSG_RELEASE(rename); 1800 PUFFS_MSG_RELEASE(rename);
1796 error = checkerr(pmp, error, __func__); 1801 error = checkerr(pmp, error, __func__);
1797 1802
1798 /* 1803 /*
1799 * XXX: stay in touch with the cache. I don't like this, but 1804 * XXX: stay in touch with the cache. I don't like this, but
1800 * don't have a better solution either. See also puffs_link(). 1805 * don't have a better solution either. See also puffs_link().
1801 */ 1806 */
1802 if (error == 0) 1807 if (error == 0)
1803 puffs_updatenode(fpn, PUFFS_UPDATECTIME, 0); 1808 puffs_updatenode(fpn, PUFFS_UPDATECTIME, 0);
1804 1809
1805 out: 1810 out:
1806 if (doabort) 1811 if (doabort)
1807 VOP_ABORTOP(tdvp, ap->a_tcnp); 1812 VOP_ABORTOP(tdvp, ap->a_tcnp);
1808 if (tvp != NULL) 1813 if (tvp != NULL)
1809 vput(tvp); 1814 vput(tvp);
1810 if (tdvp == tvp) 1815 if (tdvp == tvp)
1811 vrele(tdvp); 1816 vrele(tdvp);
1812 else 1817 else
1813 vput(tdvp); 1818 vput(tdvp);
1814 1819
1815 if (doabort) 1820 if (doabort)
1816 VOP_ABORTOP(fdvp, ap->a_fcnp); 1821 VOP_ABORTOP(fdvp, ap->a_fcnp);
1817 vrele(fdvp); 1822 vrele(fdvp);
1818 vrele(fvp); 1823 vrele(fvp);
1819 1824
1820 return error; 1825 return error;
1821} 1826}
1822 1827
1823#define RWARGS(cont, iofl, move, offset, creds) \ 1828#define RWARGS(cont, iofl, move, offset, creds) \
1824 (cont)->pvnr_ioflag = (iofl); \ 1829 (cont)->pvnr_ioflag = (iofl); \
1825 (cont)->pvnr_resid = (move); \ 1830 (cont)->pvnr_resid = (move); \
1826 (cont)->pvnr_offset = (offset); \ 1831 (cont)->pvnr_offset = (offset); \
1827 puffs_credcvt(&(cont)->pvnr_cred, creds) 1832 puffs_credcvt(&(cont)->pvnr_cred, creds)
1828 1833
1829int 1834int
1830puffs_vnop_read(void *v) 1835puffs_vnop_read(void *v)
1831{ 1836{
1832 struct vop_read_args /* {  1837 struct vop_read_args /* {
1833 const struct vnodeop_desc *a_desc; 1838 const struct vnodeop_desc *a_desc;
1834 struct vnode *a_vp; 1839 struct vnode *a_vp;
1835 struct uio *a_uio; 1840 struct uio *a_uio;
1836 int a_ioflag; 1841 int a_ioflag;
1837 kauth_cred_t a_cred; 1842 kauth_cred_t a_cred;
1838 } */ *ap = v; 1843 } */ *ap = v;
1839 PUFFS_MSG_VARS(vn, read); 1844 PUFFS_MSG_VARS(vn, read);
1840 struct vnode *vp = ap->a_vp; 1845 struct vnode *vp = ap->a_vp;
1841 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1846 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1842 struct uio *uio = ap->a_uio; 1847 struct uio *uio = ap->a_uio;
1843 size_t tomove, argsize; 1848 size_t tomove, argsize;
1844 vsize_t bytelen; 1849 vsize_t bytelen;
1845 int error; 1850 int error;
1846 1851
1847 read_msg = NULL; 1852 read_msg = NULL;
1848 error = 0; 1853 error = 0;
1849 1854
1850 /* std sanity */ 1855 /* std sanity */
1851 if (uio->uio_resid == 0) 1856 if (uio->uio_resid == 0)
1852 return 0; 1857 return 0;
1853 if (uio->uio_offset < 0) 1858 if (uio->uio_offset < 0)
1854 return EINVAL; 1859 return EINVAL;
1855 1860
1856 if (vp->v_type == VREG && PUFFS_USE_PAGECACHE(pmp)) { 1861 if (vp->v_type == VREG && PUFFS_USE_PAGECACHE(pmp)) {
1857 const int advice = IO_ADV_DECODE(ap->a_ioflag); 1862 const int advice = IO_ADV_DECODE(ap->a_ioflag);
1858 1863
1859 while (uio->uio_resid > 0) { 1864 while (uio->uio_resid > 0) {
1860 bytelen = MIN(uio->uio_resid, 1865 bytelen = MIN(uio->uio_resid,
1861 vp->v_size - uio->uio_offset); 1866 vp->v_size - uio->uio_offset);
1862 if (bytelen == 0) 1867 if (bytelen == 0)
1863 break; 1868 break;
1864 1869
1865 error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice, 1870 error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
1866 UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp)); 1871 UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
1867 if (error) 1872 if (error)
1868 break; 1873 break;
1869 } 1874 }
1870 1875
1871 if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0) 1876 if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
1872 puffs_updatenode(VPTOPP(vp), PUFFS_UPDATEATIME, 0); 1877 puffs_updatenode(VPTOPP(vp), PUFFS_UPDATEATIME, 0);
1873 } else { 1878 } else {
1874 /* 1879 /*
1875 * in case it's not a regular file or we're operating 1880 * in case it's not a regular file or we're operating
1876 * uncached, do read in the old-fashioned style, 1881 * uncached, do read in the old-fashioned style,
1877 * i.e. explicit read operations 1882 * i.e. explicit read operations
1878 */ 1883 */
1879 1884
1880 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp); 1885 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1881 argsize = sizeof(struct puffs_vnmsg_read); 1886 argsize = sizeof(struct puffs_vnmsg_read);
1882 puffs_msgmem_alloc(argsize + tomove, &park_read, 1887 puffs_msgmem_alloc(argsize + tomove, &park_read,
1883 (void *)&read_msg, 1); 1888 (void *)&read_msg, 1);
1884 1889
1885 error = 0; 1890 error = 0;
1886 while (uio->uio_resid > 0) { 1891 while (uio->uio_resid > 0) {
1887 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp); 1892 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1888 memset(read_msg, 0, argsize); /* XXX: touser KASSERT */ 1893 memset(read_msg, 0, argsize); /* XXX: touser KASSERT */
1889 RWARGS(read_msg, ap->a_ioflag, tomove, 1894 RWARGS(read_msg, ap->a_ioflag, tomove,
1890 uio->uio_offset, ap->a_cred); 1895 uio->uio_offset, ap->a_cred);
1891 puffs_msg_setinfo(park_read, PUFFSOP_VN, 1896 puffs_msg_setinfo(park_read, PUFFSOP_VN,
1892 PUFFS_VN_READ, VPTOPNC(vp)); 1897 PUFFS_VN_READ, VPTOPNC(vp));
1893 puffs_msg_setdelta(park_read, tomove); 1898 puffs_msg_setdelta(park_read, tomove);
1894 1899
1895 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_read, vp->v_data, 1900 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_read, vp->v_data,
1896 NULL, error); 1901 NULL, error);
1897 error = checkerr(pmp, error, __func__); 1902 error = checkerr(pmp, error, __func__);
1898 if (error) 1903 if (error)
1899 break; 1904 break;
1900 1905
1901 if (read_msg->pvnr_resid > tomove) { 1906 if (read_msg->pvnr_resid > tomove) {
1902 puffs_senderr(pmp, PUFFS_ERR_READ, 1907 puffs_senderr(pmp, PUFFS_ERR_READ,
1903 E2BIG, "resid grew", VPTOPNC(ap->a_vp)); 1908 E2BIG, "resid grew", VPTOPNC(ap->a_vp));
1904 error = EPROTO; 1909 error = EPROTO;
1905 break; 1910 break;
1906 } 1911 }
1907 1912
1908 error = uiomove(read_msg->pvnr_data, 1913 error = uiomove(read_msg->pvnr_data,
1909 tomove - read_msg->pvnr_resid, uio); 1914 tomove - read_msg->pvnr_resid, uio);
1910 1915
1911 /* 1916 /*
1912 * in case the file is out of juice, resid from 1917 * in case the file is out of juice, resid from
1913 * userspace is != 0. and the error-case is 1918 * userspace is != 0. and the error-case is
1914 * quite obvious 1919 * quite obvious
1915 */ 1920 */
1916 if (error || read_msg->pvnr_resid) 1921 if (error || read_msg->pvnr_resid)
1917 break; 1922 break;
1918 } 1923 }
1919 1924
1920 puffs_msgmem_release(park_read); 1925 puffs_msgmem_release(park_read);
1921 } 1926 }
1922 1927
1923 return error; 1928 return error;
1924} 1929}
1925 1930
1926/* 1931/*
1927 * XXX: in case of a failure, this leaves uio in a bad state. 1932 * XXX: in case of a failure, this leaves uio in a bad state.
1928 * We could theoretically copy the uio and iovecs and "replay" 1933 * We could theoretically copy the uio and iovecs and "replay"
1929 * them the right amount after the userspace trip, but don't 1934 * them the right amount after the userspace trip, but don't
1930 * bother for now. 1935 * bother for now.
1931 */ 1936 */
1932int 1937int
1933puffs_vnop_write(void *v) 1938puffs_vnop_write(void *v)
1934{ 1939{
1935 struct vop_write_args /* { 1940 struct vop_write_args /* {
1936 const struct vnodeop_desc *a_desc; 1941 const struct vnodeop_desc *a_desc;
1937 struct vnode *a_vp; 1942 struct vnode *a_vp;
1938 struct uio *a_uio; 1943 struct uio *a_uio;
1939 int a_ioflag; 1944 int a_ioflag;
1940 kauth_cred_t a_cred; 1945 kauth_cred_t a_cred;
1941 } */ *ap = v; 1946 } */ *ap = v;
1942 PUFFS_MSG_VARS(vn, write); 1947 PUFFS_MSG_VARS(vn, write);
1943 struct vnode *vp = ap->a_vp; 1948 struct vnode *vp = ap->a_vp;
1944 struct puffs_node *pn = VPTOPP(vp); 1949 struct puffs_node *pn = VPTOPP(vp);
1945 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 1950 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1946 struct uio *uio = ap->a_uio; 1951 struct uio *uio = ap->a_uio;
1947 size_t tomove, argsize; 1952 size_t tomove, argsize;
1948 off_t oldoff, newoff, origoff; 1953 off_t oldoff, newoff, origoff;
1949 vsize_t bytelen; 1954 vsize_t bytelen;
1950 int error, uflags; 1955 int error, uflags;
1951 int ubcflags; 1956 int ubcflags;
1952 1957
1953 error = uflags = 0; 1958 error = uflags = 0;
1954 write_msg = NULL; 1959 write_msg = NULL;
1955 1960
1956 mutex_enter(&pn->pn_sizemtx); 1961 mutex_enter(&pn->pn_sizemtx);
1957 1962
1958 if (vp->v_type == VREG && PUFFS_USE_PAGECACHE(pmp)) { 1963 if (vp->v_type == VREG && PUFFS_USE_PAGECACHE(pmp)) {
1959 ubcflags = UBC_WRITE | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp); 1964 ubcflags = UBC_WRITE | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp);
1960 1965
1961 /* 1966 /*
1962 * userspace *should* be allowed to control this, 1967 * userspace *should* be allowed to control this,
1963 * but with UBC it's a bit unclear how to handle it 1968 * but with UBC it's a bit unclear how to handle it
1964 */ 1969 */
1965 if (ap->a_ioflag & IO_APPEND) 1970 if (ap->a_ioflag & IO_APPEND)
1966 uio->uio_offset = vp->v_size; 1971 uio->uio_offset = vp->v_size;
1967 1972
1968 origoff = uio->uio_offset; 1973 origoff = uio->uio_offset;
1969 while (uio->uio_resid > 0) { 1974 while (uio->uio_resid > 0) {
1970 if (vp->v_mount->mnt_flag & MNT_RELATIME) 1975 if (vp->v_mount->mnt_flag & MNT_RELATIME)
1971 uflags |= PUFFS_UPDATEATIME; 1976 uflags |= PUFFS_UPDATEATIME;
1972 uflags |= PUFFS_UPDATECTIME; 1977 uflags |= PUFFS_UPDATECTIME;
1973 uflags |= PUFFS_UPDATEMTIME; 1978 uflags |= PUFFS_UPDATEMTIME;
1974 oldoff = uio->uio_offset; 1979 oldoff = uio->uio_offset;
1975 bytelen = uio->uio_resid; 1980 bytelen = uio->uio_resid;
1976 1981
1977 newoff = oldoff + bytelen; 1982 newoff = oldoff + bytelen;
1978 if (vp->v_size < newoff) { 1983 if (vp->v_size < newoff) {
1979 uvm_vnp_setwritesize(vp, newoff); 1984 uvm_vnp_setwritesize(vp, newoff);
1980 } 1985 }
1981 error = ubc_uiomove(&vp->v_uobj, uio, bytelen, 1986 error = ubc_uiomove(&vp->v_uobj, uio, bytelen,
1982 UVM_ADV_RANDOM, ubcflags); 1987 UVM_ADV_RANDOM, ubcflags);
1983 1988
1984 /* 1989 /*
1985 * In case of a ubc_uiomove() error, 1990 * In case of a ubc_uiomove() error,
1986 * opt to not extend the file at all and 1991 * opt to not extend the file at all and
1987 * return an error. Otherwise, if we attempt 1992 * return an error. Otherwise, if we attempt
1988 * to clear the memory we couldn't fault to, 1993 * to clear the memory we couldn't fault to,
1989 * we might generate a kernel page fault. 1994 * we might generate a kernel page fault.
1990 */ 1995 */
1991 if (vp->v_size < newoff) { 1996 if (vp->v_size < newoff) {
1992 if (error == 0) { 1997 if (error == 0) {
1993 uflags |= PUFFS_UPDATESIZE; 1998 uflags |= PUFFS_UPDATESIZE;
1994 uvm_vnp_setsize(vp, newoff); 1999 uvm_vnp_setsize(vp, newoff);
1995 } else { 2000 } else {
1996 uvm_vnp_setwritesize(vp, vp->v_size); 2001 uvm_vnp_setwritesize(vp, vp->v_size);
1997 } 2002 }
1998 } 2003 }
1999 if (error) 2004 if (error)
2000 break; 2005 break;
2001 2006
2002 /* 2007 /*
2003 * If we're writing large files, flush to file server 2008 * If we're writing large files, flush to file server
2004 * every 64k. Otherwise we can very easily exhaust 2009 * every 64k. Otherwise we can very easily exhaust
2005 * kernel and user memory, as the file server cannot 2010 * kernel and user memory, as the file server cannot
2006 * really keep up with our writing speed. 2011 * really keep up with our writing speed.
2007 * 2012 *
2008 * Note: this does *NOT* honor MNT_ASYNC, because 2013 * Note: this does *NOT* honor MNT_ASYNC, because
2009 * that gives userland too much say in the kernel. 2014 * that gives userland too much say in the kernel.
2010 */ 2015 */
2011 if (oldoff >> 16 != uio->uio_offset >> 16) { 2016 if (oldoff >> 16 != uio->uio_offset >> 16) {
2012 mutex_enter(vp->v_interlock); 2017 mutex_enter(vp->v_interlock);
2013 error = VOP_PUTPAGES(vp, oldoff & ~0xffff, 2018 error = VOP_PUTPAGES(vp, oldoff & ~0xffff,
2014 uio->uio_offset & ~0xffff, 2019 uio->uio_offset & ~0xffff,
2015 PGO_CLEANIT | PGO_SYNCIO); 2020 PGO_CLEANIT | PGO_SYNCIO);
2016 if (error) 2021 if (error)
2017 break; 2022 break;
2018 } 2023 }
2019 } 2024 }
2020 2025
2021 /* synchronous I/O? */ 2026 /* synchronous I/O? */
2022 if (error == 0 && ap->a_ioflag & IO_SYNC) { 2027 if (error == 0 && ap->a_ioflag & IO_SYNC) {
2023 mutex_enter(vp->v_interlock); 2028 mutex_enter(vp->v_interlock);
2024 error = VOP_PUTPAGES(vp, trunc_page(origoff), 2029 error = VOP_PUTPAGES(vp, trunc_page(origoff),
2025 round_page(uio->uio_offset), 2030 round_page(uio->uio_offset),
2026 PGO_CLEANIT | PGO_SYNCIO); 2031 PGO_CLEANIT | PGO_SYNCIO);
2027 2032
2028 /* write through page cache? */ 2033 /* write through page cache? */
2029 } else if (error == 0 && pmp->pmp_flags & PUFFS_KFLAG_WTCACHE) { 2034 } else if (error == 0 && pmp->pmp_flags & PUFFS_KFLAG_WTCACHE) {
2030 mutex_enter(vp->v_interlock); 2035 mutex_enter(vp->v_interlock);
2031 error = VOP_PUTPAGES(vp, trunc_page(origoff), 2036 error = VOP_PUTPAGES(vp, trunc_page(origoff),
2032 round_page(uio->uio_offset), PGO_CLEANIT); 2037 round_page(uio->uio_offset), PGO_CLEANIT);
2033 } 2038 }
2034 2039
2035 puffs_updatenode(VPTOPP(vp), uflags, vp->v_size); 2040 puffs_updatenode(VPTOPP(vp), uflags, vp->v_size);
2036 } else { 2041 } else {
2037 /* tomove is non-increasing */ 2042 /* tomove is non-increasing */
2038 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp); 2043 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
2039 argsize = sizeof(struct puffs_vnmsg_write) + tomove; 2044 argsize = sizeof(struct puffs_vnmsg_write) + tomove;
2040 puffs_msgmem_alloc(argsize, &park_write, (void *)&write_msg,1); 2045 puffs_msgmem_alloc(argsize, &park_write, (void *)&write_msg,1);
2041 2046
2042 while (uio->uio_resid > 0) { 2047 while (uio->uio_resid > 0) {
2043 /* move data to buffer */ 2048 /* move data to buffer */
2044 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp); 2049 tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
2045 memset(write_msg, 0, argsize); /* XXX: touser KASSERT */ 2050 memset(write_msg, 0, argsize); /* XXX: touser KASSERT */
2046 RWARGS(write_msg, ap->a_ioflag, tomove, 2051 RWARGS(write_msg, ap->a_ioflag, tomove,
2047 uio->uio_offset, ap->a_cred); 2052 uio->uio_offset, ap->a_cred);
2048 error = uiomove(write_msg->pvnr_data, tomove, uio); 2053 error = uiomove(write_msg->pvnr_data, tomove, uio);
2049 if (error) 2054 if (error)
2050 break; 2055 break;
2051 2056
2052 /* move buffer to userspace */ 2057 /* move buffer to userspace */
2053 puffs_msg_setinfo(park_write, PUFFSOP_VN, 2058 puffs_msg_setinfo(park_write, PUFFSOP_VN,
2054 PUFFS_VN_WRITE, VPTOPNC(vp)); 2059 PUFFS_VN_WRITE, VPTOPNC(vp));
2055 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_write, vp->v_data, 2060 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_write, vp->v_data,
2056 NULL, error); 2061 NULL, error);
2057 error = checkerr(pmp, error, __func__); 2062 error = checkerr(pmp, error, __func__);
2058 if (error) 2063 if (error)
2059 break; 2064 break;
2060 2065
2061 if (write_msg->pvnr_resid > tomove) { 2066 if (write_msg->pvnr_resid > tomove) {
2062 puffs_senderr(pmp, PUFFS_ERR_WRITE, 2067 puffs_senderr(pmp, PUFFS_ERR_WRITE,
2063 E2BIG, "resid grew", VPTOPNC(ap->a_vp)); 2068 E2BIG, "resid grew", VPTOPNC(ap->a_vp));
2064 error = EPROTO; 2069 error = EPROTO;
2065 break; 2070 break;
2066 } 2071 }
2067 2072
2068 /* adjust file size */ 2073 /* adjust file size */
2069 if (vp->v_size < uio->uio_offset) 2074 if (vp->v_size < uio->uio_offset)
2070 uvm_vnp_setsize(vp, uio->uio_offset); 2075 uvm_vnp_setsize(vp, uio->uio_offset);
2071 2076
2072 /* didn't move everything? bad userspace. bail */ 2077 /* didn't move everything? bad userspace. bail */
2073 if (write_msg->pvnr_resid != 0) { 2078 if (write_msg->pvnr_resid != 0) {
2074 error = EIO; 2079 error = EIO;
2075 break; 2080 break;
2076 } 2081 }
2077 } 2082 }
2078 puffs_msgmem_release(park_write); 2083 puffs_msgmem_release(park_write);
2079 } 2084 }
2080 2085
2081 mutex_exit(&pn->pn_sizemtx); 2086 mutex_exit(&pn->pn_sizemtx);
2082 return error; 2087 return error;
2083} 2088}
2084 2089
2085int 2090int
2086puffs_vnop_print(void *v) 2091puffs_vnop_print(void *v)
2087{ 2092{
2088 struct vop_print_args /* { 2093 struct vop_print_args /* {
2089 struct vnode *a_vp; 2094 struct vnode *a_vp;
2090 } */ *ap = v; 2095 } */ *ap = v;
2091 PUFFS_MSG_VARS(vn, print); 2096 PUFFS_MSG_VARS(vn, print);
2092 struct vnode *vp = ap->a_vp; 2097 struct vnode *vp = ap->a_vp;
2093 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 2098 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
2094 struct puffs_node *pn = vp->v_data; 2099 struct puffs_node *pn = vp->v_data;
2095 int error; 2100 int error;
2096 2101
2097 /* kernel portion */ 2102 /* kernel portion */
2098 printf("tag VT_PUFFS, vnode %p, puffs node: %p,\n" 2103 printf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
2099 "\tuserspace cookie: %p", vp, pn, pn->pn_cookie); 2104 "\tuserspace cookie: %p", vp, pn, pn->pn_cookie);
2100 if (vp->v_type == VFIFO) 2105 if (vp->v_type == VFIFO)
2101 VOCALL(fifo_vnodeop_p, VOFFSET(vop_print), v); 2106 VOCALL(fifo_vnodeop_p, VOFFSET(vop_print), v);
2102 printf("\n"); 2107 printf("\n");
2103 2108
2104 /* userspace portion */ 2109 /* userspace portion */
2105 if (EXISTSOP(pmp, PRINT)) { 2110 if (EXISTSOP(pmp, PRINT)) {
2106 PUFFS_MSG_ALLOC(vn, print); 2111 PUFFS_MSG_ALLOC(vn, print);
2107 puffs_msg_setinfo(park_print, PUFFSOP_VN, 2112 puffs_msg_setinfo(park_print, PUFFSOP_VN,
2108 PUFFS_VN_PRINT, VPTOPNC(vp)); 2113 PUFFS_VN_PRINT, VPTOPNC(vp));
2109 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_print, vp->v_data, 2114 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_print, vp->v_data,
2110 NULL, error); 2115 NULL, error);
2111 PUFFS_MSG_RELEASE(print); 2116 PUFFS_MSG_RELEASE(print);
2112 } 2117 }
2113  2118
2114 return 0; 2119 return 0;
2115} 2120}
2116 2121
2117int 2122int
2118puffs_vnop_pathconf(void *v) 2123puffs_vnop_pathconf(void *v)
2119{ 2124{
2120 struct vop_pathconf_args /* { 2125 struct vop_pathconf_args /* {
2121 const struct vnodeop_desc *a_desc; 2126 const struct vnodeop_desc *a_desc;
2122 struct vnode *a_vp; 2127 struct vnode *a_vp;
2123 int a_name; 2128 int a_name;
2124 register_t *a_retval; 2129 register_t *a_retval;
2125 } */ *ap = v; 2130 } */ *ap = v;
2126 PUFFS_MSG_VARS(vn, pathconf); 2131 PUFFS_MSG_VARS(vn, pathconf);
2127 struct vnode *vp = ap->a_vp; 2132 struct vnode *vp = ap->a_vp;
2128 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 2133 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
2129 int error; 2134 int error;
2130 2135
2131 PUFFS_MSG_ALLOC(vn, pathconf); 2136 PUFFS_MSG_ALLOC(vn, pathconf);
2132 pathconf_msg->pvnr_name = ap->a_name; 2137 pathconf_msg->pvnr_name = ap->a_name;
2133 puffs_msg_setinfo(park_pathconf, PUFFSOP_VN, 2138 puffs_msg_setinfo(park_pathconf, PUFFSOP_VN,
2134 PUFFS_VN_PATHCONF, VPTOPNC(vp)); 2139 PUFFS_VN_PATHCONF, VPTOPNC(vp));
2135 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_pathconf, vp->v_data, NULL, error); 2140 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_pathconf, vp->v_data, NULL, error);
2136 error = checkerr(pmp, error, __func__); 2141 error = checkerr(pmp, error, __func__);
2137 if (!error) 2142 if (!error)
2138 *ap->a_retval = pathconf_msg->pvnr_retval; 2143 *ap->a_retval = pathconf_msg->pvnr_retval;
2139 PUFFS_MSG_RELEASE(pathconf); 2144 PUFFS_MSG_RELEASE(pathconf);
2140 2145
2141 return error; 2146 return error;
2142} 2147}
2143 2148
2144int 2149int
2145puffs_vnop_advlock(void *v) 2150puffs_vnop_advlock(void *v)
2146{ 2151{
2147 struct vop_advlock_args /* { 2152 struct vop_advlock_args /* {
2148 const struct vnodeop_desc *a_desc; 2153 const struct vnodeop_desc *a_desc;
2149 struct vnode *a_vp; 2154 struct vnode *a_vp;
2150 void *a_id; 2155 void *a_id;
2151 int a_op; 2156 int a_op;
2152 struct flock *a_fl; 2157 struct flock *a_fl;
2153 int a_flags; 2158 int a_flags;
2154 } */ *ap = v; 2159 } */ *ap = v;
2155 PUFFS_MSG_VARS(vn, advlock); 2160 PUFFS_MSG_VARS(vn, advlock);
2156 struct vnode *vp = ap->a_vp; 2161 struct vnode *vp = ap->a_vp;
2157 struct puffs_node *pn = VPTOPP(vp); 2162 struct puffs_node *pn = VPTOPP(vp);
2158 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 2163 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
2159 int error; 2164 int error;
2160 2165
2161 if (!EXISTSOP(pmp, ADVLOCK)) 2166 if (!EXISTSOP(pmp, ADVLOCK))
2162 return lf_advlock(ap, &pn->pn_lockf, vp->v_size);  2167 return lf_advlock(ap, &pn->pn_lockf, vp->v_size);
2163  2168
2164 PUFFS_MSG_ALLOC(vn, advlock); 2169 PUFFS_MSG_ALLOC(vn, advlock);
2165 (void)memcpy(&advlock_msg->pvnr_fl, ap->a_fl,  2170 (void)memcpy(&advlock_msg->pvnr_fl, ap->a_fl,
2166 sizeof(advlock_msg->pvnr_fl)); 2171 sizeof(advlock_msg->pvnr_fl));
2167 advlock_msg->pvnr_id = ap->a_id; 2172 advlock_msg->pvnr_id = ap->a_id;
2168 advlock_msg->pvnr_op = ap->a_op; 2173 advlock_msg->pvnr_op = ap->a_op;
2169 advlock_msg->pvnr_flags = ap->a_flags; 2174 advlock_msg->pvnr_flags = ap->a_flags;
2170 puffs_msg_setinfo(park_advlock, PUFFSOP_VN, 2175 puffs_msg_setinfo(park_advlock, PUFFSOP_VN,
2171 PUFFS_VN_ADVLOCK, VPTOPNC(vp)); 2176 PUFFS_VN_ADVLOCK, VPTOPNC(vp));
2172 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_advlock, vp->v_data, NULL, error); 2177 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_advlock, vp->v_data, NULL, error);
2173 error = checkerr(pmp, error, __func__); 2178 error = checkerr(pmp, error, __func__);
2174 PUFFS_MSG_RELEASE(advlock); 2179 PUFFS_MSG_RELEASE(advlock);
2175 2180
2176 return error; 2181 return error;
2177} 2182}
2178 2183
2179int 2184int
2180puffs_vnop_abortop(void *v) 2185puffs_vnop_abortop(void *v)
2181{ 2186{
2182 struct vop_abortop_args /* { 2187 struct vop_abortop_args /* {
2183 struct vnode *a_dvp; 2188 struct vnode *a_dvp;
2184 struct componentname *a_cnp; 2189 struct componentname *a_cnp;
2185 }; */ *ap = v; 2190 }; */ *ap = v;
2186 PUFFS_MSG_VARS(vn, abortop); 2191 PUFFS_MSG_VARS(vn, abortop);
2187 struct vnode *dvp = ap->a_dvp; 2192 struct vnode *dvp = ap->a_dvp;
2188 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount); 2193 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
2189 struct componentname *cnp = ap->a_cnp; 2194 struct componentname *cnp = ap->a_cnp;
2190 2195
2191 if (EXISTSOP(pmp, ABORTOP)) { 2196 if (EXISTSOP(pmp, ABORTOP)) {
2192 PUFFS_MSG_ALLOC(vn, abortop); 2197 PUFFS_MSG_ALLOC(vn, abortop);
2193 puffs_makecn(&abortop_msg->pvnr_cn, &abortop_msg->pvnr_cn_cred, 2198 puffs_makecn(&abortop_msg->pvnr_cn, &abortop_msg->pvnr_cn_cred,
2194 cnp, PUFFS_USE_FULLPNBUF(pmp)); 2199 cnp, PUFFS_USE_FULLPNBUF(pmp));
2195 puffs_msg_setfaf(park_abortop); 2200 puffs_msg_setfaf(park_abortop);
2196 puffs_msg_setinfo(park_abortop, PUFFSOP_VN, 2201 puffs_msg_setinfo(park_abortop, PUFFSOP_VN,
2197 PUFFS_VN_ABORTOP, VPTOPNC(dvp)); 2202 PUFFS_VN_ABORTOP, VPTOPNC(dvp));
2198 2203
2199 puffs_msg_enqueue(pmp, park_abortop); 2204 puffs_msg_enqueue(pmp, park_abortop);
2200 PUFFS_MSG_RELEASE(abortop); 2205 PUFFS_MSG_RELEASE(abortop);
2201 } 2206 }
2202 2207
2203 return genfs_abortop(v); 2208 return genfs_abortop(v);
2204} 2209}
2205 2210
2206#define BIOASYNC(bp) (bp->b_flags & B_ASYNC) 2211#define BIOASYNC(bp) (bp->b_flags & B_ASYNC)
2207 2212
2208/* 2213/*
2209 * This maps itself to PUFFS_VN_READ/WRITE for data transfer. 2214 * This maps itself to PUFFS_VN_READ/WRITE for data transfer.
2210 */ 2215 */
2211int 2216int
2212puffs_vnop_strategy(void *v) 2217puffs_vnop_strategy(void *v)
2213{ 2218{
2214 struct vop_strategy_args /* { 2219 struct vop_strategy_args /* {
2215 const struct vnodeop_desc *a_desc; 2220 const struct vnodeop_desc *a_desc;
2216 struct vnode *a_vp; 2221 struct vnode *a_vp;
2217 struct buf *a_bp; 2222 struct buf *a_bp;
2218 } */ *ap = v; 2223 } */ *ap = v;
2219 PUFFS_MSG_VARS(vn, rw); 2224 PUFFS_MSG_VARS(vn, rw);
2220 struct vnode *vp = ap->a_vp; 2225 struct vnode *vp = ap->a_vp;
2221 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); 2226 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
2222 struct puffs_node *pn; 2227 struct puffs_node *pn;
2223 struct buf *bp; 2228 struct buf *bp;
2224 size_t argsize; 2229 size_t argsize;
2225 size_t tomove, moved; 2230 size_t tomove, moved;
2226 int error, dofaf, cansleep, dobiodone; 2231 int error, dofaf, cansleep, dobiodone;
2227 2232
2228 pmp = MPTOPUFFSMP(vp->v_mount); 2233 pmp = MPTOPUFFSMP(vp->v_mount);
2229 bp = ap->a_bp; 2234 bp = ap->a_bp;
2230 error = 0; 2235 error = 0;
2231 dofaf = 0; 2236 dofaf = 0;
2232 cansleep = 0; 2237 cansleep = 0;
2233 pn = VPTOPP(vp); 2238 pn = VPTOPP(vp);
2234 park_rw = NULL; /* explicit */ 2239 park_rw = NULL; /* explicit */
2235 dobiodone = 1; 2240 dobiodone = 1;
2236 2241
2237 if ((BUF_ISREAD(bp) && !EXISTSOP(pmp, READ)) 2242 if ((BUF_ISREAD(bp) && !EXISTSOP(pmp, READ))
2238 || (BUF_ISWRITE(bp) && !EXISTSOP(pmp, WRITE))) 2243 || (BUF_ISWRITE(bp) && !EXISTSOP(pmp, WRITE)))
2239 ERROUT(EOPNOTSUPP); 2244 ERROUT(EOPNOTSUPP);
2240 2245
2241 /* 2246 /*
2242 * Short-circuit optimization: don't flush buffer in between 2247 * Short-circuit optimization: don't flush buffer in between
2243 * VOP_INACTIVE and VOP_RECLAIM in case the node has no references. 2248 * VOP_INACTIVE and VOP_RECLAIM in case the node has no references.
2244 */ 2249 */
2245 if (pn->pn_stat & PNODE_DYING) { 2250 if (pn->pn_stat & PNODE_DYING) {
2246 KASSERT(BUF_ISWRITE(bp)); 2251 KASSERT(BUF_ISWRITE(bp));
2247 bp->b_resid = 0; 2252 bp->b_resid = 0;
2248 goto out; 2253 goto out;
2249 } 2254 }
2250 2255
2251#ifdef DIAGNOSTIC 2256#ifdef DIAGNOSTIC
2252 if (bp->b_bcount > pmp->pmp_msg_maxsize - PUFFS_MSGSTRUCT_MAX) 2257 if (bp->b_bcount > pmp->pmp_msg_maxsize - PUFFS_MSGSTRUCT_MAX)
2253 panic("puffs_strategy: wildly inappropriate buf bcount %d", 2258 panic("puffs_strategy: wildly inappropriate buf bcount %d",
2254 bp->b_bcount); 2259 bp->b_bcount);
2255#endif 2260#endif
2256 2261
2257 /* 2262 /*
2258 * See explanation for the necessity of a FAF in puffs_fsync. 2263 * See explanation for the necessity of a FAF in puffs_fsync.
2259 * 2264 *
2260 * Also, do FAF in case we're suspending. 2265 * Also, do FAF in case we're suspending.
2261 * See puffs_vfsops.c:pageflush() 2266 * See puffs_vfsops.c:pageflush()
2262 */ 2267 */
2263 if (BUF_ISWRITE(bp)) { 2268 if (BUF_ISWRITE(bp)) {
2264 mutex_enter(vp->v_interlock); 2269 mutex_enter(vp->v_interlock);
2265 if (vp->v_iflag & VI_XLOCK) 2270 if (vp->v_iflag & VI_XLOCK)
2266 dofaf = 1; 2271 dofaf = 1;
2267 if (pn->pn_stat & PNODE_FAF) 2272 if (pn->pn_stat & PNODE_FAF)
2268 dofaf = 1; 2273 dofaf = 1;
2269 mutex_exit(vp->v_interlock); 2274 mutex_exit(vp->v_interlock);
2270 } 2275 }
2271 2276
2272 cansleep = (curlwp == uvm.pagedaemon_lwp || dofaf) ? 0 : 1; 2277 cansleep = (curlwp == uvm.pagedaemon_lwp || dofaf) ? 0 : 1;
2273 2278
2274 KASSERT(curlwp != uvm.pagedaemon_lwp || dofaf || BIOASYNC(bp)); 2279 KASSERT(curlwp != uvm.pagedaemon_lwp || dofaf || BIOASYNC(bp));
2275 2280
2276 /* allocate transport structure */ 2281 /* allocate transport structure */
2277 tomove = PUFFS_TOMOVE(bp->b_bcount, pmp); 2282 tomove = PUFFS_TOMOVE(bp->b_bcount, pmp);
2278 argsize = sizeof(struct puffs_vnmsg_rw); 2283 argsize = sizeof(struct puffs_vnmsg_rw);
2279 error = puffs_msgmem_alloc(argsize + tomove, &park_rw, 2284 error = puffs_msgmem_alloc(argsize + tomove, &park_rw,
2280 (void *)&rw_msg, cansleep); 2285 (void *)&rw_msg, cansleep);
2281 if (error) 2286 if (error)
2282 goto out; 2287 goto out;
2283 RWARGS(rw_msg, 0, tomove, bp->b_blkno << DEV_BSHIFT, FSCRED); 2288 RWARGS(rw_msg, 0, tomove, bp->b_blkno << DEV_BSHIFT, FSCRED);
2284 2289
2285 /* 2x2 cases: read/write, faf/nofaf */ 2290 /* 2x2 cases: read/write, faf/nofaf */
2286 if (BUF_ISREAD(bp)) { 2291 if (BUF_ISREAD(bp)) {
2287 puffs_msg_setinfo(park_rw, PUFFSOP_VN, 2292 puffs_msg_setinfo(park_rw, PUFFSOP_VN,
2288 PUFFS_VN_READ, VPTOPNC(vp)); 2293 PUFFS_VN_READ, VPTOPNC(vp));
2289 puffs_msg_setdelta(park_rw, tomove); 2294 puffs_msg_setdelta(park_rw, tomove);
2290 if (BIOASYNC(bp)) { 2295 if (BIOASYNC(bp)) {
2291 puffs_msg_setcall(park_rw, 2296 puffs_msg_setcall(park_rw,
2292 puffs_parkdone_asyncbioread, bp); 2297 puffs_parkdone_asyncbioread, bp);
2293 puffs_msg_enqueue(pmp, park_rw); 2298 puffs_msg_enqueue(pmp, park_rw);
2294 dobiodone = 0; 2299 dobiodone = 0;
2295 } else { 2300 } else {
2296 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rw, vp->v_data, 2301 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rw, vp->v_data,
2297 NULL, error); 2302 NULL, error);
2298 error = checkerr(pmp, error, __func__); 2303 error = checkerr(pmp, error, __func__);
2299 if (error) 2304 if (error)
2300 goto out; 2305 goto out;
2301 2306
2302 if (rw_msg->pvnr_resid > tomove) { 2307 if (rw_msg->pvnr_resid > tomove) {
2303 puffs_senderr(pmp, PUFFS_ERR_READ, 2308 puffs_senderr(pmp, PUFFS_ERR_READ,
2304 E2BIG, "resid grew", VPTOPNC(vp)); 2309 E2BIG, "resid grew", VPTOPNC(vp));
2305 ERROUT(EPROTO); 2310 ERROUT(EPROTO);
2306 } 2311 }
2307 2312
2308 moved = tomove - rw_msg->pvnr_resid; 2313 moved = tomove - rw_msg->pvnr_resid;
2309 2314
2310 (void)memcpy(bp->b_data, rw_msg->pvnr_data, moved); 2315 (void)memcpy(bp->b_data, rw_msg->pvnr_data, moved);
2311 bp->b_resid = bp->b_bcount - moved; 2316 bp->b_resid = bp->b_bcount - moved;
2312 } 2317 }
2313 } else { 2318 } else {
2314 puffs_msg_setinfo(park_rw, PUFFSOP_VN, 2319 puffs_msg_setinfo(park_rw, PUFFSOP_VN,
2315 PUFFS_VN_WRITE, VPTOPNC(vp)); 2320 PUFFS_VN_WRITE, VPTOPNC(vp));
2316 /* 2321 /*
2317 * make pages read-only before we write them if we want 2322 * make pages read-only before we write them if we want
2318 * write caching info 2323 * write caching info
2319 */ 2324 */
2320 if (PUFFS_WCACHEINFO(pmp)) { 2325 if (PUFFS_WCACHEINFO(pmp)) {
2321 struct uvm_object *uobj = &vp->v_uobj; 2326 struct uvm_object *uobj = &vp->v_uobj;
2322 int npages = (bp->b_bcount + PAGE_SIZE-1) >> PAGE_SHIFT; 2327 int npages = (bp->b_bcount + PAGE_SIZE-1) >> PAGE_SHIFT;
2323 struct vm_page *vmp; 2328 struct vm_page *vmp;
2324 int i; 2329 int i;
2325 2330
2326 for (i = 0; i < npages; i++) { 2331 for (i = 0; i < npages; i++) {
2327 vmp= uvm_pageratop((vaddr_t)bp->b_data 2332 vmp= uvm_pageratop((vaddr_t)bp->b_data
2328 + (i << PAGE_SHIFT)); 2333 + (i << PAGE_SHIFT));
2329 DPRINTF(("puffs_strategy: write-protecting " 2334 DPRINTF(("puffs_strategy: write-protecting "
2330 "vp %p page %p, offset %" PRId64"\n", 2335 "vp %p page %p, offset %" PRId64"\n",
2331 vp, vmp, vmp->offset)); 2336 vp, vmp, vmp->offset));
2332 mutex_enter(uobj->vmobjlock); 2337 mutex_enter(uobj->vmobjlock);
2333 vmp->flags |= PG_RDONLY; 2338 vmp->flags |= PG_RDONLY;
2334 pmap_page_protect(vmp, VM_PROT_READ); 2339 pmap_page_protect(vmp, VM_PROT_READ);
2335 mutex_exit(uobj->vmobjlock); 2340 mutex_exit(uobj->vmobjlock);
2336 } 2341 }
2337 } 2342 }
2338 2343
2339 (void)memcpy(&rw_msg->pvnr_data, bp->b_data, tomove); 2344 (void)memcpy(&rw_msg->pvnr_data, bp->b_data, tomove);
2340 if (dofaf) { 2345 if (dofaf) {
2341 puffs_msg_setfaf(park_rw); 2346 puffs_msg_setfaf(park_rw);
2342 } else if (BIOASYNC(bp)) { 2347 } else if (BIOASYNC(bp)) {
2343 puffs_msg_setcall(park_rw, 2348 puffs_msg_setcall(park_rw,
2344 puffs_parkdone_asyncbiowrite, bp); 2349 puffs_parkdone_asyncbiowrite, bp);
2345 dobiodone = 0; 2350 dobiodone = 0;
2346 } 2351 }
2347 2352
2348 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rw, vp->v_data, NULL, error); 2353 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rw, vp->v_data, NULL, error);
2349 2354
2350 if (dobiodone == 0) 2355 if (dobiodone == 0)
2351 goto out; 2356 goto out;
2352 2357
2353 /* 2358 /*
2354 * XXXXXXXX: wrong, but kernel can't survive strategy 2359 * XXXXXXXX: wrong, but kernel can't survive strategy
2355 * failure currently. Here, have one more X: X. 2360 * failure currently. Here, have one more X: X.
2356 */ 2361 */
2357 if (error != ENOMEM) 2362 if (error != ENOMEM)
2358 error = 0; 2363 error = 0;
2359 2364
2360 error = checkerr(pmp, error, __func__); 2365 error = checkerr(pmp, error, __func__);
2361 if (error) 2366 if (error)
2362 goto out; 2367 goto out;