Annotation of src/sys/fs/puffs/puffs_vnops.c, Revision 1.196
1.196 ! manu 1: /* $NetBSD: puffs_vnops.c,v 1.195 2014/10/31 13:51:33 manu Exp $ */
1.1 pooka 2:
3: /*
1.64 pooka 4: * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
1.1 pooka 5: *
6: * Development of this software was supported by the
7: * Google Summer of Code program and the Ulla Tuominen Foundation.
8: * The Google SoC project was mentored by Bill Studenmund.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
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
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
32: #include <sys/cdefs.h>
1.196 ! manu 33: __KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.195 2014/10/31 13:51:33 manu Exp $");
1.1 pooka 34:
35: #include <sys/param.h>
1.130 pooka 36: #include <sys/buf.h>
1.150 kefren 37: #include <sys/lockf.h>
1.41 pooka 38: #include <sys/malloc.h>
1.1 pooka 39: #include <sys/mount.h>
40: #include <sys/namei.h>
1.41 pooka 41: #include <sys/vnode.h>
1.87 ad 42: #include <sys/proc.h>
1.165 manu 43: #include <sys/kernel.h> /* For hz, hardclock_ticks */
1.87 ad 44:
1.45 pooka 45: #include <uvm/uvm.h>
1.1 pooka 46:
47: #include <fs/puffs/puffs_msgif.h>
48: #include <fs/puffs/puffs_sys.h>
49:
1.6 pooka 50: #include <miscfs/fifofs/fifo.h>
1.1 pooka 51: #include <miscfs/genfs/genfs.h>
1.5 pooka 52: #include <miscfs/specfs/specdev.h>
53:
1.123 pooka 54: int puffs_vnop_lookup(void *);
55: int puffs_vnop_create(void *);
56: int puffs_vnop_access(void *);
57: int puffs_vnop_mknod(void *);
58: int puffs_vnop_open(void *);
59: int puffs_vnop_close(void *);
60: int puffs_vnop_getattr(void *);
61: int puffs_vnop_setattr(void *);
62: int puffs_vnop_reclaim(void *);
63: int puffs_vnop_readdir(void *);
64: int puffs_vnop_poll(void *);
65: int puffs_vnop_fsync(void *);
66: int puffs_vnop_seek(void *);
67: int puffs_vnop_remove(void *);
68: int puffs_vnop_mkdir(void *);
69: int puffs_vnop_rmdir(void *);
70: int puffs_vnop_link(void *);
71: int puffs_vnop_readlink(void *);
72: int puffs_vnop_symlink(void *);
73: int puffs_vnop_rename(void *);
74: int puffs_vnop_read(void *);
75: int puffs_vnop_write(void *);
1.196 ! manu 76: int puffs_vnop_fallocate(void *);
! 77: int puffs_vnop_fdiscard(void *);
1.123 pooka 78: int puffs_vnop_fcntl(void *);
79: int puffs_vnop_ioctl(void *);
80: int puffs_vnop_inactive(void *);
81: int puffs_vnop_print(void *);
82: int puffs_vnop_pathconf(void *);
83: int puffs_vnop_advlock(void *);
84: int puffs_vnop_strategy(void *);
85: int puffs_vnop_bmap(void *);
86: int puffs_vnop_mmap(void *);
87: int puffs_vnop_getpages(void *);
1.136 pooka 88: int puffs_vnop_abortop(void *);
1.145 pooka 89: int puffs_vnop_getextattr(void *);
90: int puffs_vnop_setextattr(void *);
91: int puffs_vnop_listextattr(void *);
92: int puffs_vnop_deleteextattr(void *);
1.123 pooka 93:
94: int puffs_vnop_spec_read(void *);
95: int puffs_vnop_spec_write(void *);
96: int puffs_vnop_fifo_read(void *);
97: int puffs_vnop_fifo_write(void *);
1.26 pooka 98:
1.123 pooka 99: int puffs_vnop_checkop(void *);
1.17 pooka 100:
1.138 pooka 101: #define puffs_vnop_lock genfs_lock
102: #define puffs_vnop_unlock genfs_unlock
103: #define puffs_vnop_islocked genfs_islocked
1.1 pooka 104:
105: int (**puffs_vnodeop_p)(void *);
106: const struct vnodeopv_entry_desc puffs_vnodeop_entries[] = {
107: { &vop_default_desc, vn_default_error },
1.123 pooka 108: { &vop_lookup_desc, puffs_vnop_lookup }, /* REAL lookup */
109: { &vop_create_desc, puffs_vnop_checkop }, /* create */
110: { &vop_mknod_desc, puffs_vnop_checkop }, /* mknod */
111: { &vop_open_desc, puffs_vnop_open }, /* REAL open */
112: { &vop_close_desc, puffs_vnop_checkop }, /* close */
113: { &vop_access_desc, puffs_vnop_access }, /* REAL access */
114: { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
115: { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
116: { &vop_read_desc, puffs_vnop_checkop }, /* read */
117: { &vop_write_desc, puffs_vnop_checkop }, /* write */
1.196 ! manu 118: { &vop_fallocate_desc, puffs_vnop_fallocate }, /* fallocate */
! 119: { &vop_fdiscard_desc, puffs_vnop_fdiscard }, /* fdiscard */
1.123 pooka 120: { &vop_fsync_desc, puffs_vnop_fsync }, /* REAL fsync */
121: { &vop_seek_desc, puffs_vnop_checkop }, /* seek */
122: { &vop_remove_desc, puffs_vnop_checkop }, /* remove */
123: { &vop_link_desc, puffs_vnop_checkop }, /* link */
124: { &vop_rename_desc, puffs_vnop_checkop }, /* rename */
125: { &vop_mkdir_desc, puffs_vnop_checkop }, /* mkdir */
126: { &vop_rmdir_desc, puffs_vnop_checkop }, /* rmdir */
127: { &vop_symlink_desc, puffs_vnop_checkop }, /* symlink */
128: { &vop_readdir_desc, puffs_vnop_checkop }, /* readdir */
129: { &vop_readlink_desc, puffs_vnop_checkop }, /* readlink */
130: { &vop_getpages_desc, puffs_vnop_checkop }, /* getpages */
1.47 pooka 131: { &vop_putpages_desc, genfs_putpages }, /* REAL putpages */
1.123 pooka 132: { &vop_pathconf_desc, puffs_vnop_checkop }, /* pathconf */
1.151 manu 133: { &vop_advlock_desc, puffs_vnop_advlock }, /* advlock */
1.123 pooka 134: { &vop_strategy_desc, puffs_vnop_strategy }, /* REAL strategy */
1.34 pooka 135: { &vop_revoke_desc, genfs_revoke }, /* REAL revoke */
1.136 pooka 136: { &vop_abortop_desc, puffs_vnop_abortop }, /* REAL abortop */
1.123 pooka 137: { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */
138: { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */
139: { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */
140: { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */
141: { &vop_bmap_desc, puffs_vnop_bmap }, /* REAL bmap */
142: { &vop_print_desc, puffs_vnop_print }, /* REAL print */
143: { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */
1.17 pooka 144: { &vop_bwrite_desc, genfs_nullop }, /* REAL bwrite */
1.123 pooka 145: { &vop_mmap_desc, puffs_vnop_mmap }, /* REAL mmap */
146: { &vop_poll_desc, puffs_vnop_poll }, /* REAL poll */
1.145 pooka 147: { &vop_getextattr_desc, puffs_vnop_getextattr }, /* getextattr */
148: { &vop_setextattr_desc, puffs_vnop_setextattr }, /* setextattr */
149: { &vop_listextattr_desc, puffs_vnop_listextattr }, /* listextattr */
150: { &vop_deleteextattr_desc, puffs_vnop_deleteextattr },/* deleteextattr */
151: #if 0
152: { &vop_openextattr_desc, puffs_vnop_checkop }, /* openextattr */
153: { &vop_closeextattr_desc, puffs_vnop_checkop }, /* closeextattr */
154: #endif
1.69 pooka 155: { &vop_kqfilter_desc, genfs_eopnotsupp }, /* kqfilter XXX */
1.1 pooka 156: { NULL, NULL }
157: };
158: const struct vnodeopv_desc puffs_vnodeop_opv_desc =
159: { &puffs_vnodeop_p, puffs_vnodeop_entries };
160:
1.5 pooka 161:
162: int (**puffs_specop_p)(void *);
163: const struct vnodeopv_entry_desc puffs_specop_entries[] = {
164: { &vop_default_desc, vn_default_error },
165: { &vop_lookup_desc, spec_lookup }, /* lookup, ENOTDIR */
1.6 pooka 166: { &vop_create_desc, spec_create }, /* genfs_badop */
167: { &vop_mknod_desc, spec_mknod }, /* genfs_badop */
168: { &vop_open_desc, spec_open }, /* spec_open */
1.26 pooka 169: { &vop_close_desc, spec_close }, /* spec_close */
1.135 pooka 170: { &vop_access_desc, puffs_vnop_checkop }, /* access */
171: { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
172: { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
173: { &vop_read_desc, puffs_vnop_spec_read }, /* update, read */
174: { &vop_write_desc, puffs_vnop_spec_write }, /* update, write */
1.182 dholland 175: { &vop_fallocate_desc, spec_fallocate }, /* fallocate */
176: { &vop_fdiscard_desc, spec_fdiscard }, /* fdiscard */
1.5 pooka 177: { &vop_ioctl_desc, spec_ioctl }, /* spec_ioctl */
178: { &vop_fcntl_desc, genfs_fcntl }, /* dummy */
179: { &vop_poll_desc, spec_poll }, /* spec_poll */
180: { &vop_kqfilter_desc, spec_kqfilter }, /* spec_kqfilter */
181: { &vop_revoke_desc, spec_revoke }, /* genfs_revoke */
1.69 pooka 182: { &vop_mmap_desc, spec_mmap }, /* spec_mmap */
1.7 pooka 183: { &vop_fsync_desc, spec_fsync }, /* vflushbuf */
1.5 pooka 184: { &vop_seek_desc, spec_seek }, /* genfs_nullop */
185: { &vop_remove_desc, spec_remove }, /* genfs_badop */
186: { &vop_link_desc, spec_link }, /* genfs_badop */
187: { &vop_rename_desc, spec_rename }, /* genfs_badop */
188: { &vop_mkdir_desc, spec_mkdir }, /* genfs_badop */
189: { &vop_rmdir_desc, spec_rmdir }, /* genfs_badop */
190: { &vop_symlink_desc, spec_symlink }, /* genfs_badop */
191: { &vop_readdir_desc, spec_readdir }, /* genfs_badop */
192: { &vop_readlink_desc, spec_readlink }, /* genfs_badop */
193: { &vop_abortop_desc, spec_abortop }, /* genfs_badop */
1.135 pooka 194: { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */
195: { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */
196: { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */
197: { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */
1.5 pooka 198: { &vop_bmap_desc, spec_bmap }, /* dummy */
199: { &vop_strategy_desc, spec_strategy }, /* dev strategy */
1.123 pooka 200: { &vop_print_desc, puffs_vnop_print }, /* REAL print */
1.135 pooka 201: { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */
1.5 pooka 202: { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
203: { &vop_advlock_desc, spec_advlock }, /* lf_advlock */
204: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
205: { &vop_getpages_desc, spec_getpages }, /* genfs_getpages */
206: { &vop_putpages_desc, spec_putpages }, /* genfs_putpages */
1.145 pooka 207: { &vop_getextattr_desc, puffs_vnop_checkop }, /* getextattr */
208: { &vop_setextattr_desc, puffs_vnop_checkop }, /* setextattr */
209: { &vop_listextattr_desc, puffs_vnop_checkop }, /* listextattr */
210: { &vop_deleteextattr_desc, puffs_vnop_checkop },/* deleteextattr */
1.5 pooka 211: #if 0
212: { &vop_openextattr_desc, _openextattr }, /* openextattr */
213: { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */
214: #endif
215: { NULL, NULL }
216: };
217: const struct vnodeopv_desc puffs_specop_opv_desc =
218: { &puffs_specop_p, puffs_specop_entries };
219:
1.23 pooka 220:
1.6 pooka 221: int (**puffs_fifoop_p)(void *);
222: const struct vnodeopv_entry_desc puffs_fifoop_entries[] = {
223: { &vop_default_desc, vn_default_error },
1.144 pooka 224: { &vop_lookup_desc, vn_fifo_bypass }, /* lookup, ENOTDIR */
225: { &vop_create_desc, vn_fifo_bypass }, /* genfs_badop */
226: { &vop_mknod_desc, vn_fifo_bypass }, /* genfs_badop */
227: { &vop_open_desc, vn_fifo_bypass }, /* open */
228: { &vop_close_desc, vn_fifo_bypass }, /* close */
1.135 pooka 229: { &vop_access_desc, puffs_vnop_checkop }, /* access */
230: { &vop_getattr_desc, puffs_vnop_checkop }, /* getattr */
231: { &vop_setattr_desc, puffs_vnop_checkop }, /* setattr */
232: { &vop_read_desc, puffs_vnop_fifo_read }, /* read, update */
233: { &vop_write_desc, puffs_vnop_fifo_write }, /* write, update */
1.182 dholland 234: { &vop_fallocate_desc, vn_fifo_bypass }, /* fallocate */
235: { &vop_fdiscard_desc, vn_fifo_bypass }, /* fdiscard */
1.144 pooka 236: { &vop_ioctl_desc, vn_fifo_bypass }, /* ioctl */
1.6 pooka 237: { &vop_fcntl_desc, genfs_fcntl }, /* dummy */
1.144 pooka 238: { &vop_poll_desc, vn_fifo_bypass }, /* poll */
239: { &vop_kqfilter_desc, vn_fifo_bypass }, /* kqfilter */
240: { &vop_revoke_desc, vn_fifo_bypass }, /* genfs_revoke */
241: { &vop_mmap_desc, vn_fifo_bypass }, /* genfs_badop */
242: { &vop_fsync_desc, vn_fifo_bypass }, /* genfs_nullop*/
243: { &vop_seek_desc, vn_fifo_bypass }, /* genfs_badop */
244: { &vop_remove_desc, vn_fifo_bypass }, /* genfs_badop */
245: { &vop_link_desc, vn_fifo_bypass }, /* genfs_badop */
246: { &vop_rename_desc, vn_fifo_bypass }, /* genfs_badop */
247: { &vop_mkdir_desc, vn_fifo_bypass }, /* genfs_badop */
248: { &vop_rmdir_desc, vn_fifo_bypass }, /* genfs_badop */
249: { &vop_symlink_desc, vn_fifo_bypass }, /* genfs_badop */
250: { &vop_readdir_desc, vn_fifo_bypass }, /* genfs_badop */
251: { &vop_readlink_desc, vn_fifo_bypass }, /* genfs_badop */
252: { &vop_abortop_desc, vn_fifo_bypass }, /* genfs_badop */
1.135 pooka 253: { &vop_inactive_desc, puffs_vnop_inactive }, /* REAL inactive */
254: { &vop_reclaim_desc, puffs_vnop_reclaim }, /* REAL reclaim */
255: { &vop_lock_desc, puffs_vnop_lock }, /* REAL lock */
256: { &vop_unlock_desc, puffs_vnop_unlock }, /* REAL unlock */
1.144 pooka 257: { &vop_bmap_desc, vn_fifo_bypass }, /* dummy */
258: { &vop_strategy_desc, vn_fifo_bypass }, /* genfs_badop */
1.123 pooka 259: { &vop_print_desc, puffs_vnop_print }, /* REAL print */
1.135 pooka 260: { &vop_islocked_desc, puffs_vnop_islocked }, /* REAL islocked */
1.144 pooka 261: { &vop_pathconf_desc, vn_fifo_bypass }, /* pathconf */
262: { &vop_advlock_desc, vn_fifo_bypass }, /* genfs_einval */
1.6 pooka 263: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
1.144 pooka 264: { &vop_putpages_desc, vn_fifo_bypass }, /* genfs_null_putpages*/
1.6 pooka 265: #if 0
266: { &vop_openextattr_desc, _openextattr }, /* openextattr */
267: { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */
268: #endif
1.145 pooka 269: { &vop_getextattr_desc, puffs_vnop_checkop }, /* getextattr */
270: { &vop_setextattr_desc, puffs_vnop_checkop }, /* setextattr */
271: { &vop_listextattr_desc, puffs_vnop_checkop }, /* listextattr */
272: { &vop_deleteextattr_desc, puffs_vnop_checkop }, /* deleteextattr */
1.6 pooka 273: { NULL, NULL }
274: };
275: const struct vnodeopv_desc puffs_fifoop_opv_desc =
276: { &puffs_fifoop_p, puffs_fifoop_entries };
277:
278:
1.17 pooka 279: /* "real" vnode operations */
280: int (**puffs_msgop_p)(void *);
281: const struct vnodeopv_entry_desc puffs_msgop_entries[] = {
282: { &vop_default_desc, vn_default_error },
1.135 pooka 283: { &vop_create_desc, puffs_vnop_create }, /* create */
1.123 pooka 284: { &vop_mknod_desc, puffs_vnop_mknod }, /* mknod */
1.135 pooka 285: { &vop_open_desc, puffs_vnop_open }, /* open */
1.123 pooka 286: { &vop_close_desc, puffs_vnop_close }, /* close */
1.135 pooka 287: { &vop_access_desc, puffs_vnop_access }, /* access */
288: { &vop_getattr_desc, puffs_vnop_getattr }, /* getattr */
289: { &vop_setattr_desc, puffs_vnop_setattr }, /* setattr */
290: { &vop_read_desc, puffs_vnop_read }, /* read */
1.123 pooka 291: { &vop_write_desc, puffs_vnop_write }, /* write */
1.135 pooka 292: { &vop_seek_desc, puffs_vnop_seek }, /* seek */
293: { &vop_remove_desc, puffs_vnop_remove }, /* remove */
294: { &vop_link_desc, puffs_vnop_link }, /* link */
295: { &vop_rename_desc, puffs_vnop_rename }, /* rename */
1.123 pooka 296: { &vop_mkdir_desc, puffs_vnop_mkdir }, /* mkdir */
297: { &vop_rmdir_desc, puffs_vnop_rmdir }, /* rmdir */
1.135 pooka 298: { &vop_symlink_desc, puffs_vnop_symlink }, /* symlink */
299: { &vop_readdir_desc, puffs_vnop_readdir }, /* readdir */
300: { &vop_readlink_desc, puffs_vnop_readlink }, /* readlink */
1.123 pooka 301: { &vop_print_desc, puffs_vnop_print }, /* print */
1.135 pooka 302: { &vop_islocked_desc, puffs_vnop_islocked }, /* islocked */
303: { &vop_pathconf_desc, puffs_vnop_pathconf }, /* pathconf */
304: { &vop_getpages_desc, puffs_vnop_getpages }, /* getpages */
1.17 pooka 305: { NULL, NULL }
306: };
307: const struct vnodeopv_desc puffs_msgop_opv_desc =
308: { &puffs_msgop_p, puffs_msgop_entries };
309:
1.166 manu 310: /*
311: * for dosetattr / update_va
312: */
313: #define SETATTR_CHSIZE 0x01
314: #define SETATTR_ASYNC 0x02
1.5 pooka 315:
1.79 pooka 316: #define ERROUT(err) \
317: do { \
318: error = err; \
319: goto out; \
320: } while (/*CONSTCOND*/0)
1.1 pooka 321:
1.17 pooka 322: /*
323: * This is a generic vnode operation handler. It checks if the necessary
324: * operations for the called vnode operation are implemented by userspace
325: * and either returns a dummy return value or proceeds to call the real
326: * vnode operation from puffs_msgop_v.
327: *
328: * XXX: this should described elsewhere and autogenerated, the complexity
329: * of the vnode operations vectors and their interrelationships is also
330: * getting a bit out of hand. Another problem is that we need this same
331: * information in the fs server code, so keeping the two in sync manually
332: * is not a viable (long term) plan.
333: */
334:
335: /* not supported, handle locking protocol */
336: #define CHECKOP_NOTSUPP(op) \
337: case VOP_##op##_DESCOFFSET: \
338: if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0) \
339: return genfs_eopnotsupp(v); \
340: break
341:
342: /* always succeed, no locking */
343: #define CHECKOP_SUCCESS(op) \
344: case VOP_##op##_DESCOFFSET: \
345: if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0) \
346: return 0; \
347: break
348:
349: int
1.123 pooka 350: puffs_vnop_checkop(void *v)
1.17 pooka 351: {
352: struct vop_generic_args /* {
353: struct vnodeop_desc *a_desc;
354: spooky mystery contents;
355: } */ *ap = v;
356: struct vnodeop_desc *desc = ap->a_desc;
357: struct puffs_mount *pmp;
358: struct vnode *vp;
1.75 pooka 359: int offset, rv;
1.17 pooka 360:
361: offset = ap->a_desc->vdesc_vp_offsets[0];
362: #ifdef DIAGNOSTIC
363: if (offset == VDESC_NO_OFFSET)
364: panic("puffs_checkop: no vnode, why did you call me?");
365: #endif
366: vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap);
367: pmp = MPTOPUFFSMP(vp->v_mount);
368:
1.75 pooka 369: DPRINTF_VERBOSE(("checkop call %s (%d), vp %p\n",
370: ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset, vp));
371:
1.66 pooka 372: if (!ALLOPS(pmp)) {
1.17 pooka 373: switch (desc->vdesc_offset) {
374: CHECKOP_NOTSUPP(CREATE);
375: CHECKOP_NOTSUPP(MKNOD);
376: CHECKOP_NOTSUPP(GETATTR);
377: CHECKOP_NOTSUPP(SETATTR);
378: CHECKOP_NOTSUPP(READ);
379: CHECKOP_NOTSUPP(WRITE);
380: CHECKOP_NOTSUPP(FCNTL);
381: CHECKOP_NOTSUPP(IOCTL);
382: CHECKOP_NOTSUPP(REMOVE);
383: CHECKOP_NOTSUPP(LINK);
384: CHECKOP_NOTSUPP(RENAME);
385: CHECKOP_NOTSUPP(MKDIR);
386: CHECKOP_NOTSUPP(RMDIR);
387: CHECKOP_NOTSUPP(SYMLINK);
388: CHECKOP_NOTSUPP(READDIR);
389: CHECKOP_NOTSUPP(READLINK);
390: CHECKOP_NOTSUPP(PRINT);
391: CHECKOP_NOTSUPP(PATHCONF);
1.145 pooka 392: CHECKOP_NOTSUPP(GETEXTATTR);
393: CHECKOP_NOTSUPP(SETEXTATTR);
394: CHECKOP_NOTSUPP(LISTEXTATTR);
395: CHECKOP_NOTSUPP(DELETEEXTATTR);
1.17 pooka 396:
1.47 pooka 397: CHECKOP_SUCCESS(ACCESS);
1.17 pooka 398: CHECKOP_SUCCESS(CLOSE);
399: CHECKOP_SUCCESS(SEEK);
400:
401: case VOP_GETPAGES_DESCOFFSET:
402: if (!EXISTSOP(pmp, READ))
403: return genfs_eopnotsupp(v);
404: break;
405:
406: default:
407: panic("puffs_checkop: unhandled vnop %d",
408: desc->vdesc_offset);
409: }
410: }
411:
1.75 pooka 412: rv = VOCALL(puffs_msgop_p, ap->a_desc->vdesc_offset, v);
413:
414: DPRINTF_VERBOSE(("checkop return %s (%d), vp %p: %d\n",
415: ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset, vp, rv));
416:
417: return rv;
1.17 pooka 418: }
419:
1.127 pooka 420: static int callremove(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t,
1.103 pooka 421: struct componentname *);
1.127 pooka 422: static int callrmdir(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t,
1.103 pooka 423: struct componentname *);
1.127 pooka 424: static void callinactive(struct puffs_mount *, puffs_cookie_t, int);
1.167 manu 425: static void callreclaim(struct puffs_mount *, puffs_cookie_t, int);
1.141 pooka 426: static int flushvncache(struct vnode *, off_t, off_t, bool);
1.165 manu 427: static void update_va(struct vnode *, struct vattr *, struct vattr *,
1.166 manu 428: struct timespec *, struct timespec *, int);
1.174 manu 429: static void update_parent(struct vnode *, struct vnode *);
1.141 pooka 430:
1.103 pooka 431:
432: #define PUFFS_ABORT_LOOKUP 1
433: #define PUFFS_ABORT_CREATE 2
434: #define PUFFS_ABORT_MKNOD 3
435: #define PUFFS_ABORT_MKDIR 4
436: #define PUFFS_ABORT_SYMLINK 5
437:
438: /*
439: * Press the pani^Wabort button! Kernel resource allocation failed.
440: */
441: static void
442: puffs_abortbutton(struct puffs_mount *pmp, int what,
1.127 pooka 443: puffs_cookie_t dck, puffs_cookie_t ck, struct componentname *cnp)
1.103 pooka 444: {
445:
446: switch (what) {
447: case PUFFS_ABORT_CREATE:
448: case PUFFS_ABORT_MKNOD:
449: case PUFFS_ABORT_SYMLINK:
1.127 pooka 450: callremove(pmp, dck, ck, cnp);
1.103 pooka 451: break;
452: case PUFFS_ABORT_MKDIR:
1.127 pooka 453: callrmdir(pmp, dck, ck, cnp);
1.103 pooka 454: break;
455: }
456:
1.127 pooka 457: callinactive(pmp, ck, 0);
1.172 manu 458: callreclaim(pmp, ck, 1);
1.103 pooka 459: }
1.17 pooka 460:
1.116 pooka 461: /*
462: * Begin vnode operations.
463: *
464: * A word from the keymaster about locks: generally we don't want
465: * to use the vnode locks at all: it creates an ugly dependency between
466: * the userlandia file server and the kernel. But we'll play along with
467: * the kernel vnode locks for now. However, even currently we attempt
468: * to release locks as early as possible. This is possible for some
469: * operations which a) don't need a locked vnode after the userspace op
470: * and b) return with the vnode unlocked. Theoretically we could
471: * unlock-do op-lock for others and order the graph in userspace, but I
472: * don't want to think of the consequences for the time being.
473: */
474:
1.165 manu 475: #define TTL_TO_TIMEOUT(ts) \
476: (hardclock_ticks + (ts->tv_sec * hz) + (ts->tv_nsec * hz / 1000000000))
1.166 manu 477: #define TTL_VALID(ts) \
478: ((ts != NULL) && !((ts->tv_sec == 0) && (ts->tv_nsec == 0)))
479: #define TIMED_OUT(expire) \
480: ((int)((unsigned int)hardclock_ticks - (unsigned int)expire) > 0)
1.1 pooka 481: int
1.123 pooka 482: puffs_vnop_lookup(void *v)
1.1 pooka 483: {
1.180 hannken 484: struct vop_lookup_v2_args /* {
1.17 pooka 485: const struct vnodeop_desc *a_desc;
486: struct vnode *a_dvp;
487: struct vnode **a_vpp;
488: struct componentname *a_cnp;
1.1 pooka 489: } */ *ap = v;
1.107 pooka 490: PUFFS_MSG_VARS(vn, lookup);
1.1 pooka 491: struct puffs_mount *pmp;
492: struct componentname *cnp;
1.165 manu 493: struct vnode *vp, *dvp, *cvp;
494: struct puffs_node *dpn, *cpn;
1.22 chs 495: int isdot;
1.1 pooka 496: int error;
497:
498: pmp = MPTOPUFFSMP(ap->a_dvp->v_mount);
499: cnp = ap->a_cnp;
500: dvp = ap->a_dvp;
1.165 manu 501: cvp = NULL;
502: cpn = NULL;
1.1 pooka 503: *ap->a_vpp = NULL;
504:
1.97 pooka 505: /* r/o fs? we check create later to handle EEXIST */
1.96 pooka 506: if ((cnp->cn_flags & ISLASTCN)
507: && (dvp->v_mount->mnt_flag & MNT_RDONLY)
1.97 pooka 508: && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
1.96 pooka 509: return EROFS;
510:
1.1 pooka 511: isdot = cnp->cn_namelen == 1 && *cnp->cn_nameptr == '.';
512:
1.98 pooka 513: DPRINTF(("puffs_lookup: \"%s\", parent vnode %p, op: %x\n",
1.1 pooka 514: cnp->cn_nameptr, dvp, cnp->cn_nameiop));
515:
516: /*
1.180 hannken 517: * If dotdot cache is enabled, add reference to .. and return.
1.174 manu 518: */
519: if (PUFFS_USE_DOTDOTCACHE(pmp) && (cnp->cn_flags & ISDOTDOT)) {
520: vp = VPTOPP(ap->a_dvp)->pn_parent;
521: vref(vp);
522:
523: *ap->a_vpp = vp;
524: return 0;
525: }
526:
527: /*
1.1 pooka 528: * Check if someone fed it into the cache
529: */
1.167 manu 530: if (!isdot && PUFFS_USE_NAMECACHE(pmp)) {
1.175 dholland 531: int found, iswhiteout;
1.30 pooka 532:
1.176 dholland 533: found = cache_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
534: cnp->cn_nameiop, cnp->cn_flags,
535: &iswhiteout, ap->a_vpp);
1.175 dholland 536: if (iswhiteout) {
537: cnp->cn_flags |= ISWHITEOUT;
538: }
539:
540: if (found && *ap->a_vpp != NULLVP && PUFFS_USE_FS_TTL(pmp)) {
1.165 manu 541: cvp = *ap->a_vpp;
542: cpn = VPTOPP(cvp);
1.167 manu 543:
1.166 manu 544: if (TIMED_OUT(cpn->pn_cn_timeout)) {
1.167 manu 545: cache_purge(cvp);
1.165 manu 546: /*
1.180 hannken 547: * cached vnode (cvp) is still referenced
1.165 manu 548: * so that we can reuse it upon a new
549: * successful lookup.
550: */
551: *ap->a_vpp = NULL;
1.175 dholland 552: found = 0;
1.165 manu 553: }
554: }
555:
556: /*
557: * Do not use negative caching, since the filesystem
558: * provides no TTL for it.
559: */
1.175 dholland 560: if (found && *ap->a_vpp == NULLVP && PUFFS_USE_FS_TTL(pmp))
561: found = 0;
562:
563: if (found) {
564: return *ap->a_vpp == NULLVP ? ENOENT : 0;
565: }
1.165 manu 566:
1.175 dholland 567: /*
568: * This is what would have been left in ERROR before
569: * the rearrangement of cache_lookup(). What with all
570: * the macros, I am not sure if this is a dead value
571: * below or not.
572: */
573: error = -1;
1.23 pooka 574: }
1.1 pooka 575:
576: if (isdot) {
1.147 pooka 577: /* deal with rename lookup semantics */
578: if (cnp->cn_nameiop == RENAME && (cnp->cn_flags & ISLASTCN))
579: return EISDIR;
580:
1.1 pooka 581: vp = ap->a_dvp;
582: vref(vp);
583: *ap->a_vpp = vp;
584: return 0;
585: }
586:
1.180 hannken 587: if (cvp != NULL) {
588: if (vn_lock(cvp, LK_EXCLUSIVE) != 0) {
589: vrele(cvp);
590: cvp = NULL;
591: } else
592: mutex_enter(&cpn->pn_sizemtx);
593: }
1.165 manu 594:
1.107 pooka 595: PUFFS_MSG_ALLOC(vn, lookup);
596: puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred,
1.122 pooka 597: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.1 pooka 598:
599: if (cnp->cn_flags & ISDOTDOT)
1.146 hannken 600: VOP_UNLOCK(dvp);
1.1 pooka 601:
1.114 pooka 602: puffs_msg_setinfo(park_lookup, PUFFSOP_VN,
603: PUFFS_VN_LOOKUP, VPTOPNC(dvp));
604: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_lookup, dvp->v_data, NULL, error);
1.1 pooka 605: DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error));
606:
607: /*
1.23 pooka 608: * In case of error, there is no new vnode to play with, so be
609: * happy with the NULL value given to vpp in the beginning.
610: * Also, check if this really was an error or the target was not
611: * present. Either treat it as a non-error for CREATE/RENAME or
612: * enter the component into the negative name cache (if desired).
1.1 pooka 613: */
614: if (error) {
1.102 pooka 615: error = checkerr(pmp, error, __func__);
1.10 pooka 616: if (error == ENOENT) {
1.97 pooka 617: /* don't allow to create files on r/o fs */
618: if ((dvp->v_mount->mnt_flag & MNT_RDONLY)
619: && cnp->cn_nameiop == CREATE) {
620: error = EROFS;
621:
622: /* adjust values if we are creating */
623: } else if ((cnp->cn_flags & ISLASTCN)
1.1 pooka 624: && (cnp->cn_nameiop == CREATE
625: || cnp->cn_nameiop == RENAME)) {
626: error = EJUSTRETURN;
1.97 pooka 627:
628: /* save negative cache entry */
1.23 pooka 629: } else {
1.168 rmind 630: if (PUFFS_USE_NAMECACHE(pmp) &&
1.170 manu 631: !PUFFS_USE_FS_TTL(pmp))
1.176 dholland 632: cache_enter(dvp, NULL, cnp->cn_nameptr,
633: cnp->cn_namelen, cnp->cn_flags);
1.10 pooka 634: }
1.1 pooka 635: }
1.80 pooka 636: goto out;
1.1 pooka 637: }
638:
1.32 pooka 639: /*
640: * Check that we don't get our parent node back, that would cause
641: * a pretty obvious deadlock.
642: */
643: dpn = dvp->v_data;
1.107 pooka 644: if (lookup_msg->pvnr_newnode == dpn->pn_cookie) {
1.114 pooka 645: puffs_senderr(pmp, PUFFS_ERR_LOOKUP, EINVAL,
1.107 pooka 646: "lookup produced parent cookie", lookup_msg->pvnr_newnode);
1.100 pooka 647: error = EPROTO;
1.80 pooka 648: goto out;
1.32 pooka 649: }
650:
1.165 manu 651: /*
1.167 manu 652: * Check if we looked up the cached vnode
1.165 manu 653: */
1.167 manu 654: vp = NULL;
655: if (cvp && (VPTOPP(cvp)->pn_cookie == lookup_msg->pvnr_newnode)) {
656: int grace;
657:
658: /*
659: * Bump grace time of this node so that it does not get
660: * reclaimed too fast. We try to increase a bit more the
661: * lifetime of busiest * nodes - with some limits.
662: */
663: grace = 10 * puffs_sopreq_expire_timeout;
664: cpn->pn_cn_grace = hardclock_ticks + grace;
1.165 manu 665: vp = cvp;
1.167 manu 666: }
667:
668: /*
669: * No cached vnode available, or the cached vnode does not
670: * match the userland cookie anymore: is the node known?
671: */
672: if (vp == NULL) {
673: error = puffs_getvnode(dvp->v_mount,
674: lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,
675: lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp);
676: if (error) {
677: puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP,
678: VPTOPNC(dvp), lookup_msg->pvnr_newnode,
679: ap->a_cnp);
1.80 pooka 680: goto out;
1.1 pooka 681: }
1.167 manu 682:
683: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.165 manu 684: }
685:
686: /*
687: * Update cache and TTL
688: */
689: if (PUFFS_USE_FS_TTL(pmp)) {
690: struct timespec *va_ttl = &lookup_msg->pvnr_va_ttl;
691: struct timespec *cn_ttl = &lookup_msg->pvnr_cn_ttl;
1.166 manu 692: update_va(vp, NULL, &lookup_msg->pvnr_va,
693: va_ttl, cn_ttl, SETATTR_CHSIZE);
1.1 pooka 694: }
1.101 pooka 695:
1.167 manu 696: KASSERT(lookup_msg->pvnr_newnode == VPTOPP(vp)->pn_cookie);
1.23 pooka 697: *ap->a_vpp = vp;
1.1 pooka 698:
1.170 manu 699: if (PUFFS_USE_NAMECACHE(pmp))
1.176 dholland 700: cache_enter(dvp, vp, cnp->cn_nameptr, cnp->cn_namelen,
701: cnp->cn_flags);
1.1 pooka 702:
1.86 pooka 703: /* XXX */
1.107 pooka 704: if ((lookup_msg->pvnr_cn.pkcn_flags & REQUIREDIR) == 0)
1.86 pooka 705: cnp->cn_flags &= ~REQUIREDIR;
1.107 pooka 706: if (lookup_msg->pvnr_cn.pkcn_consume)
707: cnp->cn_consume = MIN(lookup_msg->pvnr_cn.pkcn_consume,
1.86 pooka 708: strlen(cnp->cn_nameptr) - cnp->cn_namelen);
709:
1.167 manu 710: VPTOPP(vp)->pn_nlookup++;
1.174 manu 711:
712: if (PUFFS_USE_DOTDOTCACHE(pmp) &&
713: (VPTOPP(vp)->pn_parent != dvp))
714: update_parent(vp, dvp);
715:
1.80 pooka 716: out:
1.165 manu 717: if (cvp != NULL) {
718: mutex_exit(&cpn->pn_sizemtx);
1.167 manu 719:
720: if (error || (cvp != vp))
1.165 manu 721: vput(cvp);
722: }
1.180 hannken 723: if (error == 0)
724: VOP_UNLOCK(*ap->a_vpp);
1.165 manu 725:
1.22 chs 726: if (cnp->cn_flags & ISDOTDOT)
727: vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
1.97 pooka 728:
1.50 pooka 729: DPRINTF(("puffs_lookup: returning %d %p\n", error, *ap->a_vpp));
1.107 pooka 730: PUFFS_MSG_RELEASE(lookup);
1.22 chs 731: return error;
1.1 pooka 732: }
733:
1.116 pooka 734: #define REFPN_AND_UNLOCKVP(a, b) \
735: do { \
736: mutex_enter(&b->pn_mtx); \
737: puffs_referencenode(b); \
738: mutex_exit(&b->pn_mtx); \
1.146 hannken 739: VOP_UNLOCK(a); \
1.116 pooka 740: } while (/*CONSTCOND*/0)
741:
742: #define REFPN(b) \
743: do { \
744: mutex_enter(&b->pn_mtx); \
745: puffs_referencenode(b); \
746: mutex_exit(&b->pn_mtx); \
747: } while (/*CONSTCOND*/0)
748:
749: #define RELEPN_AND_VP(a, b) \
750: do { \
751: puffs_releasenode(b); \
752: vrele(a); \
753: } while (/*CONSTCOND*/0)
754:
1.1 pooka 755: int
1.123 pooka 756: puffs_vnop_create(void *v)
1.1 pooka 757: {
1.179 hannken 758: struct vop_create_v3_args /* {
1.1 pooka 759: const struct vnodeop_desc *a_desc;
760: struct vnode *a_dvp;
761: struct vnode **a_vpp;
762: struct componentname *a_cnp;
763: struct vattr *a_vap;
764: } */ *ap = v;
1.107 pooka 765: PUFFS_MSG_VARS(vn, create);
766: struct vnode *dvp = ap->a_dvp;
1.116 pooka 767: struct puffs_node *dpn = VPTOPP(dvp);
1.107 pooka 768: struct componentname *cnp = ap->a_cnp;
1.116 pooka 769: struct mount *mp = dvp->v_mount;
770: struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.1 pooka 771: int error;
772:
1.50 pooka 773: DPRINTF(("puffs_create: dvp %p, cnp: %s\n",
1.107 pooka 774: dvp, ap->a_cnp->cn_nameptr));
1.1 pooka 775:
1.107 pooka 776: PUFFS_MSG_ALLOC(vn, create);
777: puffs_makecn(&create_msg->pvnr_cn, &create_msg->pvnr_cn_cred,
1.122 pooka 778: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.107 pooka 779: create_msg->pvnr_va = *ap->a_vap;
1.114 pooka 780: puffs_msg_setinfo(park_create, PUFFSOP_VN,
781: PUFFS_VN_CREATE, VPTOPNC(dvp));
1.134 pooka 782: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_create, dvp->v_data, NULL, error);
1.116 pooka 783:
1.102 pooka 784: error = checkerr(pmp, error, __func__);
1.1 pooka 785: if (error)
1.4 pooka 786: goto out;
1.1 pooka 787:
1.116 pooka 788: error = puffs_newnode(mp, dvp, ap->a_vpp,
1.107 pooka 789: create_msg->pvnr_newnode, cnp, ap->a_vap->va_type, 0);
1.165 manu 790: if (error) {
1.116 pooka 791: puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie,
1.107 pooka 792: create_msg->pvnr_newnode, cnp);
1.165 manu 793: goto out;
794: }
795:
796: if (PUFFS_USE_FS_TTL(pmp)) {
797: struct timespec *va_ttl = &create_msg->pvnr_va_ttl;
798: struct timespec *cn_ttl = &create_msg->pvnr_cn_ttl;
799: struct vattr *rvap = &create_msg->pvnr_va;
800:
1.166 manu 801: update_va(*ap->a_vpp, NULL, rvap,
802: va_ttl, cn_ttl, SETATTR_CHSIZE);
1.165 manu 803: }
1.4 pooka 804:
1.173 manu 805: VPTOPP(*ap->a_vpp)->pn_nlookup++;
806:
1.174 manu 807: if (PUFFS_USE_DOTDOTCACHE(pmp) &&
808: (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
809: update_parent(*ap->a_vpp, dvp);
810:
1.4 pooka 811: out:
1.50 pooka 812: DPRINTF(("puffs_create: return %d\n", error));
1.107 pooka 813: PUFFS_MSG_RELEASE(create);
1.4 pooka 814: return error;
1.1 pooka 815: }
816:
817: int
1.123 pooka 818: puffs_vnop_mknod(void *v)
1.1 pooka 819: {
1.179 hannken 820: struct vop_mknod_v3_args /* {
1.1 pooka 821: const struct vnodeop_desc *a_desc;
822: struct vnode *a_dvp;
823: struct vnode **a_vpp;
824: struct componentname *a_cnp;
825: struct vattr *a_vap;
826: } */ *ap = v;
1.107 pooka 827: PUFFS_MSG_VARS(vn, mknod);
828: struct vnode *dvp = ap->a_dvp;
1.116 pooka 829: struct puffs_node *dpn = VPTOPP(dvp);
1.107 pooka 830: struct componentname *cnp = ap->a_cnp;
1.116 pooka 831: struct mount *mp = dvp->v_mount;
832: struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.1 pooka 833: int error;
834:
1.107 pooka 835: PUFFS_MSG_ALLOC(vn, mknod);
836: puffs_makecn(&mknod_msg->pvnr_cn, &mknod_msg->pvnr_cn_cred,
1.122 pooka 837: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.107 pooka 838: mknod_msg->pvnr_va = *ap->a_vap;
1.114 pooka 839: puffs_msg_setinfo(park_mknod, PUFFSOP_VN,
840: PUFFS_VN_MKNOD, VPTOPNC(dvp));
1.1 pooka 841:
1.134 pooka 842: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mknod, dvp->v_data, NULL, error);
1.116 pooka 843:
1.102 pooka 844: error = checkerr(pmp, error, __func__);
1.1 pooka 845: if (error)
1.4 pooka 846: goto out;
1.1 pooka 847:
1.116 pooka 848: error = puffs_newnode(mp, dvp, ap->a_vpp,
1.107 pooka 849: mknod_msg->pvnr_newnode, cnp, ap->a_vap->va_type,
1.5 pooka 850: ap->a_vap->va_rdev);
1.165 manu 851: if (error) {
1.116 pooka 852: puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie,
1.107 pooka 853: mknod_msg->pvnr_newnode, cnp);
1.165 manu 854: goto out;
855: }
856:
857: if (PUFFS_USE_FS_TTL(pmp)) {
858: struct timespec *va_ttl = &mknod_msg->pvnr_va_ttl;
859: struct timespec *cn_ttl = &mknod_msg->pvnr_cn_ttl;
860: struct vattr *rvap = &mknod_msg->pvnr_va;
861:
1.166 manu 862: update_va(*ap->a_vpp, NULL, rvap,
863: va_ttl, cn_ttl, SETATTR_CHSIZE);
1.165 manu 864: }
1.4 pooka 865:
1.173 manu 866: VPTOPP(*ap->a_vpp)->pn_nlookup++;
867:
1.174 manu 868: if (PUFFS_USE_DOTDOTCACHE(pmp) &&
869: (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
870: update_parent(*ap->a_vpp, dvp);
871:
1.4 pooka 872: out:
1.107 pooka 873: PUFFS_MSG_RELEASE(mknod);
1.4 pooka 874: return error;
1.1 pooka 875: }
876:
877: int
1.123 pooka 878: puffs_vnop_open(void *v)
1.1 pooka 879: {
880: struct vop_open_args /* {
881: const struct vnodeop_desc *a_desc;
882: struct vnode *a_vp;
883: int a_mode;
884: kauth_cred_t a_cred;
885: } */ *ap = v;
1.107 pooka 886: PUFFS_MSG_VARS(vn, open);
1.47 pooka 887: struct vnode *vp = ap->a_vp;
888: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.183 manu 889: struct puffs_node *pn = VPTOPP(vp);
1.47 pooka 890: int mode = ap->a_mode;
1.79 pooka 891: int error;
1.1 pooka 892:
1.50 pooka 893: DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode));
1.1 pooka 894:
1.79 pooka 895: if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE))
896: ERROUT(EROFS);
1.47 pooka 897:
1.79 pooka 898: if (!EXISTSOP(pmp, OPEN))
899: ERROUT(0);
1.47 pooka 900:
1.107 pooka 901: PUFFS_MSG_ALLOC(vn, open);
902: open_msg->pvnr_mode = mode;
903: puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred);
1.114 pooka 904: puffs_msg_setinfo(park_open, PUFFSOP_VN,
905: PUFFS_VN_OPEN, VPTOPNC(vp));
1.1 pooka 906:
1.114 pooka 907: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_open, vp->v_data, NULL, error);
1.102 pooka 908: error = checkerr(pmp, error, __func__);
1.50 pooka 909:
1.183 manu 910: if (open_msg->pvnr_oflags & PUFFS_OPEN_IO_DIRECT) {
911: if (mode & FREAD)
912: pn->pn_stat |= PNODE_RDIRECT;
913: if (mode & FWRITE)
914: pn->pn_stat |= PNODE_WDIRECT;
915: }
1.50 pooka 916: out:
1.79 pooka 917: DPRINTF(("puffs_open: returning %d\n", error));
1.107 pooka 918: PUFFS_MSG_RELEASE(open);
1.79 pooka 919: return error;
1.1 pooka 920: }
921:
922: int
1.123 pooka 923: puffs_vnop_close(void *v)
1.1 pooka 924: {
925: struct vop_close_args /* {
926: const struct vnodeop_desc *a_desc;
927: struct vnode *a_vp;
928: int a_fflag;
929: kauth_cred_t a_cred;
930: } */ *ap = v;
1.107 pooka 931: PUFFS_MSG_VARS(vn, close);
932: struct vnode *vp = ap->a_vp;
933: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.1 pooka 934:
1.107 pooka 935: PUFFS_MSG_ALLOC(vn, close);
936: puffs_msg_setfaf(park_close);
937: close_msg->pvnr_fflag = ap->a_fflag;
938: puffs_credcvt(&close_msg->pvnr_cred, ap->a_cred);
1.114 pooka 939: puffs_msg_setinfo(park_close, PUFFSOP_VN,
940: PUFFS_VN_CLOSE, VPTOPNC(vp));
1.1 pooka 941:
1.114 pooka 942: puffs_msg_enqueue(pmp, park_close);
1.107 pooka 943: PUFFS_MSG_RELEASE(close);
1.63 pooka 944: return 0;
1.1 pooka 945: }
946:
947: int
1.123 pooka 948: puffs_vnop_access(void *v)
1.1 pooka 949: {
950: struct vop_access_args /* {
951: const struct vnodeop_desc *a_desc;
952: struct vnode *a_vp;
953: int a_mode;
954: kauth_cred_t a_cred;
955: } */ *ap = v;
1.107 pooka 956: PUFFS_MSG_VARS(vn, access);
1.47 pooka 957: struct vnode *vp = ap->a_vp;
958: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
959: int mode = ap->a_mode;
1.102 pooka 960: int error;
1.1 pooka 961:
1.96 pooka 962: if (mode & VWRITE) {
963: switch (vp->v_type) {
964: case VDIR:
965: case VLNK:
966: case VREG:
967: if ((vp->v_mount->mnt_flag & MNT_RDONLY)
968: || !EXISTSOP(pmp, WRITE))
969: return EROFS;
970: break;
971: default:
972: break;
973: }
974: }
1.47 pooka 975:
976: if (!EXISTSOP(pmp, ACCESS))
977: return 0;
978:
1.107 pooka 979: PUFFS_MSG_ALLOC(vn, access);
980: access_msg->pvnr_mode = ap->a_mode;
981: puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred);
1.114 pooka 982: puffs_msg_setinfo(park_access, PUFFSOP_VN,
983: PUFFS_VN_ACCESS, VPTOPNC(vp));
1.107 pooka 984:
1.114 pooka 985: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_access, vp->v_data, NULL, error);
1.107 pooka 986: error = checkerr(pmp, error, __func__);
987: PUFFS_MSG_RELEASE(access);
1.1 pooka 988:
1.107 pooka 989: return error;
1.1 pooka 990: }
991:
1.165 manu 992: static void
993: update_va(struct vnode *vp, struct vattr *vap, struct vattr *rvap,
1.166 manu 994: struct timespec *va_ttl, struct timespec *cn_ttl, int flags)
1.165 manu 995: {
996: struct puffs_node *pn = VPTOPP(vp);
997:
1.167 manu 998: if (TTL_VALID(cn_ttl)) {
1.165 manu 999: pn->pn_cn_timeout = TTL_TO_TIMEOUT(cn_ttl);
1.167 manu 1000: pn->pn_cn_grace = MAX(pn->pn_cn_timeout, pn->pn_cn_grace);
1001: }
1.165 manu 1002:
1003: /*
1004: * Don't listen to the file server regarding special device
1005: * size info, the file server doesn't know anything about them.
1006: */
1007: if (vp->v_type == VBLK || vp->v_type == VCHR)
1008: rvap->va_size = vp->v_size;
1009:
1010: /* Ditto for blocksize (ufs comment: this doesn't belong here) */
1011: if (vp->v_type == VBLK)
1012: rvap->va_blocksize = BLKDEV_IOSIZE;
1013: else if (vp->v_type == VCHR)
1014: rvap->va_blocksize = MAXBSIZE;
1015:
1016: if (vap != NULL) {
1017: (void) memcpy(vap, rvap, sizeof(struct vattr));
1018: vap->va_fsid = vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
1019:
1020: if (pn->pn_stat & PNODE_METACACHE_ATIME)
1021: vap->va_atime = pn->pn_mc_atime;
1022: if (pn->pn_stat & PNODE_METACACHE_CTIME)
1023: vap->va_ctime = pn->pn_mc_ctime;
1024: if (pn->pn_stat & PNODE_METACACHE_MTIME)
1025: vap->va_mtime = pn->pn_mc_mtime;
1026: if (pn->pn_stat & PNODE_METACACHE_SIZE)
1027: vap->va_size = pn->pn_mc_size;
1028: }
1029:
1.166 manu 1030: if (!(pn->pn_stat & PNODE_METACACHE_SIZE) && (flags & SETATTR_CHSIZE)) {
1.165 manu 1031: if (rvap->va_size != VNOVAL
1032: && vp->v_type != VBLK && vp->v_type != VCHR) {
1033: uvm_vnp_setsize(vp, rvap->va_size);
1034: pn->pn_serversize = rvap->va_size;
1035: }
1036: }
1037:
1.166 manu 1038: if ((va_ttl != NULL) && TTL_VALID(va_ttl)) {
1.165 manu 1039: if (pn->pn_va_cache == NULL)
1040: pn->pn_va_cache = pool_get(&puffs_vapool, PR_WAITOK);
1041:
1042: (void)memcpy(pn->pn_va_cache, rvap, sizeof(*rvap));
1043:
1044: pn->pn_va_timeout = TTL_TO_TIMEOUT(va_ttl);
1045: }
1046: }
1047:
1.174 manu 1048: static void
1049: update_parent(struct vnode *vp, struct vnode *dvp)
1050: {
1051: struct puffs_node *pn = VPTOPP(vp);
1052:
1053: if (pn->pn_parent != NULL) {
1054: KASSERT(pn->pn_parent != dvp);
1055: vrele(pn->pn_parent);
1056: }
1057:
1058: vref(dvp);
1059: pn->pn_parent = dvp;
1060: }
1061:
1.1 pooka 1062: int
1.123 pooka 1063: puffs_vnop_getattr(void *v)
1.1 pooka 1064: {
1065: struct vop_getattr_args /* {
1066: const struct vnodeop_desc *a_desc;
1067: struct vnode *a_vp;
1068: struct vattr *a_vap;
1069: kauth_cred_t a_cred;
1070: } */ *ap = v;
1.107 pooka 1071: PUFFS_MSG_VARS(vn, getattr);
1072: struct vnode *vp = ap->a_vp;
1073: struct mount *mp = vp->v_mount;
1074: struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.67 pooka 1075: struct vattr *vap, *rvap;
1.142 pooka 1076: struct puffs_node *pn = VPTOPP(vp);
1.165 manu 1077: struct timespec *va_ttl = NULL;
1.107 pooka 1078: int error = 0;
1.1 pooka 1079:
1.155 manu 1080: /*
1081: * A lock is required so that we do not race with
1082: * setattr, write and fsync when changing vp->v_size.
1083: * This is critical, since setting a stall smaler value
1084: * triggers a file truncate in uvm_vnp_setsize(), which
1085: * most of the time means data corruption (a chunk of
1086: * data is replaced by zeroes). This can be removed if
1087: * we decide one day that VOP_GETATTR must operate on
1088: * a locked vnode.
1.161 hannken 1089: *
1090: * XXX Should be useless now that VOP_GETATTR has been
1091: * fixed to always require a shared lock at least.
1.155 manu 1092: */
1093: mutex_enter(&pn->pn_sizemtx);
1094:
1.142 pooka 1095: REFPN(pn);
1.54 pooka 1096: vap = ap->a_vap;
1.13 pooka 1097:
1.165 manu 1098: if (PUFFS_USE_FS_TTL(pmp)) {
1.166 manu 1099: if (!TIMED_OUT(pn->pn_va_timeout)) {
1100: update_va(vp, vap, pn->pn_va_cache,
1101: NULL, NULL, SETATTR_CHSIZE);
1.165 manu 1102: goto out2;
1103: }
1104: }
1105:
1.107 pooka 1106: PUFFS_MSG_ALLOC(vn, getattr);
1107: vattr_null(&getattr_msg->pvnr_va);
1108: puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred);
1.114 pooka 1109: puffs_msg_setinfo(park_getattr, PUFFSOP_VN,
1110: PUFFS_VN_GETATTR, VPTOPNC(vp));
1.1 pooka 1111:
1.114 pooka 1112: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error);
1.102 pooka 1113: error = checkerr(pmp, error, __func__);
1.1 pooka 1114: if (error)
1.107 pooka 1115: goto out;
1.1 pooka 1116:
1.107 pooka 1117: rvap = &getattr_msg->pvnr_va;
1.67 pooka 1118:
1.165 manu 1119: if (PUFFS_USE_FS_TTL(pmp))
1120: va_ttl = &getattr_msg->pvnr_va_ttl;
1.67 pooka 1121:
1.166 manu 1122: update_va(vp, vap, rvap, va_ttl, NULL, SETATTR_CHSIZE);
1.1 pooka 1123:
1.165 manu 1124: out:
1125: PUFFS_MSG_RELEASE(getattr);
1.13 pooka 1126:
1.165 manu 1127: out2:
1.142 pooka 1128: puffs_releasenode(pn);
1.155 manu 1129:
1130: mutex_exit(&pn->pn_sizemtx);
1131:
1.107 pooka 1132: return error;
1.1 pooka 1133: }
1134:
1.188 manu 1135: static void
1136: zerofill_lastpage(struct vnode *vp, voff_t off)
1137: {
1138: char zbuf[PAGE_SIZE];
1139: struct iovec iov;
1140: struct uio uio;
1141: vsize_t len;
1142: int error;
1143:
1144: if (trunc_page(off) == off)
1145: return;
1.190 manu 1146:
1147: if (vp->v_writecount == 0)
1148: return;
1.188 manu 1149:
1150: len = round_page(off) - off;
1151: memset(zbuf, 0, len);
1152:
1153: iov.iov_base = zbuf;
1154: iov.iov_len = len;
1155: UIO_SETUP_SYSSPACE(&uio);
1156: uio.uio_iov = &iov;
1157: uio.uio_iovcnt = 1;
1158: uio.uio_offset = off;
1159: uio.uio_resid = len;
1160: uio.uio_rw = UIO_WRITE;
1161:
1162: error = ubc_uiomove(&vp->v_uobj, &uio, len,
1163: UVM_ADV_SEQUENTIAL, UBC_WRITE|UBC_UNMAP_FLAG(vp));
1.192 he 1164: if (error) {
1.194 he 1165: DPRINTF(("zero-fill 0x%" PRIxVSIZE "@0x%" PRIx64
1.193 he 1166: " failed: error = %d\n", len, off, error));
1.192 he 1167: }
1.188 manu 1168:
1169: return;
1170: }
1171:
1.90 pooka 1172: static int
1.141 pooka 1173: dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags)
1.1 pooka 1174: {
1.107 pooka 1175: PUFFS_MSG_VARS(vn, setattr);
1176: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.90 pooka 1177: struct puffs_node *pn = vp->v_data;
1.190 manu 1178: vsize_t oldsize = vp->v_size;
1.141 pooka 1179: int error = 0;
1.1 pooka 1180:
1.155 manu 1181: KASSERT(!(flags & SETATTR_CHSIZE) || mutex_owned(&pn->pn_sizemtx));
1182:
1.96 pooka 1183: if ((vp->v_mount->mnt_flag & MNT_RDONLY) &&
1184: (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL
1185: || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL
1186: || vap->va_mode != (mode_t)VNOVAL))
1187: return EROFS;
1188:
1189: if ((vp->v_mount->mnt_flag & MNT_RDONLY)
1190: && vp->v_type == VREG && vap->va_size != VNOVAL)
1191: return EROFS;
1192:
1.65 pooka 1193: /*
1194: * Flush metacache first. If we are called with some explicit
1195: * parameters, treat them as information overriding metacache
1196: * information.
1197: */
1198: if (pn->pn_stat & PNODE_METACACHE_MASK) {
1199: if ((pn->pn_stat & PNODE_METACACHE_ATIME)
1200: && vap->va_atime.tv_sec == VNOVAL)
1201: vap->va_atime = pn->pn_mc_atime;
1202: if ((pn->pn_stat & PNODE_METACACHE_CTIME)
1203: && vap->va_ctime.tv_sec == VNOVAL)
1204: vap->va_ctime = pn->pn_mc_ctime;
1205: if ((pn->pn_stat & PNODE_METACACHE_MTIME)
1206: && vap->va_mtime.tv_sec == VNOVAL)
1207: vap->va_mtime = pn->pn_mc_mtime;
1208: if ((pn->pn_stat & PNODE_METACACHE_SIZE)
1209: && vap->va_size == VNOVAL)
1210: vap->va_size = pn->pn_mc_size;
1211:
1212: pn->pn_stat &= ~PNODE_METACACHE_MASK;
1213: }
1214:
1.165 manu 1215: /*
1216: * Flush attribute cache so that another thread do
1217: * not get a stale value during the operation.
1218: */
1219: if (PUFFS_USE_FS_TTL(pmp))
1220: pn->pn_va_timeout = 0;
1221:
1.107 pooka 1222: PUFFS_MSG_ALLOC(vn, setattr);
1223: (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr));
1224: puffs_credcvt(&setattr_msg->pvnr_cred, cred);
1.114 pooka 1225: puffs_msg_setinfo(park_setattr, PUFFSOP_VN,
1226: PUFFS_VN_SETATTR, VPTOPNC(vp));
1.141 pooka 1227: if (flags & SETATTR_ASYNC)
1228: puffs_msg_setfaf(park_setattr);
1.107 pooka 1229:
1.141 pooka 1230: puffs_msg_enqueue(pmp, park_setattr);
1231: if ((flags & SETATTR_ASYNC) == 0)
1232: error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL);
1.165 manu 1233:
1234: if ((error == 0) && PUFFS_USE_FS_TTL(pmp)) {
1235: struct timespec *va_ttl = &setattr_msg->pvnr_va_ttl;
1236: struct vattr *rvap = &setattr_msg->pvnr_va;
1237:
1.166 manu 1238: update_va(vp, NULL, rvap, va_ttl, NULL, flags);
1.165 manu 1239: }
1240:
1.107 pooka 1241: PUFFS_MSG_RELEASE(setattr);
1.141 pooka 1242: if ((flags & SETATTR_ASYNC) == 0) {
1243: error = checkerr(pmp, error, __func__);
1244: if (error)
1245: return error;
1246: } else {
1247: error = 0;
1248: }
1.8 pooka 1249:
1.90 pooka 1250: if (vap->va_size != VNOVAL) {
1.190 manu 1251: /*
1252: * If we truncated the file, make sure the data beyond
1253: * EOF in last page does not remain in cache, otherwise
1254: * if the file is later truncated to a larger size (creating
1255: * a hole), that area will not return zeroes as it
1256: * should.
1257: */
1258: if ((flags & SETATTR_CHSIZE) && PUFFS_USE_PAGECACHE(pmp) &&
1259: (vap->va_size < oldsize))
1260: zerofill_lastpage(vp, vap->va_size);
1261:
1.90 pooka 1262: pn->pn_serversize = vap->va_size;
1.141 pooka 1263: if (flags & SETATTR_CHSIZE)
1.90 pooka 1264: uvm_vnp_setsize(vp, vap->va_size);
1265: }
1.8 pooka 1266:
1267: return 0;
1.1 pooka 1268: }
1269:
1270: int
1.123 pooka 1271: puffs_vnop_setattr(void *v)
1.90 pooka 1272: {
1273: struct vop_getattr_args /* {
1274: const struct vnodeop_desc *a_desc;
1275: struct vnode *a_vp;
1276: struct vattr *a_vap;
1277: kauth_cred_t a_cred;
1278: } */ *ap = v;
1.155 manu 1279: struct puffs_node *pn = ap->a_vp->v_data;
1280: int error;
1.90 pooka 1281:
1.155 manu 1282: mutex_enter(&pn->pn_sizemtx);
1283: error = dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE);
1284: mutex_exit(&pn->pn_sizemtx);
1285:
1286: return error;
1.90 pooka 1287: }
1288:
1.107 pooka 1289: static __inline int
1290: doinact(struct puffs_mount *pmp, int iaflag)
1.3 pooka 1291: {
1292:
1.17 pooka 1293: if (EXISTSOP(pmp, INACTIVE))
1.66 pooka 1294: if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND)
1.103 pooka 1295: if (iaflag || ALLOPS(pmp))
1.107 pooka 1296: return 1;
1.66 pooka 1297: else
1.107 pooka 1298: return 0;
1.66 pooka 1299: else
1.107 pooka 1300: return 1;
1.66 pooka 1301: else
1.107 pooka 1302: return 0;
1303: }
1304:
1305: static void
1.127 pooka 1306: callinactive(struct puffs_mount *pmp, puffs_cookie_t ck, int iaflag)
1.107 pooka 1307: {
1308: PUFFS_MSG_VARS(vn, inactive);
1309:
1310: if (doinact(pmp, iaflag)) {
1311: PUFFS_MSG_ALLOC(vn, inactive);
1.114 pooka 1312: puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
1.127 pooka 1313: PUFFS_VN_INACTIVE, ck);
1.177 christos 1314: PUFFS_MSG_ENQUEUEWAIT_NOERROR(pmp, park_inactive);
1.107 pooka 1315: PUFFS_MSG_RELEASE(inactive);
1316: }
1.103 pooka 1317: }
1318:
1.107 pooka 1319: /* XXX: callinactive can't setback */
1.103 pooka 1320: int
1.123 pooka 1321: puffs_vnop_inactive(void *v)
1.103 pooka 1322: {
1323: struct vop_inactive_args /* {
1324: const struct vnodeop_desc *a_desc;
1325: struct vnode *a_vp;
1326: } */ *ap = v;
1.107 pooka 1327: PUFFS_MSG_VARS(vn, inactive);
1.103 pooka 1328: struct vnode *vp = ap->a_vp;
1.107 pooka 1329: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.103 pooka 1330: struct puffs_node *pnode;
1.167 manu 1331: bool recycle = false;
1.103 pooka 1332:
1333: pnode = vp->v_data;
1.155 manu 1334: mutex_enter(&pnode->pn_sizemtx);
1.103 pooka 1335:
1.107 pooka 1336: if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) {
1.141 pooka 1337: flushvncache(vp, 0, 0, false);
1.107 pooka 1338: PUFFS_MSG_ALLOC(vn, inactive);
1.114 pooka 1339: puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
1340: PUFFS_VN_INACTIVE, VPTOPNC(vp));
1.177 christos 1341: PUFFS_MSG_ENQUEUEWAIT2_NOERROR(pmp, park_inactive, vp->v_data,
1342: NULL);
1.107 pooka 1343: PUFFS_MSG_RELEASE(inactive);
1344: }
1.66 pooka 1345: pnode->pn_stat &= ~PNODE_DOINACT;
1.3 pooka 1346:
1347: /*
1.85 pooka 1348: * file server thinks it's gone? then don't be afraid care,
1.3 pooka 1349: * node's life was already all it would ever be
1350: */
1.137 pooka 1351: if (pnode->pn_stat & PNODE_NOREFS) {
1352: pnode->pn_stat |= PNODE_DYING;
1.167 manu 1353: recycle = true;
1354: }
1355:
1356: /*
1357: * Handle node TTL.
1358: * If grace has already timed out, make it reclaimed.
1359: * Otherwise, we queue its expiration by sop thread, so
1360: * that it does not remain for ages in the freelist,
1361: * holding memory in userspace, while we will have
1362: * to look it up again anyway.
1363: */
1364: if (PUFFS_USE_FS_TTL(pmp) && !(vp->v_vflag & VV_ROOT) && !recycle) {
1365: bool incache = !TIMED_OUT(pnode->pn_cn_timeout);
1366: bool ingrace = !TIMED_OUT(pnode->pn_cn_grace);
1367: bool reclaimqueued = pnode->pn_stat & PNODE_SOPEXP;
1368:
1369: if (!incache && !ingrace && !reclaimqueued) {
1370: pnode->pn_stat |= PNODE_DYING;
1371: recycle = true;
1372: }
1373:
1374: if (!recycle && !reclaimqueued) {
1375: struct puffs_sopreq *psopr;
1376: int at = MAX(pnode->pn_cn_grace, pnode->pn_cn_timeout);
1377:
1378: KASSERT(curlwp != uvm.pagedaemon_lwp);
1379: psopr = kmem_alloc(sizeof(*psopr), KM_SLEEP);
1380: psopr->psopr_ck = VPTOPNC(pnode->pn_vp);
1381: psopr->psopr_sopreq = PUFFS_SOPREQ_EXPIRE;
1382: psopr->psopr_at = at;
1383:
1384: mutex_enter(&pmp->pmp_sopmtx);
1385:
1386: /*
1387: * If thread has disapeared, just give up. The
1388: * fs is being unmounted and the node will be
1389: * be reclaimed anyway.
1390: *
1391: * Otherwise, we queue the request but do not
1392: * immediatly signal the thread, as the node
1393: * has not been expired yet.
1394: */
1395: if (pmp->pmp_sopthrcount == 0) {
1396: kmem_free(psopr, sizeof(*psopr));
1397: } else {
1.171 manu 1398: TAILQ_INSERT_TAIL(&pmp->pmp_sopnodereqs,
1.167 manu 1399: psopr, psopr_entries);
1400: pnode->pn_stat |= PNODE_SOPEXP;
1401: }
1402:
1403: mutex_exit(&pmp->pmp_sopmtx);
1404: }
1.137 pooka 1405: }
1.124 ad 1406:
1.167 manu 1407: *ap->a_recycle = recycle;
1408:
1.155 manu 1409: mutex_exit(&pnode->pn_sizemtx);
1.146 hannken 1410: VOP_UNLOCK(vp);
1.3 pooka 1411:
1412: return 0;
1413: }
1414:
1.103 pooka 1415: static void
1.167 manu 1416: callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck, int nlookup)
1.103 pooka 1417: {
1.107 pooka 1418: PUFFS_MSG_VARS(vn, reclaim);
1.103 pooka 1419:
1420: if (!EXISTSOP(pmp, RECLAIM))
1421: return;
1422:
1.107 pooka 1423: PUFFS_MSG_ALLOC(vn, reclaim);
1.167 manu 1424: reclaim_msg->pvnr_nlookup = nlookup;
1.107 pooka 1425: puffs_msg_setfaf(park_reclaim);
1.127 pooka 1426: puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck);
1.107 pooka 1427:
1.114 pooka 1428: puffs_msg_enqueue(pmp, park_reclaim);
1.107 pooka 1429: PUFFS_MSG_RELEASE(reclaim);
1.167 manu 1430: return;
1.103 pooka 1431: }
1432:
1.34 pooka 1433: /*
1434: * always FAF, we don't really care if the server wants to fail to
1435: * reclaim the node or not
1436: */
1.3 pooka 1437: int
1.123 pooka 1438: puffs_vnop_reclaim(void *v)
1.1 pooka 1439: {
1440: struct vop_reclaim_args /* {
1441: const struct vnodeop_desc *a_desc;
1442: struct vnode *a_vp;
1443: } */ *ap = v;
1.103 pooka 1444: struct vnode *vp = ap->a_vp;
1445: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.134 pooka 1446: bool notifyserver = true;
1.17 pooka 1447:
1.1 pooka 1448: /*
1449: * first things first: check if someone is trying to reclaim the
1450: * root vnode. do not allow that to travel to userspace.
1451: * Note that we don't need to take the lock similarly to
1452: * puffs_root(), since there is only one of us.
1453: */
1.105 ad 1454: if (vp->v_vflag & VV_ROOT) {
1.55 pooka 1455: mutex_enter(&pmp->pmp_lock);
1.39 pooka 1456: KASSERT(pmp->pmp_root != NULL);
1457: pmp->pmp_root = NULL;
1.55 pooka 1458: mutex_exit(&pmp->pmp_lock);
1.134 pooka 1459: notifyserver = false;
1.1 pooka 1460: }
1461:
1.134 pooka 1462: /*
1463: * purge info from kernel before issueing FAF, since we
1464: * don't really know when we'll get around to it after
1465: * that and someone might race us into node creation
1466: */
1467: mutex_enter(&pmp->pmp_lock);
1.167 manu 1468: if (PUFFS_USE_NAMECACHE(pmp))
1469: cache_purge(vp);
1.134 pooka 1470: mutex_exit(&pmp->pmp_lock);
1471:
1.167 manu 1472: if (notifyserver) {
1473: int nlookup = VPTOPP(vp)->pn_nlookup;
1474:
1475: callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp), nlookup);
1476: }
1.134 pooka 1477:
1.174 manu 1478: if (PUFFS_USE_DOTDOTCACHE(pmp)) {
1479: if (__predict_true(VPTOPP(vp)->pn_parent != NULL))
1480: vrele(VPTOPP(vp)->pn_parent);
1481: else
1.187 hannken 1482: KASSERT(vp->v_type == VNON || (vp->v_vflag & VV_ROOT));
1.174 manu 1483: }
1484:
1.103 pooka 1485: puffs_putvnode(vp);
1.1 pooka 1486:
1487: return 0;
1488: }
1489:
1.60 pooka 1490: #define CSIZE sizeof(**ap->a_cookies)
1.1 pooka 1491: int
1.123 pooka 1492: puffs_vnop_readdir(void *v)
1.1 pooka 1493: {
1494: struct vop_readdir_args /* {
1495: const struct vnodeop_desc *a_desc;
1496: struct vnode *a_vp;
1497: struct uio *a_uio;
1498: kauth_cred_t a_cred;
1499: int *a_eofflag;
1500: off_t **a_cookies;
1501: int *a_ncookies;
1502: } */ *ap = v;
1.107 pooka 1503: PUFFS_MSG_VARS(vn, readdir);
1.102 pooka 1504: struct vnode *vp = ap->a_vp;
1.107 pooka 1505: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.61 pooka 1506: size_t argsize, tomove, cookiemem, cookiesmax;
1.1 pooka 1507: struct uio *uio = ap->a_uio;
1.89 pooka 1508: size_t howmuch, resid;
1.1 pooka 1509: int error;
1510:
1.89 pooka 1511: /*
1512: * ok, so we need: resid + cookiemem = maxreq
1513: * => resid + cookiesize * (resid/minsize) = maxreq
1514: * => resid + cookiesize/minsize * resid = maxreq
1515: * => (cookiesize/minsize + 1) * resid = maxreq
1516: * => resid = maxreq / (cookiesize/minsize + 1)
1517: *
1518: * Since cookiesize <= minsize and we're not very big on floats,
1519: * we approximate that to be 1. Therefore:
1520: *
1521: * resid = maxreq / 2;
1522: *
1523: * Well, at least we didn't have to use differential equations
1524: * or the Gram-Schmidt process.
1525: *
1526: * (yes, I'm very afraid of this)
1527: */
1528: KASSERT(CSIZE <= _DIRENT_MINSIZE((struct dirent *)0));
1529:
1.58 pooka 1530: if (ap->a_cookies) {
1531: KASSERT(ap->a_ncookies != NULL);
1.59 pooka 1532: if (pmp->pmp_args.pa_fhsize == 0)
1.58 pooka 1533: return EOPNOTSUPP;
1.89 pooka 1534: resid = PUFFS_TOMOVE(uio->uio_resid, pmp) / 2;
1535: cookiesmax = resid/_DIRENT_MINSIZE((struct dirent *)0);
1.58 pooka 1536: cookiemem = ALIGN(cookiesmax*CSIZE); /* play safe */
1537: } else {
1.89 pooka 1538: resid = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.58 pooka 1539: cookiesmax = 0;
1540: cookiemem = 0;
1541: }
1.1 pooka 1542:
1.107 pooka 1543: argsize = sizeof(struct puffs_vnmsg_readdir);
1.89 pooka 1544: tomove = resid + cookiemem;
1.107 pooka 1545: puffs_msgmem_alloc(argsize + tomove, &park_readdir,
1.125 pooka 1546: (void *)&readdir_msg, 1);
1.1 pooka 1547:
1.107 pooka 1548: puffs_credcvt(&readdir_msg->pvnr_cred, ap->a_cred);
1549: readdir_msg->pvnr_offset = uio->uio_offset;
1550: readdir_msg->pvnr_resid = resid;
1551: readdir_msg->pvnr_ncookies = cookiesmax;
1552: readdir_msg->pvnr_eofflag = 0;
1553: readdir_msg->pvnr_dentoff = cookiemem;
1.114 pooka 1554: puffs_msg_setinfo(park_readdir, PUFFSOP_VN,
1555: PUFFS_VN_READDIR, VPTOPNC(vp));
1556: puffs_msg_setdelta(park_readdir, tomove);
1.1 pooka 1557:
1.114 pooka 1558: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readdir, vp->v_data, NULL, error);
1.102 pooka 1559: error = checkerr(pmp, error, __func__);
1.1 pooka 1560: if (error)
1561: goto out;
1562:
1563: /* userspace is cheating? */
1.107 pooka 1564: if (readdir_msg->pvnr_resid > resid) {
1.114 pooka 1565: puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
1.102 pooka 1566: "resid grew", VPTOPNC(vp));
1567: ERROUT(EPROTO);
1568: }
1.107 pooka 1569: if (readdir_msg->pvnr_ncookies > cookiesmax) {
1.114 pooka 1570: puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
1.102 pooka 1571: "too many cookies", VPTOPNC(vp));
1.100 pooka 1572: ERROUT(EPROTO);
1573: }
1.1 pooka 1574:
1.58 pooka 1575: /* check eof */
1.107 pooka 1576: if (readdir_msg->pvnr_eofflag)
1.58 pooka 1577: *ap->a_eofflag = 1;
1578:
1.1 pooka 1579: /* bouncy-wouncy with the directory data */
1.107 pooka 1580: howmuch = resid - readdir_msg->pvnr_resid;
1.58 pooka 1581:
1582: /* force eof if no data was returned (getcwd() needs this) */
1.29 pooka 1583: if (howmuch == 0) {
1584: *ap->a_eofflag = 1;
1585: goto out;
1586: }
1.58 pooka 1587:
1.107 pooka 1588: error = uiomove(readdir_msg->pvnr_data + cookiemem, howmuch, uio);
1.1 pooka 1589: if (error)
1590: goto out;
1.58 pooka 1591:
1592: /* provide cookies to caller if so desired */
1593: if (ap->a_cookies) {
1.159 manu 1594: KASSERT(curlwp != uvm.pagedaemon_lwp);
1.107 pooka 1595: *ap->a_cookies = malloc(readdir_msg->pvnr_ncookies*CSIZE,
1.58 pooka 1596: M_TEMP, M_WAITOK);
1.107 pooka 1597: *ap->a_ncookies = readdir_msg->pvnr_ncookies;
1598: memcpy(*ap->a_cookies, readdir_msg->pvnr_data,
1.58 pooka 1599: *ap->a_ncookies*CSIZE);
1600: }
1601:
1602: /* next readdir starts here */
1.107 pooka 1603: uio->uio_offset = readdir_msg->pvnr_offset;
1.1 pooka 1604:
1605: out:
1.107 pooka 1606: puffs_msgmem_release(park_readdir);
1.1 pooka 1607: return error;
1608: }
1.58 pooka 1609: #undef CSIZE
1.1 pooka 1610:
1.69 pooka 1611: /*
1612: * poll works by consuming the bitmask in pn_revents. If there are
1613: * events available, poll returns immediately. If not, it issues a
1614: * poll to userspace, selrecords itself and returns with no available
1615: * events. When the file server returns, it executes puffs_parkdone_poll(),
1616: * where available events are added to the bitmask. selnotify() is
1617: * then also executed by that function causing us to enter here again
1618: * and hopefully find the missing bits (unless someone got them first,
1619: * in which case it starts all over again).
1620: */
1.1 pooka 1621: int
1.123 pooka 1622: puffs_vnop_poll(void *v)
1.1 pooka 1623: {
1624: struct vop_poll_args /* {
1625: const struct vnodeop_desc *a_desc;
1626: struct vnode *a_vp;
1627: int a_events;
1.129 christos 1628: } */ *ap = v;
1.107 pooka 1629: PUFFS_MSG_VARS(vn, poll);
1.69 pooka 1630: struct vnode *vp = ap->a_vp;
1631: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1632: struct puffs_node *pn = vp->v_data;
1.177 christos 1633: int events;
1.1 pooka 1634:
1.69 pooka 1635: if (EXISTSOP(pmp, POLL)) {
1636: mutex_enter(&pn->pn_mtx);
1637: events = pn->pn_revents & ap->a_events;
1638: if (events & ap->a_events) {
1639: pn->pn_revents &= ~ap->a_events;
1640: mutex_exit(&pn->pn_mtx);
1.1 pooka 1641:
1.69 pooka 1642: return events;
1643: } else {
1644: puffs_referencenode(pn);
1645: mutex_exit(&pn->pn_mtx);
1646:
1.107 pooka 1647: PUFFS_MSG_ALLOC(vn, poll);
1648: poll_msg->pvnr_events = ap->a_events;
1.114 pooka 1649: puffs_msg_setinfo(park_poll, PUFFSOP_VN,
1650: PUFFS_VN_POLL, VPTOPNC(vp));
1651: puffs_msg_setcall(park_poll, puffs_parkdone_poll, pn);
1.120 pooka 1652: selrecord(curlwp, &pn->pn_sel);
1.69 pooka 1653:
1.177 christos 1654: PUFFS_MSG_ENQUEUEWAIT2_NOERROR(pmp, park_poll,
1655: vp->v_data, NULL);
1.107 pooka 1656: PUFFS_MSG_RELEASE(poll);
1.1 pooka 1657:
1.69 pooka 1658: return 0;
1659: }
1660: } else {
1661: return genfs_poll(v);
1662: }
1.1 pooka 1663: }
1664:
1.141 pooka 1665: static int
1666: flushvncache(struct vnode *vp, off_t offlo, off_t offhi, bool wait)
1.1 pooka 1667: {
1.141 pooka 1668: struct puffs_node *pn = VPTOPP(vp);
1.54 pooka 1669: struct vattr va;
1.141 pooka 1670: int pflags, error;
1.8 pooka 1671:
1.65 pooka 1672: /* flush out information from our metacache, see vop_setattr */
1.137 pooka 1673: if (pn->pn_stat & PNODE_METACACHE_MASK
1674: && (pn->pn_stat & PNODE_DYING) == 0) {
1.54 pooka 1675: vattr_null(&va);
1.141 pooka 1676: error = dosetattr(vp, &va, FSCRED,
1677: SETATTR_CHSIZE | (wait ? 0 : SETATTR_ASYNC));
1.54 pooka 1678: if (error)
1679: return error;
1680: }
1.8 pooka 1681:
1682: /*
1683: * flush pages to avoid being overly dirty
1684: */
1.54 pooka 1685: pflags = PGO_CLEANIT;
1.141 pooka 1686: if (wait)
1.54 pooka 1687: pflags |= PGO_SYNCIO;
1.165 manu 1688:
1.153 rmind 1689: mutex_enter(vp->v_interlock);
1.141 pooka 1690: return VOP_PUTPAGES(vp, trunc_page(offlo), round_page(offhi), pflags);
1691: }
1692:
1693: int
1694: puffs_vnop_fsync(void *v)
1695: {
1696: struct vop_fsync_args /* {
1697: const struct vnodeop_desc *a_desc;
1698: struct vnode *a_vp;
1699: kauth_cred_t a_cred;
1700: int a_flags;
1701: off_t a_offlo;
1702: off_t a_offhi;
1703: } */ *ap = v;
1704: PUFFS_MSG_VARS(vn, fsync);
1.163 martin 1705: struct vnode *vp;
1706: struct puffs_node *pn;
1707: struct puffs_mount *pmp;
1.141 pooka 1708: int error, dofaf;
1709:
1.163 martin 1710: vp = ap->a_vp;
1711: KASSERT(vp != NULL);
1712: pn = VPTOPP(vp);
1713: KASSERT(pn != NULL);
1714: pmp = MPTOPUFFSMP(vp->v_mount);
1.156 manu 1715: if (ap->a_flags & FSYNC_WAIT) {
1716: mutex_enter(&pn->pn_sizemtx);
1717: } else {
1718: if (mutex_tryenter(&pn->pn_sizemtx) == 0)
1719: return EDEADLK;
1720: }
1721:
1.141 pooka 1722: error = flushvncache(vp, ap->a_offlo, ap->a_offhi,
1723: (ap->a_flags & FSYNC_WAIT) == FSYNC_WAIT);
1.8 pooka 1724: if (error)
1.155 manu 1725: goto out;
1.8 pooka 1726:
1.31 pooka 1727: /*
1728: * HELLO! We exit already here if the user server does not
1.38 pooka 1729: * support fsync OR if we should call fsync for a node which
1730: * has references neither in the kernel or the fs server.
1731: * Otherwise we continue to issue fsync() forward.
1.31 pooka 1732: */
1.155 manu 1733: error = 0;
1.137 pooka 1734: if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING))
1.155 manu 1735: goto out;
1.31 pooka 1736:
1.41 pooka 1737: dofaf = (ap->a_flags & FSYNC_WAIT) == 0 || ap->a_flags == FSYNC_LAZY;
1.35 pooka 1738: /*
1739: * We abuse VXLOCK to mean "vnode is going to die", so we issue
1740: * only FAFs for those. Otherwise there's a danger of deadlock,
1741: * since the execution context here might be the user server
1742: * doing some operation on another fs, which in turn caused a
1743: * vnode to be reclaimed from the freelist for this fs.
1744: */
1745: if (dofaf == 0) {
1.153 rmind 1746: mutex_enter(vp->v_interlock);
1.181 hannken 1747: if (vdead_check(vp, VDEAD_NOWAIT) != 0)
1.35 pooka 1748: dofaf = 1;
1.153 rmind 1749: mutex_exit(vp->v_interlock);
1.35 pooka 1750: }
1751:
1.107 pooka 1752: PUFFS_MSG_ALLOC(vn, fsync);
1753: if (dofaf)
1754: puffs_msg_setfaf(park_fsync);
1755:
1756: puffs_credcvt(&fsync_msg->pvnr_cred, ap->a_cred);
1757: fsync_msg->pvnr_flags = ap->a_flags;
1758: fsync_msg->pvnr_offlo = ap->a_offlo;
1759: fsync_msg->pvnr_offhi = ap->a_offhi;
1.114 pooka 1760: puffs_msg_setinfo(park_fsync, PUFFSOP_VN,
1761: PUFFS_VN_FSYNC, VPTOPNC(vp));
1.31 pooka 1762:
1.114 pooka 1763: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error);
1.107 pooka 1764: PUFFS_MSG_RELEASE(fsync);
1.1 pooka 1765:
1.107 pooka 1766: error = checkerr(pmp, error, __func__);
1.8 pooka 1767:
1.155 manu 1768: out:
1769: mutex_exit(&pn->pn_sizemtx);
1.8 pooka 1770: return error;
1.1 pooka 1771: }
1772:
1773: int
1.123 pooka 1774: puffs_vnop_seek(void *v)
1.1 pooka 1775: {
1776: struct vop_seek_args /* {
1777: const struct vnodeop_desc *a_desc;
1778: struct vnode *a_vp;
1779: off_t a_oldoff;
1780: off_t a_newoff;
1781: kauth_cred_t a_cred;
1782: } */ *ap = v;
1.107 pooka 1783: PUFFS_MSG_VARS(vn, seek);
1.102 pooka 1784: struct vnode *vp = ap->a_vp;
1.106 pooka 1785: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.102 pooka 1786: int error;
1.1 pooka 1787:
1.107 pooka 1788: PUFFS_MSG_ALLOC(vn, seek);
1789: seek_msg->pvnr_oldoff = ap->a_oldoff;
1790: seek_msg->pvnr_newoff = ap->a_newoff;
1791: puffs_credcvt(&seek_msg->pvnr_cred, ap->a_cred);
1.114 pooka 1792: puffs_msg_setinfo(park_seek, PUFFSOP_VN,
1793: PUFFS_VN_SEEK, VPTOPNC(vp));
1.1 pooka 1794:
1.114 pooka 1795: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_seek, vp->v_data, NULL, error);
1.107 pooka 1796: PUFFS_MSG_RELEASE(seek);
1.106 pooka 1797: return checkerr(pmp, error, __func__);
1.1 pooka 1798: }
1799:
1.103 pooka 1800: static int
1.127 pooka 1801: callremove(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
1.103 pooka 1802: struct componentname *cnp)
1803: {
1.107 pooka 1804: PUFFS_MSG_VARS(vn, remove);
1.103 pooka 1805: int error;
1806:
1.107 pooka 1807: PUFFS_MSG_ALLOC(vn, remove);
1.127 pooka 1808: remove_msg->pvnr_cookie_targ = ck;
1.107 pooka 1809: puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
1.122 pooka 1810: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.127 pooka 1811: puffs_msg_setinfo(park_remove, PUFFSOP_VN, PUFFS_VN_REMOVE, dck);
1.107 pooka 1812:
1.114 pooka 1813: PUFFS_MSG_ENQUEUEWAIT(pmp, park_remove, error);
1.107 pooka 1814: PUFFS_MSG_RELEASE(remove);
1.103 pooka 1815:
1816: return checkerr(pmp, error, __func__);
1817: }
1818:
1.107 pooka 1819: /*
1820: * XXX: can't use callremove now because can't catch setbacks with
1.116 pooka 1821: * it due to lack of a pnode argument.
1.107 pooka 1822: */
1.1 pooka 1823: int
1.123 pooka 1824: puffs_vnop_remove(void *v)
1.1 pooka 1825: {
1826: struct vop_remove_args /* {
1827: const struct vnodeop_desc *a_desc;
1828: struct vnode *a_dvp;
1829: struct vnode *a_vp;
1830: struct componentname *a_cnp;
1831: } */ *ap = v;
1.107 pooka 1832: PUFFS_MSG_VARS(vn, remove);
1.103 pooka 1833: struct vnode *dvp = ap->a_dvp;
1834: struct vnode *vp = ap->a_vp;
1.116 pooka 1835: struct puffs_node *dpn = VPTOPP(dvp);
1836: struct puffs_node *pn = VPTOPP(vp);
1.107 pooka 1837: struct componentname *cnp = ap->a_cnp;
1.116 pooka 1838: struct mount *mp = dvp->v_mount;
1839: struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.1 pooka 1840: int error;
1841:
1.107 pooka 1842: PUFFS_MSG_ALLOC(vn, remove);
1843: remove_msg->pvnr_cookie_targ = VPTOPNC(vp);
1844: puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
1.122 pooka 1845: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.114 pooka 1846: puffs_msg_setinfo(park_remove, PUFFSOP_VN,
1847: PUFFS_VN_REMOVE, VPTOPNC(dvp));
1.1 pooka 1848:
1.116 pooka 1849: puffs_msg_enqueue(pmp, park_remove);
1850: REFPN_AND_UNLOCKVP(dvp, dpn);
1851: if (dvp == vp)
1852: REFPN(pn);
1853: else
1854: REFPN_AND_UNLOCKVP(vp, pn);
1855: error = puffs_msg_wait2(pmp, park_remove, dpn, pn);
1856:
1.107 pooka 1857: PUFFS_MSG_RELEASE(remove);
1858:
1.185 manu 1859: puffs_updatenode(VPTOPP(dvp), PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME, 0);
1860:
1.116 pooka 1861: RELEPN_AND_VP(dvp, dpn);
1862: RELEPN_AND_VP(vp, pn);
1863:
1.107 pooka 1864: error = checkerr(pmp, error, __func__);
1.1 pooka 1865: return error;
1866: }
1867:
1868: int
1.123 pooka 1869: puffs_vnop_mkdir(void *v)
1.1 pooka 1870: {
1.179 hannken 1871: struct vop_mkdir_v3_args /* {
1.1 pooka 1872: const struct vnodeop_desc *a_desc;
1873: struct vnode *a_dvp;
1874: struct vnode **a_vpp;
1875: struct componentname *a_cnp;
1876: struct vattr *a_vap;
1877: } */ *ap = v;
1.107 pooka 1878: PUFFS_MSG_VARS(vn, mkdir);
1879: struct vnode *dvp = ap->a_dvp;
1.116 pooka 1880: struct puffs_node *dpn = VPTOPP(dvp);
1.111 pooka 1881: struct componentname *cnp = ap->a_cnp;
1.116 pooka 1882: struct mount *mp = dvp->v_mount;
1883: struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.1 pooka 1884: int error;
1885:
1.107 pooka 1886: PUFFS_MSG_ALLOC(vn, mkdir);
1887: puffs_makecn(&mkdir_msg->pvnr_cn, &mkdir_msg->pvnr_cn_cred,
1.122 pooka 1888: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.107 pooka 1889: mkdir_msg->pvnr_va = *ap->a_vap;
1.114 pooka 1890: puffs_msg_setinfo(park_mkdir, PUFFSOP_VN,
1891: PUFFS_VN_MKDIR, VPTOPNC(dvp));
1.1 pooka 1892:
1.134 pooka 1893: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mkdir, dvp->v_data, NULL, error);
1.116 pooka 1894:
1.102 pooka 1895: error = checkerr(pmp, error, __func__);
1.1 pooka 1896: if (error)
1.4 pooka 1897: goto out;
1.1 pooka 1898:
1.116 pooka 1899: error = puffs_newnode(mp, dvp, ap->a_vpp,
1.111 pooka 1900: mkdir_msg->pvnr_newnode, cnp, VDIR, 0);
1.165 manu 1901: if (error) {
1.116 pooka 1902: puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie,
1.111 pooka 1903: mkdir_msg->pvnr_newnode, cnp);
1.165 manu 1904: goto out;
1905: }
1906:
1907: if (PUFFS_USE_FS_TTL(pmp)) {
1908: struct timespec *va_ttl = &mkdir_msg->pvnr_va_ttl;
1909: struct timespec *cn_ttl = &mkdir_msg->pvnr_cn_ttl;
1910: struct vattr *rvap = &mkdir_msg->pvnr_va;
1911:
1.166 manu 1912: update_va(*ap->a_vpp, NULL, rvap,
1913: va_ttl, cn_ttl, SETATTR_CHSIZE);
1.165 manu 1914: }
1.4 pooka 1915:
1.173 manu 1916: VPTOPP(*ap->a_vpp)->pn_nlookup++;
1917:
1.174 manu 1918: if (PUFFS_USE_DOTDOTCACHE(pmp) &&
1919: (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
1920: update_parent(*ap->a_vpp, dvp);
1921:
1.4 pooka 1922: out:
1.107 pooka 1923: PUFFS_MSG_RELEASE(mkdir);
1.4 pooka 1924: return error;
1.1 pooka 1925: }
1926:
1.103 pooka 1927: static int
1.127 pooka 1928: callrmdir(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
1.103 pooka 1929: struct componentname *cnp)
1930: {
1.107 pooka 1931: PUFFS_MSG_VARS(vn, rmdir);
1.103 pooka 1932: int error;
1933:
1.107 pooka 1934: PUFFS_MSG_ALLOC(vn, rmdir);
1.127 pooka 1935: rmdir_msg->pvnr_cookie_targ = ck;
1.107 pooka 1936: puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1.122 pooka 1937: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.127 pooka 1938: puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, PUFFS_VN_RMDIR, dck);
1.107 pooka 1939:
1.114 pooka 1940: PUFFS_MSG_ENQUEUEWAIT(pmp, park_rmdir, error);
1.107 pooka 1941: PUFFS_MSG_RELEASE(rmdir);
1.103 pooka 1942:
1943: return checkerr(pmp, error, __func__);
1944: }
1945:
1.1 pooka 1946: int
1.123 pooka 1947: puffs_vnop_rmdir(void *v)
1.1 pooka 1948: {
1949: struct vop_rmdir_args /* {
1950: const struct vnodeop_desc *a_desc;
1951: struct vnode *a_dvp;
1952: struct vnode *a_vp;
1953: struct componentname *a_cnp;
1954: } */ *ap = v;
1.107 pooka 1955: PUFFS_MSG_VARS(vn, rmdir);
1.103 pooka 1956: struct vnode *dvp = ap->a_dvp;
1957: struct vnode *vp = ap->a_vp;
1.116 pooka 1958: struct puffs_node *dpn = VPTOPP(dvp);
1959: struct puffs_node *pn = VPTOPP(vp);
1.103 pooka 1960: struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.107 pooka 1961: struct componentname *cnp = ap->a_cnp;
1.1 pooka 1962: int error;
1963:
1.107 pooka 1964: PUFFS_MSG_ALLOC(vn, rmdir);
1965: rmdir_msg->pvnr_cookie_targ = VPTOPNC(vp);
1966: puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1.122 pooka 1967: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.114 pooka 1968: puffs_msg_setinfo(park_rmdir, PUFFSOP_VN,
1969: PUFFS_VN_RMDIR, VPTOPNC(dvp));
1.107 pooka 1970:
1.116 pooka 1971: puffs_msg_enqueue(pmp, park_rmdir);
1972: REFPN_AND_UNLOCKVP(dvp, dpn);
1973: REFPN_AND_UNLOCKVP(vp, pn);
1974: error = puffs_msg_wait2(pmp, park_rmdir, dpn, pn);
1975:
1.107 pooka 1976: PUFFS_MSG_RELEASE(rmdir);
1.1 pooka 1977:
1.185 manu 1978: puffs_updatenode(VPTOPP(dvp), PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME, 0);
1979:
1.23 pooka 1980: /* XXX: some call cache_purge() *for both vnodes* here, investigate */
1.116 pooka 1981: RELEPN_AND_VP(dvp, dpn);
1982: RELEPN_AND_VP(vp, pn);
1.1 pooka 1983:
1984: return error;
1985: }
1986:
1987: int
1.123 pooka 1988: puffs_vnop_link(void *v)
1.1 pooka 1989: {
1990: struct vop_link_args /* {
1991: const struct vnodeop_desc *a_desc;
1992: struct vnode *a_dvp;
1993: struct vnode *a_vp;
1994: struct componentname *a_cnp;
1.129 christos 1995: } */ *ap = v;
1.107 pooka 1996: PUFFS_MSG_VARS(vn, link);
1997: struct vnode *dvp = ap->a_dvp;
1998: struct vnode *vp = ap->a_vp;
1.116 pooka 1999: struct puffs_node *dpn = VPTOPP(dvp);
2000: struct puffs_node *pn = VPTOPP(vp);
1.107 pooka 2001: struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.111 pooka 2002: struct componentname *cnp = ap->a_cnp;
1.1 pooka 2003: int error;
2004:
1.107 pooka 2005: PUFFS_MSG_ALLOC(vn, link);
2006: link_msg->pvnr_cookie_targ = VPTOPNC(vp);
2007: puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred,
1.122 pooka 2008: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.114 pooka 2009: puffs_msg_setinfo(park_link, PUFFSOP_VN,
2010: PUFFS_VN_LINK, VPTOPNC(dvp));
1.1 pooka 2011:
1.116 pooka 2012: puffs_msg_enqueue(pmp, park_link);
2013: REFPN_AND_UNLOCKVP(dvp, dpn);
2014: REFPN(pn);
2015: error = puffs_msg_wait2(pmp, park_link, dpn, pn);
2016:
1.107 pooka 2017: PUFFS_MSG_RELEASE(link);
1.1 pooka 2018:
1.102 pooka 2019: error = checkerr(pmp, error, __func__);
1.1 pooka 2020:
1.54 pooka 2021: /*
2022: * XXX: stay in touch with the cache. I don't like this, but
2023: * don't have a better solution either. See also puffs_rename().
2024: */
1.185 manu 2025: if (error == 0) {
1.117 pooka 2026: puffs_updatenode(pn, PUFFS_UPDATECTIME, 0);
1.185 manu 2027: puffs_updatenode(VPTOPP(dvp),
2028: PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME, 0);
2029: }
1.54 pooka 2030:
1.116 pooka 2031: RELEPN_AND_VP(dvp, dpn);
2032: puffs_releasenode(pn);
1.1 pooka 2033:
2034: return error;
2035: }
2036:
2037: int
1.123 pooka 2038: puffs_vnop_symlink(void *v)
1.1 pooka 2039: {
1.179 hannken 2040: struct vop_symlink_v3_args /* {
1.1 pooka 2041: const struct vnodeop_desc *a_desc;
2042: struct vnode *a_dvp;
2043: struct vnode **a_vpp;
2044: struct componentname *a_cnp;
2045: struct vattr *a_vap;
2046: char *a_target;
1.129 christos 2047: } */ *ap = v;
1.107 pooka 2048: PUFFS_MSG_VARS(vn, symlink);
2049: struct vnode *dvp = ap->a_dvp;
1.116 pooka 2050: struct puffs_node *dpn = VPTOPP(dvp);
2051: struct mount *mp = dvp->v_mount;
1.107 pooka 2052: struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.116 pooka 2053: struct componentname *cnp = ap->a_cnp;
1.1 pooka 2054: int error;
2055:
2056: *ap->a_vpp = NULL;
2057:
1.107 pooka 2058: PUFFS_MSG_ALLOC(vn, symlink);
2059: puffs_makecn(&symlink_msg->pvnr_cn, &symlink_msg->pvnr_cn_cred,
1.122 pooka 2060: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.107 pooka 2061: symlink_msg->pvnr_va = *ap->a_vap;
2062: (void)strlcpy(symlink_msg->pvnr_link, ap->a_target,
2063: sizeof(symlink_msg->pvnr_link));
1.114 pooka 2064: puffs_msg_setinfo(park_symlink, PUFFSOP_VN,
2065: PUFFS_VN_SYMLINK, VPTOPNC(dvp));
1.1 pooka 2066:
1.134 pooka 2067: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_symlink, dvp->v_data, NULL, error);
1.116 pooka 2068:
1.102 pooka 2069: error = checkerr(pmp, error, __func__);
1.1 pooka 2070: if (error)
1.4 pooka 2071: goto out;
1.1 pooka 2072:
1.116 pooka 2073: error = puffs_newnode(mp, dvp, ap->a_vpp,
2074: symlink_msg->pvnr_newnode, cnp, VLNK, 0);
1.165 manu 2075: if (error) {
1.116 pooka 2076: puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie,
2077: symlink_msg->pvnr_newnode, cnp);
1.165 manu 2078: goto out;
2079: }
2080:
2081: if (PUFFS_USE_FS_TTL(pmp)) {
2082: struct timespec *va_ttl = &symlink_msg->pvnr_va_ttl;
2083: struct timespec *cn_ttl = &symlink_msg->pvnr_cn_ttl;
2084: struct vattr *rvap = &symlink_msg->pvnr_va;
2085:
1.166 manu 2086: update_va(*ap->a_vpp, NULL, rvap,
2087: va_ttl, cn_ttl, SETATTR_CHSIZE);
1.165 manu 2088: }
1.4 pooka 2089:
1.173 manu 2090: VPTOPP(*ap->a_vpp)->pn_nlookup++;
2091:
1.174 manu 2092: if (PUFFS_USE_DOTDOTCACHE(pmp) &&
2093: (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
2094: update_parent(*ap->a_vpp, dvp);
2095:
1.4 pooka 2096: out:
1.107 pooka 2097: PUFFS_MSG_RELEASE(symlink);
1.81 pooka 2098:
1.4 pooka 2099: return error;
1.1 pooka 2100: }
2101:
2102: int
1.123 pooka 2103: puffs_vnop_readlink(void *v)
1.1 pooka 2104: {
2105: struct vop_readlink_args /* {
2106: const struct vnodeop_desc *a_desc;
2107: struct vnode *a_vp;
2108: struct uio *a_uio;
2109: kauth_cred_t a_cred;
2110: } */ *ap = v;
1.107 pooka 2111: PUFFS_MSG_VARS(vn, readlink);
2112: struct vnode *vp = ap->a_vp;
1.100 pooka 2113: struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1.51 pooka 2114: size_t linklen;
1.1 pooka 2115: int error;
2116:
1.107 pooka 2117: PUFFS_MSG_ALLOC(vn, readlink);
2118: puffs_credcvt(&readlink_msg->pvnr_cred, ap->a_cred);
2119: linklen = sizeof(readlink_msg->pvnr_link);
2120: readlink_msg->pvnr_linklen = linklen;
1.114 pooka 2121: puffs_msg_setinfo(park_readlink, PUFFSOP_VN,
2122: PUFFS_VN_READLINK, VPTOPNC(vp));
1.1 pooka 2123:
1.114 pooka 2124: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readlink, vp->v_data, NULL, error);
1.102 pooka 2125: error = checkerr(pmp, error, __func__);
1.1 pooka 2126: if (error)
1.107 pooka 2127: goto out;
1.1 pooka 2128:
1.51 pooka 2129: /* bad bad user file server */
1.107 pooka 2130: if (readlink_msg->pvnr_linklen > linklen) {
1.114 pooka 2131: puffs_senderr(pmp, PUFFS_ERR_READLINK, E2BIG,
1.102 pooka 2132: "linklen too big", VPTOPNC(ap->a_vp));
1.107 pooka 2133: error = EPROTO;
2134: goto out;
1.100 pooka 2135: }
1.51 pooka 2136:
1.107 pooka 2137: error = uiomove(&readlink_msg->pvnr_link, readlink_msg->pvnr_linklen,
1.1 pooka 2138: ap->a_uio);
1.107 pooka 2139: out:
2140: PUFFS_MSG_RELEASE(readlink);
2141: return error;
1.1 pooka 2142: }
2143:
2144: int
1.123 pooka 2145: puffs_vnop_rename(void *v)
1.1 pooka 2146: {
2147: struct vop_rename_args /* {
2148: const struct vnodeop_desc *a_desc;
2149: struct vnode *a_fdvp;
2150: struct vnode *a_fvp;
2151: struct componentname *a_fcnp;
2152: struct vnode *a_tdvp;
2153: struct vnode *a_tvp;
2154: struct componentname *a_tcnp;
1.129 christos 2155: } */ *ap = v;
1.107 pooka 2156: PUFFS_MSG_VARS(vn, rename);
1.140 pooka 2157: struct vnode *fdvp = ap->a_fdvp, *fvp = ap->a_fvp;
2158: struct vnode *tdvp = ap->a_tdvp, *tvp = ap->a_tvp;
1.117 pooka 2159: struct puffs_node *fpn = ap->a_fvp->v_data;
1.114 pooka 2160: struct puffs_mount *pmp = MPTOPUFFSMP(fdvp->v_mount);
1.1 pooka 2161: int error;
1.140 pooka 2162: bool doabort = true;
1.1 pooka 2163:
1.140 pooka 2164: if ((fvp->v_mount != tdvp->v_mount) ||
2165: (tvp && (fvp->v_mount != tvp->v_mount))) {
1.79 pooka 2166: ERROUT(EXDEV);
1.140 pooka 2167: }
1.1 pooka 2168:
1.107 pooka 2169: PUFFS_MSG_ALLOC(vn, rename);
1.140 pooka 2170: rename_msg->pvnr_cookie_src = VPTOPNC(fvp);
2171: rename_msg->pvnr_cookie_targdir = VPTOPNC(tdvp);
2172: if (tvp)
2173: rename_msg->pvnr_cookie_targ = VPTOPNC(tvp);
1.1 pooka 2174: else
1.107 pooka 2175: rename_msg->pvnr_cookie_targ = NULL;
1.122 pooka 2176: puffs_makecn(&rename_msg->pvnr_cn_src, &rename_msg->pvnr_cn_src_cred,
1.83 pooka 2177: ap->a_fcnp, PUFFS_USE_FULLPNBUF(pmp));
1.122 pooka 2178: puffs_makecn(&rename_msg->pvnr_cn_targ, &rename_msg->pvnr_cn_targ_cred,
1.83 pooka 2179: ap->a_tcnp, PUFFS_USE_FULLPNBUF(pmp));
1.114 pooka 2180: puffs_msg_setinfo(park_rename, PUFFSOP_VN,
2181: PUFFS_VN_RENAME, VPTOPNC(fdvp));
1.1 pooka 2182:
1.114 pooka 2183: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rename, fdvp->v_data, NULL, error);
1.140 pooka 2184: doabort = false;
2185: PUFFS_MSG_RELEASE(rename);
1.102 pooka 2186: error = checkerr(pmp, error, __func__);
1.1 pooka 2187:
1.54 pooka 2188: /*
2189: * XXX: stay in touch with the cache. I don't like this, but
2190: * don't have a better solution either. See also puffs_link().
2191: */
1.174 manu 2192: if (error == 0) {
1.117 pooka 2193: puffs_updatenode(fpn, PUFFS_UPDATECTIME, 0);
1.185 manu 2194: puffs_updatenode(VPTOPP(fdvp),
2195: PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME, 0);
2196: if (fdvp != tdvp)
2197: puffs_updatenode(VPTOPP(tdvp),
2198: PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME,
2199: 0);
1.54 pooka 2200:
1.174 manu 2201: if (PUFFS_USE_DOTDOTCACHE(pmp) &&
2202: (VPTOPP(fvp)->pn_parent != tdvp))
2203: update_parent(fvp, tdvp);
2204: }
2205:
2206:
1.1 pooka 2207: out:
1.140 pooka 2208: if (doabort)
2209: VOP_ABORTOP(tdvp, ap->a_tcnp);
2210: if (tvp != NULL)
2211: vput(tvp);
2212: if (tdvp == tvp)
2213: vrele(tdvp);
1.28 pooka 2214: else
1.140 pooka 2215: vput(tdvp);
1.1 pooka 2216:
1.140 pooka 2217: if (doabort)
2218: VOP_ABORTOP(fdvp, ap->a_fcnp);
2219: vrele(fdvp);
2220: vrele(fvp);
1.1 pooka 2221:
2222: return error;
2223: }
2224:
1.79 pooka 2225: #define RWARGS(cont, iofl, move, offset, creds) \
2226: (cont)->pvnr_ioflag = (iofl); \
2227: (cont)->pvnr_resid = (move); \
2228: (cont)->pvnr_offset = (offset); \
2229: puffs_credcvt(&(cont)->pvnr_cred, creds)
2230:
1.1 pooka 2231: int
1.123 pooka 2232: puffs_vnop_read(void *v)
1.1 pooka 2233: {
2234: struct vop_read_args /* {
2235: const struct vnodeop_desc *a_desc;
2236: struct vnode *a_vp;
2237: struct uio *a_uio;
2238: int a_ioflag;
2239: kauth_cred_t a_cred;
2240: } */ *ap = v;
1.107 pooka 2241: PUFFS_MSG_VARS(vn, read);
2242: struct vnode *vp = ap->a_vp;
1.183 manu 2243: struct puffs_node *pn = VPTOPP(vp);
1.107 pooka 2244: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
2245: struct uio *uio = ap->a_uio;
1.1 pooka 2246: size_t tomove, argsize;
1.8 pooka 2247: vsize_t bytelen;
1.131 pooka 2248: int error;
1.1 pooka 2249:
1.107 pooka 2250: read_msg = NULL;
1.8 pooka 2251: error = 0;
1.1 pooka 2252:
1.8 pooka 2253: /* std sanity */
2254: if (uio->uio_resid == 0)
2255: return 0;
2256: if (uio->uio_offset < 0)
1.186 manu 2257: return EFBIG;
1.1 pooka 2258:
1.183 manu 2259: if (vp->v_type == VREG &&
2260: PUFFS_USE_PAGECACHE(pmp) &&
2261: !(pn->pn_stat & PNODE_RDIRECT)) {
1.8 pooka 2262: const int advice = IO_ADV_DECODE(ap->a_ioflag);
1.1 pooka 2263:
1.8 pooka 2264: while (uio->uio_resid > 0) {
1.164 jakllsch 2265: if (vp->v_size <= uio->uio_offset) {
2266: break;
2267: }
1.8 pooka 2268: bytelen = MIN(uio->uio_resid,
2269: vp->v_size - uio->uio_offset);
2270: if (bytelen == 0)
2271: break;
2272:
1.131 pooka 2273: error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
2274: UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
1.8 pooka 2275: if (error)
2276: break;
1.1 pooka 2277: }
2278:
1.8 pooka 2279: if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
1.117 pooka 2280: puffs_updatenode(VPTOPP(vp), PUFFS_UPDATEATIME, 0);
1.8 pooka 2281: } else {
1.1 pooka 2282: /*
1.15 pooka 2283: * in case it's not a regular file or we're operating
2284: * uncached, do read in the old-fashioned style,
2285: * i.e. explicit read operations
1.1 pooka 2286: */
2287:
2288: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.107 pooka 2289: argsize = sizeof(struct puffs_vnmsg_read);
2290: puffs_msgmem_alloc(argsize + tomove, &park_read,
1.125 pooka 2291: (void *)&read_msg, 1);
1.8 pooka 2292:
2293: error = 0;
2294: while (uio->uio_resid > 0) {
1.79 pooka 2295: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.113 pooka 2296: memset(read_msg, 0, argsize); /* XXX: touser KASSERT */
1.107 pooka 2297: RWARGS(read_msg, ap->a_ioflag, tomove,
1.79 pooka 2298: uio->uio_offset, ap->a_cred);
1.114 pooka 2299: puffs_msg_setinfo(park_read, PUFFSOP_VN,
2300: PUFFS_VN_READ, VPTOPNC(vp));
2301: puffs_msg_setdelta(park_read, tomove);
1.8 pooka 2302:
1.114 pooka 2303: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_read, vp->v_data,
2304: NULL, error);
1.102 pooka 2305: error = checkerr(pmp, error, __func__);
1.8 pooka 2306: if (error)
2307: break;
2308:
1.107 pooka 2309: if (read_msg->pvnr_resid > tomove) {
1.114 pooka 2310: puffs_senderr(pmp, PUFFS_ERR_READ,
1.102 pooka 2311: E2BIG, "resid grew", VPTOPNC(ap->a_vp));
1.100 pooka 2312: error = EPROTO;
1.8 pooka 2313: break;
2314: }
2315:
1.107 pooka 2316: error = uiomove(read_msg->pvnr_data,
2317: tomove - read_msg->pvnr_resid, uio);
1.8 pooka 2318:
2319: /*
2320: * in case the file is out of juice, resid from
2321: * userspace is != 0. and the error-case is
2322: * quite obvious
2323: */
1.107 pooka 2324: if (error || read_msg->pvnr_resid)
1.8 pooka 2325: break;
2326: }
1.107 pooka 2327:
2328: puffs_msgmem_release(park_read);
1.1 pooka 2329: }
2330:
2331: return error;
2332: }
2333:
1.79 pooka 2334: /*
2335: * XXX: in case of a failure, this leaves uio in a bad state.
2336: * We could theoretically copy the uio and iovecs and "replay"
2337: * them the right amount after the userspace trip, but don't
2338: * bother for now.
2339: */
1.1 pooka 2340: int
1.123 pooka 2341: puffs_vnop_write(void *v)
1.1 pooka 2342: {
2343: struct vop_write_args /* {
2344: const struct vnodeop_desc *a_desc;
2345: struct vnode *a_vp;
2346: struct uio *a_uio;
2347: int a_ioflag;
2348: kauth_cred_t a_cred;
1.73 yamt 2349: } */ *ap = v;
1.107 pooka 2350: PUFFS_MSG_VARS(vn, write);
2351: struct vnode *vp = ap->a_vp;
1.155 manu 2352: struct puffs_node *pn = VPTOPP(vp);
1.107 pooka 2353: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
2354: struct uio *uio = ap->a_uio;
1.1 pooka 2355: size_t tomove, argsize;
1.8 pooka 2356: off_t oldoff, newoff, origoff;
2357: vsize_t bytelen;
1.15 pooka 2358: int error, uflags;
1.50 pooka 2359: int ubcflags;
1.1 pooka 2360:
1.8 pooka 2361: error = uflags = 0;
1.107 pooka 2362: write_msg = NULL;
1.11 pooka 2363:
1.186 manu 2364: /* std sanity */
2365: if (uio->uio_resid == 0)
2366: return 0;
2367: if (uio->uio_offset < 0)
2368: return EFBIG;
2369:
1.155 manu 2370: mutex_enter(&pn->pn_sizemtx);
2371:
1.183 manu 2372: if (vp->v_type == VREG &&
2373: PUFFS_USE_PAGECACHE(pmp) &&
2374: !(pn->pn_stat & PNODE_WDIRECT)) {
1.131 pooka 2375: ubcflags = UBC_WRITE | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp);
1.12 pooka 2376:
1.8 pooka 2377: /*
2378: * userspace *should* be allowed to control this,
2379: * but with UBC it's a bit unclear how to handle it
2380: */
2381: if (ap->a_ioflag & IO_APPEND)
2382: uio->uio_offset = vp->v_size;
1.1 pooka 2383:
1.8 pooka 2384: origoff = uio->uio_offset;
2385: while (uio->uio_resid > 0) {
2386: oldoff = uio->uio_offset;
2387: bytelen = uio->uio_resid;
2388:
1.74 yamt 2389: newoff = oldoff + bytelen;
2390: if (vp->v_size < newoff) {
2391: uvm_vnp_setwritesize(vp, newoff);
2392: }
2393: error = ubc_uiomove(&vp->v_uobj, uio, bytelen,
1.93 yamt 2394: UVM_ADV_RANDOM, ubcflags);
1.8 pooka 2395:
2396: /*
1.74 yamt 2397: * In case of a ubc_uiomove() error,
1.64 pooka 2398: * opt to not extend the file at all and
2399: * return an error. Otherwise, if we attempt
2400: * to clear the memory we couldn't fault to,
2401: * we might generate a kernel page fault.
1.8 pooka 2402: */
1.74 yamt 2403: if (vp->v_size < newoff) {
2404: if (error == 0) {
2405: uflags |= PUFFS_UPDATESIZE;
2406: uvm_vnp_setsize(vp, newoff);
2407: } else {
2408: uvm_vnp_setwritesize(vp, vp->v_size);
2409: }
1.8 pooka 2410: }
2411: if (error)
2412: break;
2413:
1.50 pooka 2414: /*
2415: * If we're writing large files, flush to file server
2416: * every 64k. Otherwise we can very easily exhaust
2417: * kernel and user memory, as the file server cannot
2418: * really keep up with our writing speed.
2419: *
2420: * Note: this does *NOT* honor MNT_ASYNC, because
2421: * that gives userland too much say in the kernel.
2422: */
2423: if (oldoff >> 16 != uio->uio_offset >> 16) {
1.153 rmind 2424: mutex_enter(vp->v_interlock);
1.8 pooka 2425: error = VOP_PUTPAGES(vp, oldoff & ~0xffff,
1.50 pooka 2426: uio->uio_offset & ~0xffff,
2427: PGO_CLEANIT | PGO_SYNCIO);
1.8 pooka 2428: if (error)
2429: break;
2430: }
1.1 pooka 2431: }
1.8 pooka 2432:
1.62 pooka 2433: /* synchronous I/O? */
1.15 pooka 2434: if (error == 0 && ap->a_ioflag & IO_SYNC) {
1.153 rmind 2435: mutex_enter(vp->v_interlock);
1.8 pooka 2436: error = VOP_PUTPAGES(vp, trunc_page(origoff),
1.15 pooka 2437: round_page(uio->uio_offset),
2438: PGO_CLEANIT | PGO_SYNCIO);
1.62 pooka 2439:
1.97 pooka 2440: /* write through page cache? */
1.62 pooka 2441: } else if (error == 0 && pmp->pmp_flags & PUFFS_KFLAG_WTCACHE) {
1.153 rmind 2442: mutex_enter(vp->v_interlock);
1.62 pooka 2443: error = VOP_PUTPAGES(vp, trunc_page(origoff),
2444: round_page(uio->uio_offset), PGO_CLEANIT);
1.1 pooka 2445: }
1.8 pooka 2446: } else {
1.19 pooka 2447: /* tomove is non-increasing */
1.1 pooka 2448: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.107 pooka 2449: argsize = sizeof(struct puffs_vnmsg_write) + tomove;
1.125 pooka 2450: puffs_msgmem_alloc(argsize, &park_write, (void *)&write_msg,1);
1.8 pooka 2451:
2452: while (uio->uio_resid > 0) {
1.79 pooka 2453: /* move data to buffer */
2454: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.113 pooka 2455: memset(write_msg, 0, argsize); /* XXX: touser KASSERT */
1.107 pooka 2456: RWARGS(write_msg, ap->a_ioflag, tomove,
1.79 pooka 2457: uio->uio_offset, ap->a_cred);
1.107 pooka 2458: error = uiomove(write_msg->pvnr_data, tomove, uio);
1.8 pooka 2459: if (error)
2460: break;
2461:
1.79 pooka 2462: /* move buffer to userspace */
1.114 pooka 2463: puffs_msg_setinfo(park_write, PUFFSOP_VN,
2464: PUFFS_VN_WRITE, VPTOPNC(vp));
2465: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_write, vp->v_data,
2466: NULL, error);
1.102 pooka 2467: error = checkerr(pmp, error, __func__);
1.79 pooka 2468: if (error)
1.8 pooka 2469: break;
1.79 pooka 2470:
1.107 pooka 2471: if (write_msg->pvnr_resid > tomove) {
1.114 pooka 2472: puffs_senderr(pmp, PUFFS_ERR_WRITE,
1.102 pooka 2473: E2BIG, "resid grew", VPTOPNC(ap->a_vp));
1.100 pooka 2474: error = EPROTO;
1.8 pooka 2475: break;
2476: }
2477:
2478: /* adjust file size */
1.186 manu 2479: if (vp->v_size < uio->uio_offset) {
2480: uflags |= PUFFS_UPDATESIZE;
1.20 pooka 2481: uvm_vnp_setsize(vp, uio->uio_offset);
1.186 manu 2482: }
1.8 pooka 2483:
2484: /* didn't move everything? bad userspace. bail */
1.107 pooka 2485: if (write_msg->pvnr_resid != 0) {
1.8 pooka 2486: error = EIO;
2487: break;
2488: }
2489: }
1.107 pooka 2490: puffs_msgmem_release(park_write);
1.1 pooka 2491: }
2492:
1.186 manu 2493: if (vp->v_mount->mnt_flag & MNT_RELATIME)
2494: uflags |= PUFFS_UPDATEATIME;
2495: uflags |= PUFFS_UPDATECTIME;
2496: uflags |= PUFFS_UPDATEMTIME;
2497: puffs_updatenode(VPTOPP(vp), uflags, vp->v_size);
2498:
1.155 manu 2499: mutex_exit(&pn->pn_sizemtx);
1.1 pooka 2500: return error;
2501: }
2502:
2503: int
1.196 ! manu 2504: puffs_vnop_fallocate(void *v)
! 2505: {
! 2506: struct vop_fallocate_args /* {
! 2507: const struct vnodeop_desc *a_desc;
! 2508: struct vnode *a_vp;
! 2509: off_t a_pos;
! 2510: off_t a_len;
! 2511: } */ *ap = v;
! 2512: struct vnode *vp = ap->a_vp;
! 2513: struct puffs_node *pn = VPTOPP(vp);
! 2514: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
! 2515: PUFFS_MSG_VARS(vn, fallocate);
! 2516: int error;
! 2517:
! 2518: mutex_enter(&pn->pn_sizemtx);
! 2519:
! 2520: PUFFS_MSG_ALLOC(vn, fallocate);
! 2521: fallocate_msg->pvnr_off = ap->a_pos;
! 2522: fallocate_msg->pvnr_len = ap->a_len;
! 2523: puffs_msg_setinfo(park_fallocate, PUFFSOP_VN,
! 2524: PUFFS_VN_FALLOCATE, VPTOPNC(vp));
! 2525:
! 2526: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fallocate, vp->v_data, NULL, error);
! 2527: error = checkerr(pmp, error, __func__);
! 2528: PUFFS_MSG_RELEASE(fallocate);
! 2529:
! 2530: switch (error) {
! 2531: case 0:
! 2532: break;
! 2533: case EAGAIN:
! 2534: error = EIO;
! 2535: /* FALLTHROUGH */
! 2536: default:
! 2537: goto out;
! 2538: }
! 2539:
! 2540: if (ap->a_pos + ap->a_len > vp->v_size) {
! 2541: uvm_vnp_setsize(vp, ap->a_pos + ap->a_len);
! 2542: puffs_updatenode(pn, PUFFS_UPDATESIZE, vp->v_size);
! 2543: }
! 2544: out:
! 2545: mutex_exit(&pn->pn_sizemtx);
! 2546:
! 2547: return error;
! 2548: }
! 2549:
! 2550: int
! 2551: puffs_vnop_fdiscard(void *v)
! 2552: {
! 2553: struct vop_fdiscard_args /* {
! 2554: const struct vnodeop_desc *a_desc;
! 2555: struct vnode *a_vp;
! 2556: off_t a_pos;
! 2557: off_t a_len;
! 2558: } */ *ap = v;
! 2559: struct vnode *vp = ap->a_vp;
! 2560: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
! 2561: PUFFS_MSG_VARS(vn, fdiscard);
! 2562: int error;
! 2563:
! 2564: PUFFS_MSG_ALLOC(vn, fdiscard);
! 2565: fdiscard_msg->pvnr_off = ap->a_pos;
! 2566: fdiscard_msg->pvnr_len = ap->a_len;
! 2567: puffs_msg_setinfo(park_fdiscard, PUFFSOP_VN,
! 2568: PUFFS_VN_FALLOCATE, VPTOPNC(vp));
! 2569:
! 2570: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fdiscard, vp->v_data, NULL, error);
! 2571: error = checkerr(pmp, error, __func__);
! 2572: PUFFS_MSG_RELEASE(fdiscard);
! 2573:
! 2574: return error;
! 2575: }
! 2576:
! 2577: int
1.123 pooka 2578: puffs_vnop_print(void *v)
1.1 pooka 2579: {
2580: struct vop_print_args /* {
2581: struct vnode *a_vp;
2582: } */ *ap = v;
1.107 pooka 2583: PUFFS_MSG_VARS(vn, print);
1.1 pooka 2584: struct vnode *vp = ap->a_vp;
1.107 pooka 2585: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.2 pooka 2586: struct puffs_node *pn = vp->v_data;
1.1 pooka 2587:
2588: /* kernel portion */
1.144 pooka 2589: printf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
2590: "\tuserspace cookie: %p", vp, pn, pn->pn_cookie);
1.6 pooka 2591: if (vp->v_type == VFIFO)
1.144 pooka 2592: VOCALL(fifo_vnodeop_p, VOFFSET(vop_print), v);
1.143 pooka 2593: printf("\n");
1.1 pooka 2594:
2595: /* userspace portion */
1.107 pooka 2596: if (EXISTSOP(pmp, PRINT)) {
2597: PUFFS_MSG_ALLOC(vn, print);
1.114 pooka 2598: puffs_msg_setinfo(park_print, PUFFSOP_VN,
2599: PUFFS_VN_PRINT, VPTOPNC(vp));
1.177 christos 2600: PUFFS_MSG_ENQUEUEWAIT2_NOERROR(pmp, park_print, vp->v_data,
2601: NULL);
1.107 pooka 2602: PUFFS_MSG_RELEASE(print);
2603: }
1.17 pooka 2604:
2605: return 0;
1.1 pooka 2606: }
2607:
2608: int
1.123 pooka 2609: puffs_vnop_pathconf(void *v)
1.1 pooka 2610: {
2611: struct vop_pathconf_args /* {
2612: const struct vnodeop_desc *a_desc;
2613: struct vnode *a_vp;
2614: int a_name;
2615: register_t *a_retval;
2616: } */ *ap = v;
1.107 pooka 2617: PUFFS_MSG_VARS(vn, pathconf);
1.102 pooka 2618: struct vnode *vp = ap->a_vp;
2619: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.1 pooka 2620: int error;
2621:
1.107 pooka 2622: PUFFS_MSG_ALLOC(vn, pathconf);
2623: pathconf_msg->pvnr_name = ap->a_name;
1.114 pooka 2624: puffs_msg_setinfo(park_pathconf, PUFFSOP_VN,
2625: PUFFS_VN_PATHCONF, VPTOPNC(vp));
2626: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_pathconf, vp->v_data, NULL, error);
1.102 pooka 2627: error = checkerr(pmp, error, __func__);
1.107 pooka 2628: if (!error)
2629: *ap->a_retval = pathconf_msg->pvnr_retval;
2630: PUFFS_MSG_RELEASE(pathconf);
1.1 pooka 2631:
1.107 pooka 2632: return error;
1.1 pooka 2633: }
2634:
2635: int
1.123 pooka 2636: puffs_vnop_advlock(void *v)
1.1 pooka 2637: {
2638: struct vop_advlock_args /* {
2639: const struct vnodeop_desc *a_desc;
2640: struct vnode *a_vp;
2641: void *a_id;
2642: int a_op;
2643: struct flock *a_fl;
2644: int a_flags;
2645: } */ *ap = v;
1.151 manu 2646: PUFFS_MSG_VARS(vn, advlock);
1.102 pooka 2647: struct vnode *vp = ap->a_vp;
1.150 kefren 2648: struct puffs_node *pn = VPTOPP(vp);
1.151 manu 2649: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
2650: int error;
2651:
2652: if (!EXISTSOP(pmp, ADVLOCK))
2653: return lf_advlock(ap, &pn->pn_lockf, vp->v_size);
2654:
2655: PUFFS_MSG_ALLOC(vn, advlock);
2656: (void)memcpy(&advlock_msg->pvnr_fl, ap->a_fl,
2657: sizeof(advlock_msg->pvnr_fl));
2658: advlock_msg->pvnr_id = ap->a_id;
2659: advlock_msg->pvnr_op = ap->a_op;
2660: advlock_msg->pvnr_flags = ap->a_flags;
2661: puffs_msg_setinfo(park_advlock, PUFFSOP_VN,
2662: PUFFS_VN_ADVLOCK, VPTOPNC(vp));
2663: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_advlock, vp->v_data, NULL, error);
2664: error = checkerr(pmp, error, __func__);
2665: PUFFS_MSG_RELEASE(advlock);
1.1 pooka 2666:
1.151 manu 2667: return error;
1.1 pooka 2668: }
1.79 pooka 2669:
1.136 pooka 2670: int
2671: puffs_vnop_abortop(void *v)
2672: {
2673: struct vop_abortop_args /* {
2674: struct vnode *a_dvp;
2675: struct componentname *a_cnp;
2676: }; */ *ap = v;
2677: PUFFS_MSG_VARS(vn, abortop);
2678: struct vnode *dvp = ap->a_dvp;
2679: struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
2680: struct componentname *cnp = ap->a_cnp;
2681:
2682: if (EXISTSOP(pmp, ABORTOP)) {
2683: PUFFS_MSG_ALLOC(vn, abortop);
2684: puffs_makecn(&abortop_msg->pvnr_cn, &abortop_msg->pvnr_cn_cred,
2685: cnp, PUFFS_USE_FULLPNBUF(pmp));
1.139 pooka 2686: puffs_msg_setfaf(park_abortop);
1.136 pooka 2687: puffs_msg_setinfo(park_abortop, PUFFSOP_VN,
2688: PUFFS_VN_ABORTOP, VPTOPNC(dvp));
2689:
1.139 pooka 2690: puffs_msg_enqueue(pmp, park_abortop);
1.136 pooka 2691: PUFFS_MSG_RELEASE(abortop);
2692: }
2693:
2694: return genfs_abortop(v);
2695: }
2696:
1.79 pooka 2697: #define BIOASYNC(bp) (bp->b_flags & B_ASYNC)
2698:
1.8 pooka 2699: /*
2700: * This maps itself to PUFFS_VN_READ/WRITE for data transfer.
2701: */
2702: int
1.123 pooka 2703: puffs_vnop_strategy(void *v)
1.8 pooka 2704: {
2705: struct vop_strategy_args /* {
2706: const struct vnodeop_desc *a_desc;
2707: struct vnode *a_vp;
2708: struct buf *a_bp;
2709: } */ *ap = v;
1.107 pooka 2710: PUFFS_MSG_VARS(vn, rw);
1.35 pooka 2711: struct vnode *vp = ap->a_vp;
1.107 pooka 2712: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.38 pooka 2713: struct puffs_node *pn;
1.8 pooka 2714: struct buf *bp;
2715: size_t argsize;
1.14 pooka 2716: size_t tomove, moved;
1.159 manu 2717: int error, dofaf, cansleep, dobiodone;
1.8 pooka 2718:
1.35 pooka 2719: pmp = MPTOPUFFSMP(vp->v_mount);
1.8 pooka 2720: bp = ap->a_bp;
1.36 pooka 2721: error = 0;
1.79 pooka 2722: dofaf = 0;
1.159 manu 2723: cansleep = 0;
1.38 pooka 2724: pn = VPTOPP(vp);
1.107 pooka 2725: park_rw = NULL; /* explicit */
1.115 pooka 2726: dobiodone = 1;
1.38 pooka 2727:
1.119 pooka 2728: if ((BUF_ISREAD(bp) && !EXISTSOP(pmp, READ))
2729: || (BUF_ISWRITE(bp) && !EXISTSOP(pmp, WRITE)))
1.79 pooka 2730: ERROUT(EOPNOTSUPP);
1.8 pooka 2731:
1.137 pooka 2732: /*
2733: * Short-circuit optimization: don't flush buffer in between
2734: * VOP_INACTIVE and VOP_RECLAIM in case the node has no references.
2735: */
2736: if (pn->pn_stat & PNODE_DYING) {
2737: KASSERT(BUF_ISWRITE(bp));
2738: bp->b_resid = 0;
2739: goto out;
2740: }
2741:
1.8 pooka 2742: #ifdef DIAGNOSTIC
1.107 pooka 2743: if (bp->b_bcount > pmp->pmp_msg_maxsize - PUFFS_MSGSTRUCT_MAX)
1.46 pooka 2744: panic("puffs_strategy: wildly inappropriate buf bcount %d",
2745: bp->b_bcount);
1.8 pooka 2746: #endif
2747:
1.35 pooka 2748: /*
1.41 pooka 2749: * See explanation for the necessity of a FAF in puffs_fsync.
2750: *
2751: * Also, do FAF in case we're suspending.
2752: * See puffs_vfsops.c:pageflush()
1.35 pooka 2753: */
1.119 pooka 2754: if (BUF_ISWRITE(bp)) {
1.153 rmind 2755: mutex_enter(vp->v_interlock);
1.181 hannken 2756: if (vdead_check(vp, VDEAD_NOWAIT) != 0)
1.79 pooka 2757: dofaf = 1;
1.138 pooka 2758: if (pn->pn_stat & PNODE_FAF)
1.79 pooka 2759: dofaf = 1;
1.153 rmind 2760: mutex_exit(vp->v_interlock);
1.35 pooka 2761: }
2762:
1.159 manu 2763: cansleep = (curlwp == uvm.pagedaemon_lwp || dofaf) ? 0 : 1;
2764:
1.160 manu 2765: KASSERT(curlwp != uvm.pagedaemon_lwp || dofaf || BIOASYNC(bp));
1.45 pooka 2766:
1.79 pooka 2767: /* allocate transport structure */
1.53 pooka 2768: tomove = PUFFS_TOMOVE(bp->b_bcount, pmp);
1.107 pooka 2769: argsize = sizeof(struct puffs_vnmsg_rw);
2770: error = puffs_msgmem_alloc(argsize + tomove, &park_rw,
1.159 manu 2771: (void *)&rw_msg, cansleep);
1.107 pooka 2772: if (error)
2773: goto out;
2774: RWARGS(rw_msg, 0, tomove, bp->b_blkno << DEV_BSHIFT, FSCRED);
1.79 pooka 2775:
2776: /* 2x2 cases: read/write, faf/nofaf */
1.119 pooka 2777: if (BUF_ISREAD(bp)) {
1.114 pooka 2778: puffs_msg_setinfo(park_rw, PUFFSOP_VN,
2779: PUFFS_VN_READ, VPTOPNC(vp));
2780: puffs_msg_setdelta(park_rw, tomove);
1.115 pooka 2781: if (BIOASYNC(bp)) {
1.114 pooka 2782: puffs_msg_setcall(park_rw,
2783: puffs_parkdone_asyncbioread, bp);
2784: puffs_msg_enqueue(pmp, park_rw);
1.115 pooka 2785: dobiodone = 0;
1.79 pooka 2786: } else {
1.114 pooka 2787: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rw, vp->v_data,
2788: NULL, error);
1.102 pooka 2789: error = checkerr(pmp, error, __func__);
1.79 pooka 2790: if (error)
2791: goto out;
1.53 pooka 2792:
1.107 pooka 2793: if (rw_msg->pvnr_resid > tomove) {
1.114 pooka 2794: puffs_senderr(pmp, PUFFS_ERR_READ,
1.102 pooka 2795: E2BIG, "resid grew", VPTOPNC(vp));
1.100 pooka 2796: ERROUT(EPROTO);
2797: }
1.14 pooka 2798:
1.107 pooka 2799: moved = tomove - rw_msg->pvnr_resid;
1.8 pooka 2800:
1.107 pooka 2801: (void)memcpy(bp->b_data, rw_msg->pvnr_data, moved);
1.79 pooka 2802: bp->b_resid = bp->b_bcount - moved;
1.14 pooka 2803: }
1.8 pooka 2804: } else {
1.114 pooka 2805: puffs_msg_setinfo(park_rw, PUFFSOP_VN,
2806: PUFFS_VN_WRITE, VPTOPNC(vp));
1.54 pooka 2807: /*
2808: * make pages read-only before we write them if we want
2809: * write caching info
2810: */
2811: if (PUFFS_WCACHEINFO(pmp)) {
2812: struct uvm_object *uobj = &vp->v_uobj;
2813: int npages = (bp->b_bcount + PAGE_SIZE-1) >> PAGE_SHIFT;
2814: struct vm_page *vmp;
2815: int i;
2816:
2817: for (i = 0; i < npages; i++) {
2818: vmp= uvm_pageratop((vaddr_t)bp->b_data
2819: + (i << PAGE_SHIFT));
2820: DPRINTF(("puffs_strategy: write-protecting "
2821: "vp %p page %p, offset %" PRId64"\n",
2822: vp, vmp, vmp->offset));
1.153 rmind 2823: mutex_enter(uobj->vmobjlock);
1.54 pooka 2824: vmp->flags |= PG_RDONLY;
2825: pmap_page_protect(vmp, VM_PROT_READ);
1.153 rmind 2826: mutex_exit(uobj->vmobjlock);
1.54 pooka 2827: }
2828: }
2829:
1.107 pooka 2830: (void)memcpy(&rw_msg->pvnr_data, bp->b_data, tomove);
1.115 pooka 2831: if (dofaf) {
1.107 pooka 2832: puffs_msg_setfaf(park_rw);
1.115 pooka 2833: } else if (BIOASYNC(bp)) {
2834: puffs_msg_setcall(park_rw,
2835: puffs_parkdone_asyncbiowrite, bp);
2836: dobiodone = 0;
2837: }
2838:
1.114 pooka 2839: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rw, vp->v_data, NULL, error);
1.107 pooka 2840:
1.115 pooka 2841: if (dobiodone == 0)
2842: goto out;
2843:
1.112 pooka 2844: error = checkerr(pmp, error, __func__);
2845: if (error)
2846: goto out;
2847:
2848: if (rw_msg->pvnr_resid > tomove) {
1.114 pooka 2849: puffs_senderr(pmp, PUFFS_ERR_WRITE,
1.112 pooka 2850: E2BIG, "resid grew", VPTOPNC(vp));
2851: ERROUT(EPROTO);
2852: }
1.8 pooka 2853:
1.112 pooka 2854: /*
2855: * FAF moved everything. Frankly, we don't
2856: * really have a choice.
2857: */
2858: if (dofaf && error == 0)
2859: moved = tomove;
2860: else
1.107 pooka 2861: moved = tomove - rw_msg->pvnr_resid;
1.9 pooka 2862:
1.112 pooka 2863: bp->b_resid = bp->b_bcount - moved;
2864: if (bp->b_resid != 0) {
2865: ERROUT(EIO);
1.14 pooka 2866: }
1.8 pooka 2867: }
2868:
2869: out:
1.107 pooka 2870: if (park_rw)
2871: puffs_msgmem_release(park_rw);
1.14 pooka 2872:
1.94 ad 2873: if (error)
1.40 pooka 2874: bp->b_error = error;
2875:
1.115 pooka 2876: if (error || dobiodone)
1.53 pooka 2877: biodone(bp);
1.79 pooka 2878:
1.8 pooka 2879: return error;
2880: }
1.1 pooka 2881:
1.21 pooka 2882: int
1.123 pooka 2883: puffs_vnop_mmap(void *v)
1.21 pooka 2884: {
2885: struct vop_mmap_args /* {
2886: const struct vnodeop_desc *a_desc;
2887: struct vnode *a_vp;
1.92 pooka 2888: vm_prot_t a_prot;
1.21 pooka 2889: kauth_cred_t a_cred;
2890: } */ *ap = v;
1.107 pooka 2891: PUFFS_MSG_VARS(vn, mmap);
2892: struct vnode *vp = ap->a_vp;
2893: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.21 pooka 2894: int error;
2895:
1.78 pooka 2896: if (!PUFFS_USE_PAGECACHE(pmp))
1.21 pooka 2897: return genfs_eopnotsupp(v);
2898:
2899: if (EXISTSOP(pmp, MMAP)) {
1.107 pooka 2900: PUFFS_MSG_ALLOC(vn, mmap);
2901: mmap_msg->pvnr_prot = ap->a_prot;
2902: puffs_credcvt(&mmap_msg->pvnr_cred, ap->a_cred);
1.114 pooka 2903: puffs_msg_setinfo(park_mmap, PUFFSOP_VN,
2904: PUFFS_VN_MMAP, VPTOPNC(vp));
1.107 pooka 2905:
1.114 pooka 2906: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mmap, vp->v_data, NULL, error);
1.102 pooka 2907: error = checkerr(pmp, error, __func__);
1.107 pooka 2908: PUFFS_MSG_RELEASE(mmap);
1.21 pooka 2909: } else {
2910: error = genfs_mmap(v);
2911: }
2912:
2913: return error;
2914: }
2915:
2916:
1.1 pooka 2917: /*
2918: * The rest don't get a free trip to userspace and back, they
2919: * have to stay within the kernel.
2920: */
2921:
2922: /*
1.8 pooka 2923: * bmap doesn't really make any sense for puffs, so just 1:1 map it.
2924: * well, maybe somehow, somewhere, some day ....
2925: */
2926: int
1.123 pooka 2927: puffs_vnop_bmap(void *v)
1.8 pooka 2928: {
2929: struct vop_bmap_args /* {
2930: const struct vnodeop_desc *a_desc;
2931: struct vnode *a_vp;
2932: daddr_t a_bn;
2933: struct vnode **a_vpp;
2934: daddr_t *a_bnp;
2935: int *a_runp;
2936: } */ *ap = v;
2937: struct puffs_mount *pmp;
2938:
2939: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
2940:
2941: if (ap->a_vpp)
2942: *ap->a_vpp = ap->a_vp;
2943: if (ap->a_bnp)
2944: *ap->a_bnp = ap->a_bn;
2945: if (ap->a_runp)
1.55 pooka 2946: *ap->a_runp
1.107 pooka 2947: = (PUFFS_TOMOVE(pmp->pmp_msg_maxsize, pmp)>>DEV_BSHIFT) - 1;
1.8 pooka 2948:
2949: return 0;
2950: }
2951:
1.54 pooka 2952: /*
2953: * Handle getpages faults in puffs. We let genfs_getpages() do most
2954: * of the dirty work, but we come in this route to do accounting tasks.
2955: * If the user server has specified functions for cache notifications
2956: * about reads and/or writes, we record which type of operation we got,
2957: * for which page range, and proceed to issue a FAF notification to the
2958: * server about it.
2959: */
2960: int
1.123 pooka 2961: puffs_vnop_getpages(void *v)
1.54 pooka 2962: {
2963: struct vop_getpages_args /* {
2964: const struct vnodeop_desc *a_desc;
2965: struct vnode *a_vp;
2966: voff_t a_offset;
2967: struct vm_page **a_m;
2968: int *a_count;
2969: int a_centeridx;
2970: vm_prot_t a_access_type;
2971: int a_advice;
2972: int a_flags;
2973: } */ *ap = v;
2974: struct puffs_mount *pmp;
1.90 pooka 2975: struct puffs_node *pn;
1.54 pooka 2976: struct vnode *vp;
2977: struct vm_page **pgs;
2978: struct puffs_cacheinfo *pcinfo = NULL;
2979: struct puffs_cacherun *pcrun;
1.55 pooka 2980: void *parkmem = NULL;
1.54 pooka 2981: size_t runsizes;
2982: int i, npages, si, streakon;
2983: int error, locked, write;
2984:
2985: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
2986: npages = *ap->a_count;
2987: pgs = ap->a_m;
2988: vp = ap->a_vp;
1.90 pooka 2989: pn = vp->v_data;
1.54 pooka 2990: locked = (ap->a_flags & PGO_LOCKED) != 0;
2991: write = (ap->a_access_type & VM_PROT_WRITE) != 0;
2992:
2993: /* ccg xnaht - gets Wuninitialized wrong */
2994: pcrun = NULL;
2995: runsizes = 0;
2996:
1.90 pooka 2997: /*
2998: * Check that we aren't trying to fault in pages which our file
2999: * server doesn't know about. This happens if we extend a file by
3000: * skipping some pages and later try to fault in pages which
3001: * are between pn_serversize and vp_size. This check optimizes
3002: * away the common case where a file is being extended.
3003: */
3004: if (ap->a_offset >= pn->pn_serversize && ap->a_offset < vp->v_size) {
3005: struct vattr va;
3006:
3007: /* try again later when we can block */
3008: if (locked)
3009: ERROUT(EBUSY);
3010:
1.153 rmind 3011: mutex_exit(vp->v_interlock);
1.90 pooka 3012: vattr_null(&va);
3013: va.va_size = vp->v_size;
1.123 pooka 3014: error = dosetattr(vp, &va, FSCRED, 0);
1.90 pooka 3015: if (error)
3016: ERROUT(error);
1.153 rmind 3017: mutex_enter(vp->v_interlock);
1.90 pooka 3018: }
3019:
1.54 pooka 3020: if (write && PUFFS_WCACHEINFO(pmp)) {
1.107 pooka 3021: #ifdef notnowjohn
1.54 pooka 3022: /* allocate worst-case memory */
3023: runsizes = ((npages / 2) + 1) * sizeof(struct puffs_cacherun);
1.160 manu 3024: KASSERT(curlwp != uvm.pagedaemon_lwp || locked);
1.132 tsutsui 3025: pcinfo = kmem_zalloc(sizeof(struct puffs_cacheinfo) + runsize,
1.118 pooka 3026: locked ? KM_NOSLEEP : KM_SLEEP);
1.54 pooka 3027:
3028: /*
3029: * can't block if we're locked and can't mess up caching
3030: * information for fs server. so come back later, please
3031: */
1.79 pooka 3032: if (pcinfo == NULL)
3033: ERROUT(ENOMEM);
1.54 pooka 3034:
1.57 pooka 3035: parkmem = puffs_park_alloc(locked == 0);
1.79 pooka 3036: if (parkmem == NULL)
3037: ERROUT(ENOMEM);
1.54 pooka 3038:
3039: pcrun = pcinfo->pcache_runs;
1.107 pooka 3040: #else
3041: (void)parkmem;
3042: #endif
1.54 pooka 3043: }
3044:
3045: error = genfs_getpages(v);
3046: if (error)
3047: goto out;
3048:
3049: if (PUFFS_WCACHEINFO(pmp) == 0)
3050: goto out;
3051:
3052: /*
3053: * Let's see whose fault it was and inform the user server of
3054: * possibly read/written pages. Map pages from read faults
3055: * strictly read-only, since otherwise we might miss info on
3056: * when the page is actually write-faulted to.
3057: */
3058: if (!locked)
1.153 rmind 3059: mutex_enter(vp->v_uobj.vmobjlock);
1.54 pooka 3060: for (i = 0, si = 0, streakon = 0; i < npages; i++) {
3061: if (pgs[i] == NULL || pgs[i] == PGO_DONTCARE) {
3062: if (streakon && write) {
3063: streakon = 0;
3064: pcrun[si].pcache_runend
3065: = trunc_page(pgs[i]->offset) + PAGE_MASK;
3066: si++;
3067: }
3068: continue;
3069: }
3070: if (streakon == 0 && write) {
3071: streakon = 1;
3072: pcrun[si].pcache_runstart = pgs[i]->offset;
3073: }
3074:
3075: if (!write)
3076: pgs[i]->flags |= PG_RDONLY;
3077: }
3078: /* was the last page part of our streak? */
3079: if (streakon) {
3080: pcrun[si].pcache_runend
3081: = trunc_page(pgs[i-1]->offset) + PAGE_MASK;
3082: si++;
3083: }
3084: if (!locked)
1.153 rmind 3085: mutex_exit(vp->v_uobj.vmobjlock);
1.54 pooka 3086:
3087: KASSERT(si <= (npages / 2) + 1);
3088:
1.107 pooka 3089: #ifdef notnowjohn
1.54 pooka 3090: /* send results to userspace */
3091: if (write)
1.55 pooka 3092: puffs_cacheop(pmp, parkmem, pcinfo,
1.54 pooka 3093: sizeof(struct puffs_cacheinfo) + runsizes, VPTOPNC(vp));
1.107 pooka 3094: #endif
1.54 pooka 3095:
3096: out:
3097: if (error) {
3098: if (pcinfo != NULL)
1.118 pooka 3099: kmem_free(pcinfo,
3100: sizeof(struct puffs_cacheinfo) + runsizes);
1.107 pooka 3101: #ifdef notnowjohn
1.55 pooka 3102: if (parkmem != NULL)
1.57 pooka 3103: puffs_park_release(parkmem, 1);
1.107 pooka 3104: #endif
1.54 pooka 3105: }
3106:
3107: return error;
3108: }
1.41 pooka 3109:
1.26 pooka 3110: /*
1.145 pooka 3111: * Extended attribute support.
3112: */
3113:
3114: int
3115: puffs_vnop_getextattr(void *v)
3116: {
3117: struct vop_getextattr_args /*
3118: struct vnode *a_vp;
3119: int a_attrnamespace;
3120: const char *a_name;
3121: struct uio *a_uio;
3122: size_t *a_size;
3123: kauth_cred_t a_cred;
3124: }; */ *ap = v;
3125: PUFFS_MSG_VARS(vn, getextattr);
3126: struct vnode *vp = ap->a_vp;
3127: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
3128: int attrnamespace = ap->a_attrnamespace;
3129: const char *name = ap->a_name;
3130: struct uio *uio = ap->a_uio;
3131: size_t *sizep = ap->a_size;
3132: size_t tomove, resid;
3133: int error;
3134:
3135: if (uio)
3136: resid = uio->uio_resid;
3137: else
3138: resid = 0;
3139:
3140: tomove = PUFFS_TOMOVE(resid, pmp);
3141: if (tomove != resid) {
3142: error = E2BIG;
3143: goto out;
3144: }
3145:
3146: puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_getextattr) + tomove,
3147: &park_getextattr, (void *)&getextattr_msg, 1);
3148:
3149: getextattr_msg->pvnr_attrnamespace = attrnamespace;
3150: strlcpy(getextattr_msg->pvnr_attrname, name,
3151: sizeof(getextattr_msg->pvnr_attrname));
3152: puffs_credcvt(&getextattr_msg->pvnr_cred, ap->a_cred);
3153: if (sizep)
3154: getextattr_msg->pvnr_datasize = 1;
3155: getextattr_msg->pvnr_resid = tomove;
3156:
3157: puffs_msg_setinfo(park_getextattr,
3158: PUFFSOP_VN, PUFFS_VN_GETEXTATTR, VPTOPNC(vp));
3159: puffs_msg_setdelta(park_getextattr, tomove);
3160: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getextattr, vp->v_data, NULL, error);
3161:
3162: error = checkerr(pmp, error, __func__);
3163: if (error)
3164: goto out;
3165:
3166: resid = getextattr_msg->pvnr_resid;
3167: if (resid > tomove) {
3168: puffs_senderr(pmp, PUFFS_ERR_GETEXTATTR, E2BIG,
3169: "resid grew", VPTOPNC(vp));
3170: error = EPROTO;
3171: goto out;
3172: }
3173:
3174: if (sizep)
3175: *sizep = getextattr_msg->pvnr_datasize;
3176: if (uio)
3177: error = uiomove(getextattr_msg->pvnr_data, tomove - resid, uio);
3178:
3179: out:
3180: PUFFS_MSG_RELEASE(getextattr);
3181: return error;
3182: }
3183:
3184: int
3185: puffs_vnop_setextattr(void *v)
3186: {
3187: struct vop_setextattr_args /* {
3188: struct vnode *a_vp;
3189: int a_attrnamespace;
3190: const char *a_name;
3191: struct uio *a_uio;
3192: kauth_cred_t a_cred;
3193: }; */ *ap = v;
3194: PUFFS_MSG_VARS(vn, setextattr);
3195: struct vnode *vp = ap->a_vp;
3196: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
3197: int attrnamespace = ap->a_attrnamespace;
3198: const char *name = ap->a_name;
3199: struct uio *uio = ap->a_uio;
3200: size_t tomove, resid;
3201: int error;
3202:
3203: if (uio)
3204: resid = uio->uio_resid;
3205: else
3206: resid = 0;
3207:
3208: tomove = PUFFS_TOMOVE(resid, pmp);
3209: if (tomove != resid) {
3210: error = E2BIG;
3211: goto out;
3212: }
3213:
3214: puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_setextattr) + tomove,
3215: &park_setextattr, (void *)&setextattr_msg, 1);
3216:
3217: setextattr_msg->pvnr_attrnamespace = attrnamespace;
3218: strlcpy(setextattr_msg->pvnr_attrname, name,
3219: sizeof(setextattr_msg->pvnr_attrname));
3220: puffs_credcvt(&setextattr_msg->pvnr_cred, ap->a_cred);
3221: setextattr_msg->pvnr_resid = tomove;
3222:
3223: if (uio) {
3224: error = uiomove(setextattr_msg->pvnr_data, tomove, uio);
3225: if (error)
3226: goto out;
3227: }
3228:
3229: puffs_msg_setinfo(park_setextattr,
3230: PUFFSOP_VN, PUFFS_VN_SETEXTATTR, VPTOPNC(vp));
3231: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_setextattr, vp->v_data, NULL, error);
3232:
3233: error = checkerr(pmp, error, __func__);
3234: if (error)
3235: goto out;
3236:
3237: if (setextattr_msg->pvnr_resid != 0)
3238: error = EIO;
3239:
3240: out:
3241: PUFFS_MSG_RELEASE(setextattr);
3242:
3243: return error;
3244: }
3245:
3246: int
3247: puffs_vnop_listextattr(void *v)
3248: {
3249: struct vop_listextattr_args /* {
3250: struct vnode *a_vp;
3251: int a_attrnamespace;
3252: struct uio *a_uio;
3253: size_t *a_size;
1.154 manu 3254: int a_flag,
1.145 pooka 3255: kauth_cred_t a_cred;
3256: }; */ *ap = v;
3257: PUFFS_MSG_VARS(vn, listextattr);
3258: struct vnode *vp = ap->a_vp;
3259: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
3260: int attrnamespace = ap->a_attrnamespace;
3261: struct uio *uio = ap->a_uio;
3262: size_t *sizep = ap->a_size;
1.154 manu 3263: int flag = ap->a_flag;
1.145 pooka 3264: size_t tomove, resid;
3265: int error;
3266:
3267: if (uio)
3268: resid = uio->uio_resid;
3269: else
3270: resid = 0;
3271:
3272: tomove = PUFFS_TOMOVE(resid, pmp);
3273: if (tomove != resid) {
3274: error = E2BIG;
3275: goto out;
3276: }
3277:
3278: puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_listextattr) + tomove,
3279: &park_listextattr, (void *)&listextattr_msg, 1);
3280:
3281: listextattr_msg->pvnr_attrnamespace = attrnamespace;
1.154 manu 3282: listextattr_msg->pvnr_flag = flag;
1.145 pooka 3283: puffs_credcvt(&listextattr_msg->pvnr_cred, ap->a_cred);
3284: listextattr_msg->pvnr_resid = tomove;
3285: if (sizep)
3286: listextattr_msg->pvnr_datasize = 1;
3287:
3288: puffs_msg_setinfo(park_listextattr,
3289: PUFFSOP_VN, PUFFS_VN_LISTEXTATTR, VPTOPNC(vp));
3290: puffs_msg_setdelta(park_listextattr, tomove);
3291: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_listextattr, vp->v_data, NULL, error);
3292:
3293: error = checkerr(pmp, error, __func__);
3294: if (error)
3295: goto out;
3296:
3297: resid = listextattr_msg->pvnr_resid;
3298: if (resid > tomove) {
3299: puffs_senderr(pmp, PUFFS_ERR_LISTEXTATTR, E2BIG,
3300: "resid grew", VPTOPNC(vp));
3301: error = EPROTO;
3302: goto out;
3303: }
3304:
3305: if (sizep)
3306: *sizep = listextattr_msg->pvnr_datasize;
3307: if (uio)
3308: error = uiomove(listextattr_msg->pvnr_data, tomove-resid, uio);
3309:
3310: out:
3311: PUFFS_MSG_RELEASE(listextattr);
3312: return error;
3313: }
3314:
3315: int
3316: puffs_vnop_deleteextattr(void *v)
3317: {
3318: struct vop_deleteextattr_args /* {
3319: struct vnode *a_vp;
3320: int a_attrnamespace;
3321: const char *a_name;
3322: kauth_cred_t a_cred;
3323: }; */ *ap = v;
3324: PUFFS_MSG_VARS(vn, deleteextattr);
3325: struct vnode *vp = ap->a_vp;
3326: struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
3327: int attrnamespace = ap->a_attrnamespace;
3328: const char *name = ap->a_name;
3329: int error;
3330:
3331: PUFFS_MSG_ALLOC(vn, deleteextattr);
3332: deleteextattr_msg->pvnr_attrnamespace = attrnamespace;
3333: strlcpy(deleteextattr_msg->pvnr_attrname, name,
3334: sizeof(deleteextattr_msg->pvnr_attrname));
3335: puffs_credcvt(&deleteextattr_msg->pvnr_cred, ap->a_cred);
3336:
3337: puffs_msg_setinfo(park_deleteextattr,
3338: PUFFSOP_VN, PUFFS_VN_DELETEEXTATTR, VPTOPNC(vp));
3339: PUFFS_MSG_ENQUEUEWAIT2(pmp, park_deleteextattr,
3340: vp->v_data, NULL, error);
3341:
3342: error = checkerr(pmp, error, __func__);
3343:
3344: PUFFS_MSG_RELEASE(deleteextattr);
3345: return error;
3346: }
3347:
3348: /*
1.31 pooka 3349: * spec & fifo. These call the miscfs spec and fifo vectors, but issue
1.26 pooka 3350: * FAF update information for the puffs node first.
3351: */
3352: int
1.123 pooka 3353: puffs_vnop_spec_read(void *v)
1.26 pooka 3354: {
3355: struct vop_read_args /* {
3356: const struct vnodeop_desc *a_desc;
3357: struct vnode *a_vp;
3358: struct uio *a_uio;
3359: int a_ioflag;
3360: kauth_cred_t a_cred;
3361: } */ *ap = v;
3362:
1.117 pooka 3363: puffs_updatenode(VPTOPP(ap->a_vp), PUFFS_UPDATEATIME, 0);
1.26 pooka 3364: return VOCALL(spec_vnodeop_p, VOFFSET(vop_read), v);
3365: }
3366:
3367: int
1.123 pooka 3368: puffs_vnop_spec_write(void *v)
1.26 pooka 3369: {
3370: struct vop_write_args /* {
3371: const struct vnodeop_desc *a_desc;
3372: struct vnode *a_vp;
3373: struct uio *a_uio;
3374: int a_ioflag;
3375: kauth_cred_t a_cred;
1.129 christos 3376: } */ *ap = v;
1.26 pooka 3377:
1.117 pooka 3378: puffs_updatenode(VPTOPP(ap->a_vp), PUFFS_UPDATEMTIME, 0);
1.26 pooka 3379: return VOCALL(spec_vnodeop_p, VOFFSET(vop_write), v);
3380: }
3381:
3382: int
1.123 pooka 3383: puffs_vnop_fifo_read(void *v)
1.26 pooka 3384: {
3385: struct vop_read_args /* {
3386: const struct vnodeop_desc *a_desc;
3387: struct vnode *a_vp;
3388: struct uio *a_uio;
3389: int a_ioflag;
3390: kauth_cred_t a_cred;
3391: } */ *ap = v;
3392:
1.117 pooka 3393: puffs_updatenode(VPTOPP(ap->a_vp), PUFFS_UPDATEATIME, 0);
1.26 pooka 3394: return VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), v);
3395: }
3396:
3397: int
1.123 pooka 3398: puffs_vnop_fifo_write(void *v)
1.26 pooka 3399: {
3400: struct vop_write_args /* {
3401: const struct vnodeop_desc *a_desc;
3402: struct vnode *a_vp;
3403: struct uio *a_uio;
3404: int a_ioflag;
3405: kauth_cred_t a_cred;
1.129 christos 3406: } */ *ap = v;
1.26 pooka 3407:
1.117 pooka 3408: puffs_updatenode(VPTOPP(ap->a_vp), PUFFS_UPDATEMTIME, 0);
1.26 pooka 3409: return VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), v);
3410: }
CVSweb <webmaster@jp.NetBSD.org>