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