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