Annotation of src/sys/fs/puffs/puffs_vnops.c, Revision 1.38
1.38 ! pooka 1: /* $NetBSD: puffs_vnops.c,v 1.37 2007/01/21 14:52:20 pooka Exp $ */
1.1 pooka 2:
3: /*
4: * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
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: * 3. The name of the company nor the name of the author may be used to
19: * endorse or promote products derived from this software without specific
20: * prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: #include <sys/cdefs.h>
1.38 ! pooka 36: __KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.37 2007/01/21 14:52:20 pooka Exp $");
1.1 pooka 37:
38: #include <sys/param.h>
39: #include <sys/vnode.h>
40: #include <sys/mount.h>
41: #include <sys/malloc.h>
42: #include <sys/namei.h>
43:
44: #include <fs/puffs/puffs_msgif.h>
45: #include <fs/puffs/puffs_sys.h>
46:
1.6 pooka 47: #include <miscfs/fifofs/fifo.h>
1.1 pooka 48: #include <miscfs/genfs/genfs.h>
1.5 pooka 49: #include <miscfs/specfs/specdev.h>
50:
1.1 pooka 51: int puffs_lookup(void *);
52: int puffs_create(void *);
53: int puffs_access(void *);
54: int puffs_mknod(void *);
55: int puffs_open(void *);
56: int puffs_close(void *);
57: int puffs_getattr(void *);
58: int puffs_setattr(void *);
59: int puffs_reclaim(void *);
60: int puffs_readdir(void *);
61: int puffs_poll(void *);
62: int puffs_fsync(void *);
63: int puffs_seek(void *);
64: int puffs_remove(void *);
65: int puffs_mkdir(void *);
66: int puffs_rmdir(void *);
67: int puffs_link(void *);
68: int puffs_readlink(void *);
69: int puffs_symlink(void *);
70: int puffs_rename(void *);
71: int puffs_read(void *);
72: int puffs_write(void *);
73: int puffs_fcntl(void *);
74: int puffs_ioctl(void *);
75: int puffs_inactive(void *);
76: int puffs_print(void *);
77: int puffs_pathconf(void *);
78: int puffs_advlock(void *);
1.8 pooka 79: int puffs_strategy(void *);
80: int puffs_bmap(void *);
1.16 pooka 81: int puffs_mmap(void *);
1.1 pooka 82:
1.26 pooka 83: int puffs_spec_read(void *);
84: int puffs_spec_write(void *);
85: int puffs_fifo_read(void *);
86: int puffs_fifo_write(void *);
87:
1.17 pooka 88: int puffs_checkop(void *);
89:
1.1 pooka 90:
91: /* VOP_LEASE() not included */
92:
93: int puffs_generic(void *);
94:
95: #if 0
96: #define puffs_lock genfs_lock
97: #define puffs_unlock genfs_unlock
98: #define puffs_islocked genfs_islocked
99: #else
100: int puffs_lock(void *);
101: int puffs_unlock(void *);
102: int puffs_islocked(void *);
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.17 pooka 108: { &vop_lookup_desc, puffs_lookup }, /* REAL lookup */
109: { &vop_create_desc, puffs_checkop }, /* create */
110: { &vop_mknod_desc, puffs_checkop }, /* mknod */
111: { &vop_open_desc, puffs_checkop }, /* open */
112: { &vop_close_desc, puffs_checkop }, /* close */
113: { &vop_access_desc, puffs_checkop }, /* access */
114: { &vop_getattr_desc, puffs_checkop }, /* getattr */
115: { &vop_setattr_desc, puffs_checkop }, /* setattr */
116: { &vop_read_desc, puffs_checkop }, /* read */
117: { &vop_write_desc, puffs_checkop }, /* write */
118: { &vop_fcntl_desc, puffs_checkop }, /* fcntl */
119: { &vop_ioctl_desc, puffs_checkop }, /* ioctl */
1.31 pooka 120: { &vop_fsync_desc, puffs_fsync }, /* REAL fsync */
1.17 pooka 121: { &vop_seek_desc, puffs_checkop }, /* seek */
122: { &vop_remove_desc, puffs_checkop }, /* remove */
123: { &vop_link_desc, puffs_checkop }, /* link */
124: { &vop_rename_desc, puffs_checkop }, /* rename */
125: { &vop_mkdir_desc, puffs_checkop }, /* mkdir */
126: { &vop_rmdir_desc, puffs_checkop }, /* rmdir */
127: { &vop_symlink_desc, puffs_checkop }, /* symlink */
128: { &vop_readdir_desc, puffs_checkop }, /* readdir */
129: { &vop_readlink_desc, puffs_checkop }, /* readlink */
130: { &vop_getpages_desc, puffs_checkop }, /* getpages */
131: { &vop_putpages_desc, puffs_checkop }, /* putpages */
132: { &vop_pathconf_desc, puffs_checkop }, /* pathconf */
133: { &vop_advlock_desc, puffs_checkop }, /* advlock */
134: { &vop_strategy_desc, puffs_strategy }, /* REAL strategy */
1.34 pooka 135: { &vop_revoke_desc, genfs_revoke }, /* REAL revoke */
1.17 pooka 136: { &vop_abortop_desc, genfs_abortop }, /* REAL abortop */
137: { &vop_inactive_desc, puffs_inactive }, /* REAL inactive */
138: { &vop_reclaim_desc, puffs_reclaim }, /* REAL reclaim */
139: { &vop_lock_desc, puffs_lock }, /* REAL lock */
140: { &vop_unlock_desc, puffs_unlock }, /* REAL unlock */
141: { &vop_bmap_desc, puffs_bmap }, /* REAL bmap */
142: { &vop_print_desc, puffs_print }, /* REAL print */
143: { &vop_islocked_desc, puffs_islocked }, /* REAL islocked */
144: { &vop_bwrite_desc, genfs_nullop }, /* REAL bwrite */
145: { &vop_mmap_desc, puffs_mmap }, /* REAL mmap */
1.1 pooka 146:
147: { &vop_poll_desc, genfs_eopnotsupp }, /* poll XXX */
148: { &vop_poll_desc, genfs_eopnotsupp }, /* kqfilter XXX */
149: { NULL, NULL }
150: };
151: const struct vnodeopv_desc puffs_vnodeop_opv_desc =
152: { &puffs_vnodeop_p, puffs_vnodeop_entries };
153:
1.5 pooka 154:
155: int (**puffs_specop_p)(void *);
156: const struct vnodeopv_entry_desc puffs_specop_entries[] = {
157: { &vop_default_desc, vn_default_error },
158: { &vop_lookup_desc, spec_lookup }, /* lookup, ENOTDIR */
1.6 pooka 159: { &vop_create_desc, spec_create }, /* genfs_badop */
160: { &vop_mknod_desc, spec_mknod }, /* genfs_badop */
161: { &vop_open_desc, spec_open }, /* spec_open */
1.26 pooka 162: { &vop_close_desc, spec_close }, /* spec_close */
163: { &vop_access_desc, puffs_checkop }, /* access */
164: { &vop_getattr_desc, puffs_checkop }, /* getattr */
165: { &vop_setattr_desc, puffs_checkop }, /* setattr */
166: { &vop_read_desc, puffs_spec_read }, /* update, read */
167: { &vop_write_desc, puffs_spec_write }, /* update, write */
1.5 pooka 168: { &vop_lease_desc, spec_lease_check }, /* genfs_nullop */
169: { &vop_ioctl_desc, spec_ioctl }, /* spec_ioctl */
170: { &vop_fcntl_desc, genfs_fcntl }, /* dummy */
171: { &vop_poll_desc, spec_poll }, /* spec_poll */
172: { &vop_kqfilter_desc, spec_kqfilter }, /* spec_kqfilter */
173: { &vop_revoke_desc, spec_revoke }, /* genfs_revoke */
174: { &vop_mmap_desc, spec_mmap }, /* genfs_mmap (dummy) */
1.7 pooka 175: { &vop_fsync_desc, spec_fsync }, /* vflushbuf */
1.5 pooka 176: { &vop_seek_desc, spec_seek }, /* genfs_nullop */
177: { &vop_remove_desc, spec_remove }, /* genfs_badop */
178: { &vop_link_desc, spec_link }, /* genfs_badop */
179: { &vop_rename_desc, spec_rename }, /* genfs_badop */
180: { &vop_mkdir_desc, spec_mkdir }, /* genfs_badop */
181: { &vop_rmdir_desc, spec_rmdir }, /* genfs_badop */
182: { &vop_symlink_desc, spec_symlink }, /* genfs_badop */
183: { &vop_readdir_desc, spec_readdir }, /* genfs_badop */
184: { &vop_readlink_desc, spec_readlink }, /* genfs_badop */
185: { &vop_abortop_desc, spec_abortop }, /* genfs_badop */
1.26 pooka 186: { &vop_inactive_desc, puffs_inactive }, /* REAL inactive */
187: { &vop_reclaim_desc, puffs_reclaim }, /* REAL reclaim */
188: { &vop_lock_desc, puffs_lock }, /* REAL lock */
189: { &vop_unlock_desc, puffs_unlock }, /* REAL unlock */
1.5 pooka 190: { &vop_bmap_desc, spec_bmap }, /* dummy */
191: { &vop_strategy_desc, spec_strategy }, /* dev strategy */
1.26 pooka 192: { &vop_print_desc, puffs_print }, /* REAL print */
193: { &vop_islocked_desc, puffs_islocked }, /* REAL islocked */
1.5 pooka 194: { &vop_pathconf_desc, spec_pathconf }, /* pathconf */
195: { &vop_advlock_desc, spec_advlock }, /* lf_advlock */
196: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
197: { &vop_getpages_desc, spec_getpages }, /* genfs_getpages */
198: { &vop_putpages_desc, spec_putpages }, /* genfs_putpages */
199: #if 0
200: { &vop_openextattr_desc, _openextattr }, /* openextattr */
201: { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */
202: { &vop_getextattr_desc, _getextattr }, /* getextattr */
203: { &vop_setextattr_desc, _setextattr }, /* setextattr */
204: { &vop_listextattr_desc, _listextattr }, /* listextattr */
205: { &vop_deleteextattr_desc, _deleteextattr }, /* deleteextattr */
206: #endif
207: { NULL, NULL }
208: };
209: const struct vnodeopv_desc puffs_specop_opv_desc =
210: { &puffs_specop_p, puffs_specop_entries };
211:
1.23 pooka 212:
1.6 pooka 213: int (**puffs_fifoop_p)(void *);
214: const struct vnodeopv_entry_desc puffs_fifoop_entries[] = {
215: { &vop_default_desc, vn_default_error },
216: { &vop_lookup_desc, fifo_lookup }, /* lookup, ENOTDIR */
217: { &vop_create_desc, fifo_create }, /* genfs_badop */
218: { &vop_mknod_desc, fifo_mknod }, /* genfs_badop */
219: { &vop_open_desc, fifo_open }, /* open */
1.26 pooka 220: { &vop_close_desc, fifo_close }, /* close */
221: { &vop_access_desc, puffs_checkop }, /* access */
222: { &vop_getattr_desc, puffs_checkop }, /* getattr */
223: { &vop_setattr_desc, puffs_checkop }, /* setattr */
224: { &vop_read_desc, puffs_fifo_read }, /* read, update */
225: { &vop_write_desc, puffs_fifo_write }, /* write, update */
1.6 pooka 226: { &vop_lease_desc, fifo_lease_check }, /* genfs_nullop */
227: { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */
228: { &vop_fcntl_desc, genfs_fcntl }, /* dummy */
229: { &vop_poll_desc, fifo_poll }, /* poll */
230: { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */
231: { &vop_revoke_desc, fifo_revoke }, /* genfs_revoke */
232: { &vop_mmap_desc, fifo_mmap }, /* genfs_badop */
1.26 pooka 233: { &vop_fsync_desc, puffs_checkop }, /* fsync */
1.6 pooka 234: { &vop_seek_desc, fifo_seek }, /* genfs_badop */
235: { &vop_remove_desc, fifo_remove }, /* genfs_badop */
236: { &vop_link_desc, fifo_link }, /* genfs_badop */
237: { &vop_rename_desc, fifo_rename }, /* genfs_badop */
238: { &vop_mkdir_desc, fifo_mkdir }, /* genfs_badop */
239: { &vop_rmdir_desc, fifo_rmdir }, /* genfs_badop */
240: { &vop_symlink_desc, fifo_symlink }, /* genfs_badop */
241: { &vop_readdir_desc, fifo_readdir }, /* genfs_badop */
242: { &vop_readlink_desc, fifo_readlink }, /* genfs_badop */
243: { &vop_abortop_desc, fifo_abortop }, /* genfs_badop */
1.26 pooka 244: { &vop_inactive_desc, puffs_inactive }, /* REAL inactive */
245: { &vop_reclaim_desc, puffs_reclaim }, /* REAL reclaim */
246: { &vop_lock_desc, puffs_lock }, /* REAL lock */
247: { &vop_unlock_desc, puffs_unlock }, /* REAL unlock */
1.6 pooka 248: { &vop_bmap_desc, fifo_bmap }, /* dummy */
249: { &vop_strategy_desc, fifo_strategy }, /* genfs_badop */
1.26 pooka 250: { &vop_print_desc, puffs_print }, /* REAL print */
251: { &vop_islocked_desc, puffs_islocked }, /* REAL islocked */
1.6 pooka 252: { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */
253: { &vop_advlock_desc, fifo_advlock }, /* genfs_einval */
254: { &vop_bwrite_desc, vn_bwrite }, /* bwrite */
255: { &vop_putpages_desc, fifo_putpages }, /* genfs_null_putpages*/
256: #if 0
257: { &vop_openextattr_desc, _openextattr }, /* openextattr */
258: { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */
259: { &vop_getextattr_desc, _getextattr }, /* getextattr */
260: { &vop_setextattr_desc, _setextattr }, /* setextattr */
261: { &vop_listextattr_desc, _listextattr }, /* listextattr */
262: { &vop_deleteextattr_desc, _deleteextattr }, /* deleteextattr */
263: #endif
264: { NULL, NULL }
265: };
266: const struct vnodeopv_desc puffs_fifoop_opv_desc =
267: { &puffs_fifoop_p, puffs_fifoop_entries };
268:
269:
1.17 pooka 270: /* "real" vnode operations */
271: int (**puffs_msgop_p)(void *);
272: const struct vnodeopv_entry_desc puffs_msgop_entries[] = {
273: { &vop_default_desc, vn_default_error },
274: { &vop_create_desc, puffs_create }, /* create */
275: { &vop_mknod_desc, puffs_mknod }, /* mknod */
276: { &vop_open_desc, puffs_open }, /* open */
277: { &vop_close_desc, puffs_close }, /* close */
278: { &vop_access_desc, puffs_access }, /* access */
279: { &vop_getattr_desc, puffs_getattr }, /* getattr */
280: { &vop_setattr_desc, puffs_setattr }, /* setattr */
281: { &vop_read_desc, puffs_read }, /* read */
282: { &vop_write_desc, puffs_write }, /* write */
283: { &vop_fcntl_desc, puffs_fcntl }, /* fcntl */
284: { &vop_ioctl_desc, puffs_ioctl }, /* ioctl */
285: { &vop_fsync_desc, puffs_fsync }, /* fsync */
286: { &vop_seek_desc, puffs_seek }, /* seek */
287: { &vop_remove_desc, puffs_remove }, /* remove */
288: { &vop_link_desc, puffs_link }, /* link */
289: { &vop_rename_desc, puffs_rename }, /* rename */
290: { &vop_mkdir_desc, puffs_mkdir }, /* mkdir */
291: { &vop_rmdir_desc, puffs_rmdir }, /* rmdir */
292: { &vop_symlink_desc, puffs_symlink }, /* symlink */
293: { &vop_readdir_desc, puffs_readdir }, /* readdir */
294: { &vop_readlink_desc, puffs_readlink }, /* readlink */
295: { &vop_print_desc, puffs_print }, /* print */
296: { &vop_islocked_desc, puffs_islocked }, /* islocked */
297: { &vop_pathconf_desc, puffs_pathconf }, /* pathconf */
298: { &vop_advlock_desc, puffs_advlock }, /* advlock */
299: { &vop_getpages_desc, genfs_getpages }, /* getpages */
300: { &vop_putpages_desc, genfs_putpages }, /* putpages */
301: { NULL, NULL }
302: };
303: const struct vnodeopv_desc puffs_msgop_opv_desc =
304: { &puffs_msgop_p, puffs_msgop_entries };
305:
1.5 pooka 306:
1.1 pooka 307: #define LOCKEDVP(a) (VOP_ISLOCKED(a) ? (a) : NULL)
308:
309:
1.17 pooka 310: /*
311: * This is a generic vnode operation handler. It checks if the necessary
312: * operations for the called vnode operation are implemented by userspace
313: * and either returns a dummy return value or proceeds to call the real
314: * vnode operation from puffs_msgop_v.
315: *
316: * XXX: this should described elsewhere and autogenerated, the complexity
317: * of the vnode operations vectors and their interrelationships is also
318: * getting a bit out of hand. Another problem is that we need this same
319: * information in the fs server code, so keeping the two in sync manually
320: * is not a viable (long term) plan.
321: */
322:
323: /* not supported, handle locking protocol */
324: #define CHECKOP_NOTSUPP(op) \
325: case VOP_##op##_DESCOFFSET: \
326: if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0) \
327: return genfs_eopnotsupp(v); \
328: break
329:
330: /* always succeed, no locking */
331: #define CHECKOP_SUCCESS(op) \
332: case VOP_##op##_DESCOFFSET: \
333: if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0) \
334: return 0; \
335: break
336:
337: int
338: puffs_checkop(void *v)
339: {
340: struct vop_generic_args /* {
341: struct vnodeop_desc *a_desc;
342: spooky mystery contents;
343: } */ *ap = v;
344: struct vnodeop_desc *desc = ap->a_desc;
345: struct puffs_mount *pmp;
346: struct vnode *vp;
347: int offset;
348:
349: DPRINTF_VERBOSE(("checkop call %s (%d)\n",
350: ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset));
351:
352: offset = ap->a_desc->vdesc_vp_offsets[0];
353: #ifdef DIAGNOSTIC
354: if (offset == VDESC_NO_OFFSET)
355: panic("puffs_checkop: no vnode, why did you call me?");
356: #endif
357: vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap);
358: pmp = MPTOPUFFSMP(vp->v_mount);
359:
1.18 pooka 360: if ((pmp->pmp_flags & PUFFS_KFLAG_ALLOPS) == 0) {
1.17 pooka 361: switch (desc->vdesc_offset) {
362: CHECKOP_NOTSUPP(CREATE);
363: CHECKOP_NOTSUPP(MKNOD);
364: CHECKOP_NOTSUPP(GETATTR);
365: CHECKOP_NOTSUPP(SETATTR);
366: CHECKOP_NOTSUPP(READ);
367: CHECKOP_NOTSUPP(WRITE);
368: CHECKOP_NOTSUPP(FCNTL);
369: CHECKOP_NOTSUPP(IOCTL);
370: CHECKOP_NOTSUPP(REMOVE);
371: CHECKOP_NOTSUPP(LINK);
372: CHECKOP_NOTSUPP(RENAME);
373: CHECKOP_NOTSUPP(MKDIR);
374: CHECKOP_NOTSUPP(RMDIR);
375: CHECKOP_NOTSUPP(SYMLINK);
376: CHECKOP_NOTSUPP(READDIR);
377: CHECKOP_NOTSUPP(READLINK);
378: CHECKOP_NOTSUPP(PRINT);
379: CHECKOP_NOTSUPP(PATHCONF);
380: CHECKOP_NOTSUPP(ADVLOCK);
381:
382: CHECKOP_SUCCESS(OPEN);
383: CHECKOP_SUCCESS(CLOSE);
384: CHECKOP_SUCCESS(ACCESS);
385: CHECKOP_SUCCESS(SEEK);
386:
1.31 pooka 387: /* XXXfixme: read w/o write && cache == bad bad bad */
1.17 pooka 388: case VOP_GETPAGES_DESCOFFSET:
389: if (!EXISTSOP(pmp, READ))
390: return genfs_eopnotsupp(v);
391: break;
392:
393: case VOP_PUTPAGES_DESCOFFSET:
394: if (!EXISTSOP(pmp, WRITE))
395: return genfs_null_putpages(v);
396: break;
397:
398: default:
399: panic("puffs_checkop: unhandled vnop %d",
400: desc->vdesc_offset);
401: }
402: }
403:
404: return VOCALL(puffs_msgop_p, ap->a_desc->vdesc_offset, v);
405: }
406:
407:
1.1 pooka 408: int
409: puffs_lookup(void *v)
410: {
411: struct vop_lookup_args /* {
1.17 pooka 412: const struct vnodeop_desc *a_desc;
413: struct vnode *a_dvp;
414: struct vnode **a_vpp;
415: struct componentname *a_cnp;
1.1 pooka 416: } */ *ap = v;
417: struct puffs_mount *pmp;
418: struct componentname *cnp;
419: struct vnode *vp, *dvp;
1.32 pooka 420: struct puffs_node *dpn;
1.22 chs 421: int isdot;
1.1 pooka 422: int error;
423:
424: PUFFS_VNREQ(lookup);
425:
426: pmp = MPTOPUFFSMP(ap->a_dvp->v_mount);
427: cnp = ap->a_cnp;
428: dvp = ap->a_dvp;
429: *ap->a_vpp = NULL;
430:
431: /* first things first: check access */
432: error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_lwp);
433: if (error)
434: return error;
435:
436: isdot = cnp->cn_namelen == 1 && *cnp->cn_nameptr == '.';
437:
438: DPRINTF(("puffs_lookup: \"%s\", parent vnode %p, op: %lx\n",
439: cnp->cn_nameptr, dvp, cnp->cn_nameiop));
440:
441: /*
442: * Check if someone fed it into the cache
443: */
1.23 pooka 444: if (PUFFS_DOCACHE(pmp)) {
445: error = cache_lookup(dvp, ap->a_vpp, cnp);
1.30 pooka 446:
1.23 pooka 447: if (error >= 0)
448: return error;
449: }
1.1 pooka 450:
451: if (isdot) {
452: vp = ap->a_dvp;
453: vref(vp);
454: *ap->a_vpp = vp;
455: return 0;
456: }
457:
458: puffs_makecn(&lookup_arg.pvnr_cn, cnp);
459:
460: if (cnp->cn_flags & ISDOTDOT)
461: VOP_UNLOCK(dvp, 0);
462:
463: error = puffs_vntouser(pmp, PUFFS_VN_LOOKUP,
464: &lookup_arg, sizeof(lookup_arg), VPTOPNC(dvp), LOCKEDVP(dvp), NULL);
465: DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error));
466:
467: /*
1.23 pooka 468: * In case of error, there is no new vnode to play with, so be
469: * happy with the NULL value given to vpp in the beginning.
470: * Also, check if this really was an error or the target was not
471: * present. Either treat it as a non-error for CREATE/RENAME or
472: * enter the component into the negative name cache (if desired).
1.1 pooka 473: */
474: if (error) {
1.10 pooka 475: if (error == ENOENT) {
1.1 pooka 476: if ((cnp->cn_flags & ISLASTCN)
477: && (cnp->cn_nameiop == CREATE
478: || cnp->cn_nameiop == RENAME)) {
479: cnp->cn_flags |= SAVENAME;
480: error = EJUSTRETURN;
1.23 pooka 481: } else {
482: if ((cnp->cn_flags & MAKEENTRY)
483: && PUFFS_DOCACHE(pmp))
484: cache_enter(dvp, NULL, cnp);
1.10 pooka 485: }
1.1 pooka 486: }
1.22 chs 487: goto errout;
1.1 pooka 488: }
489:
1.32 pooka 490: /*
491: * Check that we don't get our parent node back, that would cause
492: * a pretty obvious deadlock.
493: */
494: dpn = dvp->v_data;
495: if (lookup_arg.pvnr_newnode == dpn->pn_cookie) {
496: error = EINVAL;
497: goto errout;
498: }
499:
500: /* XXX: race here */
1.33 pooka 501: /* XXX2: this check for node existence twice */
1.30 pooka 502: vp = puffs_pnode2vnode(pmp, lookup_arg.pvnr_newnode, 1);
1.1 pooka 503: if (!vp) {
504: error = puffs_getvnode(dvp->v_mount,
1.5 pooka 505: lookup_arg.pvnr_newnode, lookup_arg.pvnr_vtype,
1.8 pooka 506: lookup_arg.pvnr_size, lookup_arg.pvnr_rdev, &vp);
1.1 pooka 507: if (error) {
1.22 chs 508: goto errout;
1.1 pooka 509: }
510: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
511: }
1.23 pooka 512: *ap->a_vpp = vp;
1.1 pooka 513:
1.23 pooka 514: if ((cnp->cn_flags & MAKEENTRY) != 0 && PUFFS_DOCACHE(pmp))
1.1 pooka 515: cache_enter(dvp, vp, cnp);
516:
1.23 pooka 517: errout:
1.22 chs 518: if (cnp->cn_flags & ISDOTDOT)
519: vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
520:
521: return error;
1.1 pooka 522: }
523:
524: int
525: puffs_create(void *v)
526: {
527: struct vop_create_args /* {
528: const struct vnodeop_desc *a_desc;
529: struct vnode *a_dvp;
530: struct vnode **a_vpp;
531: struct componentname *a_cnp;
532: struct vattr *a_vap;
533: } */ *ap = v;
534: int error;
535:
536: PUFFS_VNREQ(create);
537:
538: puffs_makecn(&create_arg.pvnr_cn, ap->a_cnp);
539: create_arg.pvnr_va = *ap->a_vap;
540:
541: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_CREATE,
542: &create_arg, sizeof(create_arg), VPTOPNC(ap->a_dvp),
543: ap->a_dvp, NULL);
544: if (error)
1.4 pooka 545: goto out;
1.1 pooka 546:
1.4 pooka 547: error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5 pooka 548: create_arg.pvnr_newnode, ap->a_cnp, ap->a_vap->va_type, 0);
1.4 pooka 549:
550: out:
551: if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
552: PNBUF_PUT(ap->a_cnp->cn_pnbuf);
553: vput(ap->a_dvp);
554: return error;
1.1 pooka 555: }
556:
557: int
558: puffs_mknod(void *v)
559: {
560: struct vop_mknod_args /* {
561: const struct vnodeop_desc *a_desc;
562: struct vnode *a_dvp;
563: struct vnode **a_vpp;
564: struct componentname *a_cnp;
565: struct vattr *a_vap;
566: } */ *ap = v;
567: int error;
568:
569: PUFFS_VNREQ(mknod);
570:
571: puffs_makecn(&mknod_arg.pvnr_cn, ap->a_cnp);
572: mknod_arg.pvnr_va = *ap->a_vap;
573:
574: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_MKNOD,
575: &mknod_arg, sizeof(mknod_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
576: if (error)
1.4 pooka 577: goto out;
1.1 pooka 578:
1.4 pooka 579: error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5 pooka 580: mknod_arg.pvnr_newnode, ap->a_cnp, ap->a_vap->va_type,
581: ap->a_vap->va_rdev);
1.4 pooka 582:
583: out:
584: if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
585: PNBUF_PUT(ap->a_cnp->cn_pnbuf);
586: vput(ap->a_dvp);
587: return error;
1.1 pooka 588: }
589:
590: int
591: puffs_open(void *v)
592: {
593: struct vop_open_args /* {
594: const struct vnodeop_desc *a_desc;
595: struct vnode *a_vp;
596: int a_mode;
597: kauth_cred_t a_cred;
598: struct lwp *a_l;
599: } */ *ap = v;
600:
601: PUFFS_VNREQ(open);
602:
603: open_arg.pvnr_mode = ap->a_mode;
604: puffs_credcvt(&open_arg.pvnr_cred, ap->a_cred);
605: open_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
606:
607: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_OPEN,
608: &open_arg, sizeof(open_arg), VPTOPNC(ap->a_vp), ap->a_vp, NULL);
609: }
610:
611: int
612: puffs_close(void *v)
613: {
614: struct vop_close_args /* {
615: const struct vnodeop_desc *a_desc;
616: struct vnode *a_vp;
617: int a_fflag;
618: kauth_cred_t a_cred;
619: struct lwp *a_l;
620: } */ *ap = v;
621:
622: PUFFS_VNREQ(close);
623:
624: close_arg.pvnr_fflag = ap->a_fflag;
625: puffs_credcvt(&close_arg.pvnr_cred, ap->a_cred);
626: close_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
627:
628: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_CLOSE,
629: &close_arg, sizeof(close_arg), VPTOPNC(ap->a_vp), ap->a_vp, NULL);
630: }
631:
632: int
633: puffs_access(void *v)
634: {
635: struct vop_access_args /* {
636: const struct vnodeop_desc *a_desc;
637: struct vnode *a_vp;
638: int a_mode;
639: kauth_cred_t a_cred;
640: struct lwp *a_l;
641: } */ *ap = v;
642:
643: PUFFS_VNREQ(access);
644:
645: access_arg.pvnr_mode = ap->a_mode;
646: access_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
647: puffs_credcvt(&access_arg.pvnr_cred, ap->a_cred);
648:
1.8 pooka 649: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_ACCESS,
1.1 pooka 650: &access_arg, sizeof(access_arg), VPTOPNC(ap->a_vp), ap->a_vp, NULL);
651: }
652:
653: int
654: puffs_getattr(void *v)
655: {
656: struct vop_getattr_args /* {
657: const struct vnodeop_desc *a_desc;
658: struct vnode *a_vp;
659: struct vattr *a_vap;
660: kauth_cred_t a_cred;
661: struct lwp *a_l;
662: } */ *ap = v;
1.13 pooka 663: struct mount *mp;
1.1 pooka 664: int error;
665:
666: PUFFS_VNREQ(getattr);
667:
1.13 pooka 668: mp = ap->a_vp->v_mount;
669:
1.1 pooka 670: vattr_null(&getattr_arg.pvnr_va);
671: puffs_credcvt(&getattr_arg.pvnr_cred, ap->a_cred);
672: getattr_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
673:
674: /*
675: * XXX + XX (dos equis): this can't go through the unlock/lock
676: * cycle, since it can be called from uvn_attach(), which fiddles
677: * around with VXLOCK and therefore breaks vn_lock(). Proper
678: * fix pending.
679: */
680: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_GETATTR,
681: &getattr_arg, sizeof(getattr_arg), VPTOPNC(ap->a_vp),
682: NULL /* XXXseeabove: should be LOCKEDVP(ap->a_vp) */, NULL);
683: if (error)
684: return error;
685:
686: (void)memcpy(ap->a_vap, &getattr_arg.pvnr_va, sizeof(struct vattr));
687:
1.13 pooka 688: /*
689: * fill in information userspace does not have
690: * XXX: but would it be better to do fsid at the generic level?
691: */
692: ap->a_vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
693:
1.1 pooka 694: return 0;
695: }
696:
697: int
698: puffs_setattr(void *v)
699: {
700: struct vop_getattr_args /* {
701: const struct vnodeop_desc *a_desc;
702: struct vnode *a_vp;
703: struct vattr *a_vap;
704: kauth_cred_t a_cred;
705: struct lwp *a_l;
706: } */ *ap = v;
1.8 pooka 707: int error;
1.1 pooka 708:
709: PUFFS_VNREQ(setattr);
710:
711: (void)memcpy(&setattr_arg.pvnr_va, ap->a_vap, sizeof(struct vattr));
712: puffs_credcvt(&setattr_arg.pvnr_cred, ap->a_cred);
713: setattr_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
714:
1.8 pooka 715: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_SETATTR,
1.1 pooka 716: &setattr_arg, sizeof(setattr_arg), VPTOPNC(ap->a_vp),
717: ap->a_vp, NULL);
1.8 pooka 718: if (error)
719: return error;
720:
721: if (ap->a_vap->va_size != VNOVAL)
722: uvm_vnp_setsize(ap->a_vp, ap->a_vap->va_size);
723:
724: return 0;
1.1 pooka 725: }
726:
727: int
1.3 pooka 728: puffs_inactive(void *v)
729: {
730: struct vop_inactive_args /* {
731: const struct vnodeop_desc *a_desc;
732: struct vnode *a_vp;
733: struct lwp *a_l;
734: } */ *ap = v;
1.17 pooka 735: struct puffs_mount *pmp;
1.3 pooka 736: struct puffs_node *pnode;
737: int rv, vnrefs;
738:
739: PUFFS_VNREQ(inactive);
740:
741: /*
742: * XXX: think about this after we really start unlocking
743: * when going to userspace
744: */
745: pnode = ap->a_vp->v_data;
746:
1.17 pooka 747: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
748:
1.3 pooka 749: inactive_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
750:
1.17 pooka 751: if (EXISTSOP(pmp, INACTIVE))
752: rv = puffs_vntouser(pmp, PUFFS_VN_INACTIVE,
753: &inactive_arg, sizeof(inactive_arg), VPTOPNC(ap->a_vp),
754: ap->a_vp, NULL);
755: else
756: rv = 1; /* see below */
1.3 pooka 757:
758: /* can't trust userspace return value? simulate safe answer */
759: if (rv)
760: vnrefs = 1;
761: else
762: vnrefs = inactive_arg.pvnr_backendrefs;
763:
764: VOP_UNLOCK(ap->a_vp, 0);
765:
766: /*
767: * user server thinks it's gone? then don't be afraid care,
768: * node's life was already all it would ever be
769: */
1.38 ! pooka 770: if (vnrefs == 0) {
! 771: pnode->pn_stat |= PNODE_NOREFS;
1.3 pooka 772: vrecycle(ap->a_vp, NULL, ap->a_l);
1.38 ! pooka 773: }
1.3 pooka 774:
775: return 0;
776: }
777:
1.34 pooka 778: /*
779: * always FAF, we don't really care if the server wants to fail to
780: * reclaim the node or not
781: */
1.3 pooka 782: int
1.1 pooka 783: puffs_reclaim(void *v)
784: {
785: struct vop_reclaim_args /* {
786: const struct vnodeop_desc *a_desc;
787: struct vnode *a_vp;
788: struct lwp *a_l;
789: } */ *ap = v;
790: struct puffs_mount *pmp;
1.34 pooka 791: struct puffs_vnreq_reclaim *reclaim_argp;
1.1 pooka 792:
1.17 pooka 793: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
794:
1.1 pooka 795: /*
796: * first things first: check if someone is trying to reclaim the
797: * root vnode. do not allow that to travel to userspace.
798: * Note that we don't need to take the lock similarly to
799: * puffs_root(), since there is only one of us.
800: */
801: if (ap->a_vp->v_flag & VROOT) {
802: #ifdef DIAGNOSTIC
803: simple_lock(&pmp->pmp_lock);
804: if (pmp->pmp_root == NULL)
805: panic("puffs_reclaim: releasing root vnode (%p) twice",
806: ap->a_vp);
807: simple_unlock(&pmp->pmp_lock);
808: #endif
809: pmp->pmp_root = NULL;
1.34 pooka 810: goto out;
1.1 pooka 811: }
812:
1.34 pooka 813: if (!EXISTSOP(pmp, RECLAIM))
814: goto out;
1.1 pooka 815:
1.34 pooka 816: reclaim_argp = malloc(sizeof(struct puffs_vnreq_reclaim),
817: M_PUFFS, M_WAITOK | M_ZERO);
818: reclaim_argp->pvnr_pid = puffs_lwp2pid(ap->a_l);
819:
820: puffs_vntouser_faf(pmp, PUFFS_VN_RECLAIM,
821: reclaim_argp, sizeof(struct puffs_vnreq_reclaim),
822: VPTOPNC(ap->a_vp));
1.1 pooka 823:
1.34 pooka 824: out:
1.23 pooka 825: if (PUFFS_DOCACHE(pmp))
826: cache_purge(ap->a_vp);
1.1 pooka 827: puffs_putvnode(ap->a_vp);
828:
829: return 0;
830: }
831:
832: int
833: puffs_readdir(void *v)
834: {
835: struct vop_readdir_args /* {
836: const struct vnodeop_desc *a_desc;
837: struct vnode *a_vp;
838: struct uio *a_uio;
839: kauth_cred_t a_cred;
840: int *a_eofflag;
841: off_t **a_cookies;
842: int *a_ncookies;
843: } */ *ap = v;
844: struct puffs_vnreq_readdir *readdir_argp;
845: size_t argsize;
846: struct uio *uio = ap->a_uio;
847: size_t howmuch;
848: int error;
849:
850: /* worry about these later */
851: if (!(ap->a_cookies == NULL && ap->a_ncookies == NULL))
852: return EOPNOTSUPP;
853:
854: argsize = sizeof(struct puffs_vnreq_readdir);
855: readdir_argp = malloc(argsize, M_PUFFS, M_ZERO | M_WAITOK);
856:
857: puffs_credcvt(&readdir_argp->pvnr_cred, ap->a_cred);
858: readdir_argp->pvnr_offset = uio->uio_offset;
859: readdir_argp->pvnr_resid = uio->uio_resid;
860:
861: error = puffs_vntouser_adjbuf(MPTOPUFFSMP(ap->a_vp->v_mount),
862: PUFFS_VN_READDIR, (void **)&readdir_argp, &argsize,
1.19 pooka 863: readdir_argp->pvnr_resid, VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1.1 pooka 864: if (error)
865: goto out;
866:
867: /* userspace is cheating? */
868: if (readdir_argp->pvnr_resid > uio->uio_resid) {
869: error = EINVAL;
870: goto out;
871: }
872:
873: /* bouncy-wouncy with the directory data */
874: howmuch = uio->uio_resid - readdir_argp->pvnr_resid;
1.29 pooka 875: /* XXX: we could let userlandia tell its opinion first time 'round */
876: if (howmuch == 0) {
877: *ap->a_eofflag = 1;
878: goto out;
879: }
1.1 pooka 880: error = uiomove(readdir_argp->pvnr_dent, howmuch, uio);
881: if (error)
882: goto out;
883: uio->uio_offset = readdir_argp->pvnr_offset;
884:
885: out:
886: free(readdir_argp, M_PUFFS);
887: return error;
888: }
889:
890: int
891: puffs_poll(void *v)
892: {
893: struct vop_poll_args /* {
894: const struct vnodeop_desc *a_desc;
895: struct vnode *a_vp;
896: int a_events;
897: struct lwp *a_l;
898: } */ *ap = v;
899:
900: PUFFS_VNREQ(poll);
901:
902: poll_arg.pvnr_events = ap->a_events;
903: poll_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
904:
905: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_POLL,
906: &poll_arg, sizeof(poll_arg), VPTOPNC(ap->a_vp), NULL, NULL);
907: }
908:
909: int
910: puffs_fsync(void *v)
911: {
912: struct vop_fsync_args /* {
913: const struct vnodeop_desc *a_desc;
914: struct vnode *a_vp;
915: kauth_cred_t a_cred;
916: int a_flags;
917: off_t a_offlo;
918: off_t a_offhi;
919: struct lwp *a_l;
920: } */ *ap = v;
1.31 pooka 921: struct puffs_mount *pmp;
1.8 pooka 922: struct puffs_vnreq_fsync *fsync_argp;
923: struct vnode *vp;
1.38 ! pooka 924: struct puffs_node *pn;
1.35 pooka 925: int pflags, error, dofaf;
1.1 pooka 926:
927: PUFFS_VNREQ(fsync);
928:
1.8 pooka 929: vp = ap->a_vp;
1.38 ! pooka 930: pn = VPTOPP(vp);
1.31 pooka 931: pmp = MPTOPUFFSMP(vp->v_mount);
1.8 pooka 932:
933: pflags = PGO_CLEANIT;
1.31 pooka 934: if (ap->a_flags & FSYNC_WAIT)
1.8 pooka 935: pflags |= PGO_SYNCIO;
936:
937: /*
938: * flush pages to avoid being overly dirty
939: */
940: simple_lock(&vp->v_interlock);
941: error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
942: round_page(ap->a_offhi), pflags);
943: if (error)
944: return error;
945:
1.31 pooka 946: /*
947: * HELLO! We exit already here if the user server does not
1.38 ! pooka 948: * support fsync OR if we should call fsync for a node which
! 949: * has references neither in the kernel or the fs server.
! 950: * Otherwise we continue to issue fsync() forward.
1.31 pooka 951: */
1.38 ! pooka 952: if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_NOREFS))
1.31 pooka 953: return 0;
954:
1.35 pooka 955: dofaf = (ap->a_flags & FSYNC_WAIT) == 0;
956: /*
957: * We abuse VXLOCK to mean "vnode is going to die", so we issue
958: * only FAFs for those. Otherwise there's a danger of deadlock,
959: * since the execution context here might be the user server
960: * doing some operation on another fs, which in turn caused a
961: * vnode to be reclaimed from the freelist for this fs.
962: */
963: if (dofaf == 0) {
964: simple_lock(&vp->v_interlock);
965: if (vp->v_flag & VXLOCK)
966: dofaf = 1;
967: simple_unlock(&vp->v_interlock);
968: }
969:
970: if (dofaf == 0) {
1.31 pooka 971: fsync_argp = &fsync_arg;
972: } else {
973: fsync_argp = malloc(sizeof(struct puffs_vnreq_fsync),
974: M_PUFFS, M_ZERO | M_NOWAIT);
975: if (fsync_argp == NULL)
976: return ENOMEM;
977: }
978:
1.8 pooka 979: puffs_credcvt(&fsync_argp->pvnr_cred, ap->a_cred);
980: fsync_argp->pvnr_flags = ap->a_flags;
981: fsync_argp->pvnr_offlo = ap->a_offlo;
982: fsync_argp->pvnr_offhi = ap->a_offhi;
983: fsync_argp->pvnr_pid = puffs_lwp2pid(ap->a_l);
1.1 pooka 984:
985: /*
986: * XXX: see comment at puffs_getattr about locking
1.8 pooka 987: *
988: * If we are not required to wait, do a FAF operation.
989: * Otherwise block here.
1.1 pooka 990: */
1.35 pooka 991: if (dofaf == 0) {
1.8 pooka 992: error = puffs_vntouser(MPTOPUFFSMP(vp->v_mount),
993: PUFFS_VN_FSYNC, fsync_argp, sizeof(*fsync_argp),
994: VPTOPNC(vp), NULL /* XXXshouldbe: vp */, NULL);
995: } else {
996: /* FAF is always "succesful" */
997: error = 0;
998: puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount),
999: PUFFS_VN_FSYNC, fsync_argp, sizeof(*fsync_argp),
1000: VPTOPNC(vp));
1001: }
1002:
1003: return error;
1.1 pooka 1004: }
1005:
1006: int
1007: puffs_seek(void *v)
1008: {
1009: struct vop_seek_args /* {
1010: const struct vnodeop_desc *a_desc;
1011: struct vnode *a_vp;
1012: off_t a_oldoff;
1013: off_t a_newoff;
1014: kauth_cred_t a_cred;
1015: } */ *ap = v;
1016:
1017: PUFFS_VNREQ(seek);
1018:
1019: seek_arg.pvnr_oldoff = ap->a_oldoff;
1020: seek_arg.pvnr_newoff = ap->a_newoff;
1021: puffs_credcvt(&seek_arg.pvnr_cred, ap->a_cred);
1022:
1023: /*
1024: * XXX: seems like seek is called with an unlocked vp, but
1025: * it can't hurt to play safe
1026: */
1027: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_SEEK,
1028: &seek_arg, sizeof(seek_arg), VPTOPNC(ap->a_vp),
1029: LOCKEDVP(ap->a_vp), NULL);
1030: }
1031:
1032: int
1033: puffs_remove(void *v)
1034: {
1035: struct vop_remove_args /* {
1036: const struct vnodeop_desc *a_desc;
1037: struct vnode *a_dvp;
1038: struct vnode *a_vp;
1039: struct componentname *a_cnp;
1040: } */ *ap = v;
1041: int error;
1042:
1043: PUFFS_VNREQ(remove);
1044:
1045: remove_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
1046: puffs_makecn(&remove_arg.pvnr_cn, ap->a_cnp);
1047:
1048: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_REMOVE,
1049: &remove_arg, sizeof(remove_arg), VPTOPNC(ap->a_dvp),
1050: ap->a_dvp, ap->a_vp);
1051:
1052: vput(ap->a_vp);
1.25 pooka 1053: if (ap->a_dvp == ap->a_vp)
1054: vrele(ap->a_dvp);
1055: else
1056: vput(ap->a_dvp);
1.1 pooka 1057:
1058: return error;
1059: }
1060:
1061: int
1062: puffs_mkdir(void *v)
1063: {
1064: struct vop_mkdir_args /* {
1065: const struct vnodeop_desc *a_desc;
1066: struct vnode *a_dvp;
1067: struct vnode **a_vpp;
1068: struct componentname *a_cnp;
1069: struct vattr *a_vap;
1070: } */ *ap = v;
1071: int error;
1072:
1073: PUFFS_VNREQ(mkdir);
1074:
1075: puffs_makecn(&mkdir_arg.pvnr_cn, ap->a_cnp);
1076: mkdir_arg.pvnr_va = *ap->a_vap;
1077:
1078: /* XXX: wouldn't need to relock dvp, but that's life */
1079: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_MKDIR,
1080: &mkdir_arg, sizeof(mkdir_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
1081: if (error)
1.4 pooka 1082: goto out;
1.1 pooka 1083:
1.4 pooka 1084: error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5 pooka 1085: mkdir_arg.pvnr_newnode, ap->a_cnp, VDIR, 0);
1.4 pooka 1086:
1087: out:
1088: if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
1089: PNBUF_PUT(ap->a_cnp->cn_pnbuf);
1090: vput(ap->a_dvp);
1091: return error;
1.1 pooka 1092: }
1093:
1094: int
1095: puffs_rmdir(void *v)
1096: {
1097: struct vop_rmdir_args /* {
1098: const struct vnodeop_desc *a_desc;
1099: struct vnode *a_dvp;
1100: struct vnode *a_vp;
1101: struct componentname *a_cnp;
1102: } */ *ap = v;
1103: int error;
1104:
1105: PUFFS_VNREQ(rmdir);
1106:
1107: rmdir_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
1108: puffs_makecn(&rmdir_arg.pvnr_cn, ap->a_cnp);
1109:
1110: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_RMDIR,
1111: &rmdir_arg, sizeof(rmdir_arg), VPTOPNC(ap->a_dvp),
1112: ap->a_dvp, ap->a_vp);
1113:
1.23 pooka 1114: /* XXX: some call cache_purge() *for both vnodes* here, investigate */
1115:
1.1 pooka 1116: vput(ap->a_dvp);
1117: vput(ap->a_vp);
1118:
1119: return error;
1120: }
1121:
1122: int
1123: puffs_link(void *v)
1124: {
1125: struct vop_link_args /* {
1126: const struct vnodeop_desc *a_desc;
1127: struct vnode *a_dvp;
1128: struct vnode *a_vp;
1129: struct componentname *a_cnp;
1130: } */ *ap = v;
1131: int error;
1132:
1133: PUFFS_VNREQ(link);
1134:
1135: link_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
1136: puffs_makecn(&link_arg.pvnr_cn, ap->a_cnp);
1137:
1138: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_LINK,
1139: &link_arg, sizeof(link_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
1140:
1141: vput(ap->a_dvp);
1142:
1143: return error;
1144: }
1145:
1146: int
1147: puffs_symlink(void *v)
1148: {
1149: struct vop_symlink_args /* {
1150: const struct vnodeop_desc *a_desc;
1151: struct vnode *a_dvp;
1152: struct vnode **a_vpp;
1153: struct componentname *a_cnp;
1154: struct vattr *a_vap;
1155: char *a_target;
1156: } */ *ap = v;
1157: int error;
1158:
1159: PUFFS_VNREQ(symlink); /* XXX: large structure */
1160:
1161: *ap->a_vpp = NULL;
1162:
1163: puffs_makecn(&symlink_arg.pvnr_cn, ap->a_cnp);
1164: symlink_arg.pvnr_va = *ap->a_vap;
1165: (void)strlcpy(symlink_arg.pvnr_link, ap->a_target,
1166: sizeof(symlink_arg.pvnr_link));
1167:
1168: /* XXX: don't need to relock parent */
1169: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount),
1170: PUFFS_VN_SYMLINK, &symlink_arg, sizeof(symlink_arg),
1171: VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
1172: if (error)
1.4 pooka 1173: goto out;
1.1 pooka 1174:
1.4 pooka 1175: error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5 pooka 1176: symlink_arg.pvnr_newnode, ap->a_cnp, VLNK, 0);
1.4 pooka 1177:
1178: out:
1179: if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
1180: PNBUF_PUT(ap->a_cnp->cn_pnbuf);
1181: vput(ap->a_dvp);
1182: return error;
1.1 pooka 1183: }
1184:
1185: int
1186: puffs_readlink(void *v)
1187: {
1188: struct vop_readlink_args /* {
1189: const struct vnodeop_desc *a_desc;
1190: struct vnode *a_vp;
1191: struct uio *a_uio;
1192: kauth_cred_t a_cred;
1193: } */ *ap = v;
1194: int error;
1195:
1196: PUFFS_VNREQ(readlink);
1197:
1198: puffs_credcvt(&readlink_arg.pvnr_cred, ap->a_cred);
1199: readlink_arg.pvnr_linklen = sizeof(readlink_arg.pvnr_link);
1200:
1201: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
1202: PUFFS_VN_READLINK, &readlink_arg, sizeof(readlink_arg),
1203: VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1204: if (error)
1205: return error;
1206:
1207: readlink_arg.pvnr_link[readlink_arg.pvnr_linklen] = '\0';
1208: return uiomove(&readlink_arg.pvnr_link, readlink_arg.pvnr_linklen,
1209: ap->a_uio);
1210: }
1211:
1212: /* XXXXXXX: think about locking & userspace op delocking... */
1213: int
1214: puffs_rename(void *v)
1215: {
1216: struct vop_rename_args /* {
1217: const struct vnodeop_desc *a_desc;
1218: struct vnode *a_fdvp;
1219: struct vnode *a_fvp;
1220: struct componentname *a_fcnp;
1221: struct vnode *a_tdvp;
1222: struct vnode *a_tvp;
1223: struct componentname *a_tcnp;
1224: } */ *ap = v;
1225: int error;
1226:
1227: PUFFS_VNREQ(rename);
1228:
1229: if (ap->a_fvp->v_mount != ap->a_tdvp->v_mount) {
1230: error = EXDEV;
1231: goto out;
1232: }
1233:
1234: rename_arg.pvnr_cookie_src = VPTOPNC(ap->a_fvp);
1235: rename_arg.pvnr_cookie_targdir = VPTOPNC(ap->a_tdvp);
1236: if (ap->a_tvp)
1237: rename_arg.pvnr_cookie_targ = VPTOPNC(ap->a_tvp);
1238: else
1239: rename_arg.pvnr_cookie_targ = NULL;
1240: puffs_makecn(&rename_arg.pvnr_cn_src, ap->a_fcnp);
1241: puffs_makecn(&rename_arg.pvnr_cn_targ, ap->a_tcnp);
1242:
1243: error = puffs_vntouser(MPTOPUFFSMP(ap->a_fdvp->v_mount),
1244: PUFFS_VN_RENAME, &rename_arg, sizeof(rename_arg),
1245: VPTOPNC(ap->a_fdvp), NULL, NULL);
1246:
1247: out:
1248: if (ap->a_tvp != NULL)
1249: vput(ap->a_tvp);
1.28 pooka 1250: if (ap->a_tdvp == ap->a_tvp)
1251: vrele(ap->a_tdvp);
1252: else
1253: vput(ap->a_tdvp);
1.1 pooka 1254:
1255: vrele(ap->a_fdvp);
1256: vrele(ap->a_fvp);
1257:
1258: return error;
1259: }
1260:
1261: int
1262: puffs_read(void *v)
1263: {
1264: struct vop_read_args /* {
1265: const struct vnodeop_desc *a_desc;
1266: struct vnode *a_vp;
1267: struct uio *a_uio;
1268: int a_ioflag;
1269: kauth_cred_t a_cred;
1270: } */ *ap = v;
1271: struct puffs_vnreq_read *read_argp;
1272: struct puffs_mount *pmp;
1.8 pooka 1273: struct vnode *vp;
1.1 pooka 1274: struct uio *uio;
1.8 pooka 1275: void *win;
1.1 pooka 1276: size_t tomove, argsize;
1.8 pooka 1277: vsize_t bytelen;
1.11 pooka 1278: int error, ubcflags;
1.1 pooka 1279:
1280: uio = ap->a_uio;
1.8 pooka 1281: vp = ap->a_vp;
1282: read_argp = NULL;
1283: error = 0;
1.11 pooka 1284: pmp = MPTOPUFFSMP(vp->v_mount);
1.1 pooka 1285:
1.8 pooka 1286: /* std sanity */
1287: if (uio->uio_resid == 0)
1288: return 0;
1289: if (uio->uio_offset < 0)
1290: return EINVAL;
1.1 pooka 1291:
1.23 pooka 1292: if (vp->v_type == VREG && PUFFS_DOCACHE(pmp)) {
1.8 pooka 1293: const int advice = IO_ADV_DECODE(ap->a_ioflag);
1.1 pooka 1294:
1.12 pooka 1295: ubcflags = 0;
1.15 pooka 1296: if (UBC_WANT_UNMAP(vp))
1.12 pooka 1297: ubcflags = UBC_UNMAP;
1298:
1.8 pooka 1299: while (uio->uio_resid > 0) {
1300: bytelen = MIN(uio->uio_resid,
1301: vp->v_size - uio->uio_offset);
1302: if (bytelen == 0)
1303: break;
1304:
1305: win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
1306: &bytelen, advice, UBC_READ);
1307: error = uiomove(win, bytelen, uio);
1.11 pooka 1308: ubc_release(win, ubcflags);
1.8 pooka 1309: if (error)
1310: break;
1.1 pooka 1311: }
1312:
1.8 pooka 1313: if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
1314: puffs_updatenode(vp, PUFFS_UPDATEATIME);
1315: } else {
1.1 pooka 1316: /*
1.15 pooka 1317: * in case it's not a regular file or we're operating
1318: * uncached, do read in the old-fashioned style,
1319: * i.e. explicit read operations
1.1 pooka 1320: */
1321:
1322: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.8 pooka 1323: argsize = sizeof(struct puffs_vnreq_read);
1324: read_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
1325:
1326: error = 0;
1327: while (uio->uio_resid > 0) {
1328: read_argp->pvnr_ioflag = ap->a_ioflag;
1329: read_argp->pvnr_resid = tomove;
1330: read_argp->pvnr_offset = uio->uio_offset;
1331: puffs_credcvt(&read_argp->pvnr_cred, ap->a_cred);
1332:
1333: argsize = sizeof(struct puffs_vnreq_read);
1334: error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
1335: (void **)&read_argp, &argsize,
1.19 pooka 1336: read_argp->pvnr_resid, VPTOPNC(ap->a_vp),
1.8 pooka 1337: ap->a_vp, NULL);
1338: if (error)
1339: break;
1340:
1341: if (read_argp->pvnr_resid > tomove) {
1342: error = EINVAL;
1343: break;
1344: }
1345:
1346: error = uiomove(read_argp->pvnr_data,
1347: tomove - read_argp->pvnr_resid, uio);
1348:
1349: /*
1350: * in case the file is out of juice, resid from
1351: * userspace is != 0. and the error-case is
1352: * quite obvious
1353: */
1354: if (error || read_argp->pvnr_resid)
1355: break;
1356:
1357: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1358: }
1.1 pooka 1359: }
1360:
1.8 pooka 1361: if (read_argp)
1362: free(read_argp, M_PUFFS);
1.1 pooka 1363: return error;
1364: }
1365:
1366: int
1367: puffs_write(void *v)
1368: {
1369: struct vop_write_args /* {
1370: const struct vnodeop_desc *a_desc;
1371: struct vnode *a_vp;
1372: struct uio *a_uio;
1373: int a_ioflag;
1374: kauth_cred_t a_cred;
1375: } */ *ap = v;
1376: struct puffs_vnreq_write *write_argp;
1377: struct puffs_mount *pmp;
1378: struct uio *uio;
1.8 pooka 1379: struct vnode *vp;
1380: void *win;
1.1 pooka 1381: size_t tomove, argsize;
1.8 pooka 1382: off_t oldoff, newoff, origoff;
1383: vsize_t bytelen;
1.15 pooka 1384: int error, uflags;
1.11 pooka 1385: int async, ubcflags;
1.1 pooka 1386:
1.8 pooka 1387: vp = ap->a_vp;
1.1 pooka 1388: uio = ap->a_uio;
1.8 pooka 1389: async = vp->v_mount->mnt_flag & MNT_ASYNC;
1390: error = uflags = 0;
1391: write_argp = NULL;
1.11 pooka 1392: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1393:
1.23 pooka 1394: if (vp->v_type == VREG && PUFFS_DOCACHE(pmp)) {
1.12 pooka 1395: ubcflags = 0;
1.15 pooka 1396: if (UBC_WANT_UNMAP(vp))
1.12 pooka 1397: ubcflags = UBC_UNMAP;
1398:
1.8 pooka 1399: /*
1400: * userspace *should* be allowed to control this,
1401: * but with UBC it's a bit unclear how to handle it
1402: */
1403: if (ap->a_ioflag & IO_APPEND)
1404: uio->uio_offset = vp->v_size;
1.1 pooka 1405:
1.8 pooka 1406: origoff = uio->uio_offset;
1407: while (uio->uio_resid > 0) {
1408: uflags |= PUFFS_UPDATECTIME;
1409: uflags |= PUFFS_UPDATEMTIME;
1410: oldoff = uio->uio_offset;
1411: bytelen = uio->uio_resid;
1412:
1413: win = ubc_alloc(&vp->v_uobj, oldoff, &bytelen,
1414: UVM_ADV_NORMAL, UBC_WRITE);
1415: error = uiomove(win, bytelen, uio);
1416:
1417: /*
1418: * did we grow the file?
1419: * XXX: should probably ask userspace to extend
1420: * it's idea of the *first* before growing it
1421: * here. Or we need some mechanism to "rollback"
1422: * in case putpages fails.
1423: */
1424: newoff = oldoff + bytelen;
1425: if (vp->v_size < newoff) {
1426: uflags |= PUFFS_UPDATESIZE;
1427: uvm_vnp_setsize(vp, newoff);
1428:
1429: /*
1430: * in case we couldn't copy data to the
1431: * window, zero it out so that we don't
1432: * have any random leftovers in there.
1433: */
1434: if (error)
1435: memset(win, 0, bytelen);
1436: }
1.1 pooka 1437:
1.11 pooka 1438: ubc_release(win, ubcflags);
1.8 pooka 1439: if (error)
1440: break;
1441:
1442: /* ok, I really need to admit: why's this? */
1443: if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
1444: simple_lock(&vp->v_interlock);
1445: error = VOP_PUTPAGES(vp, oldoff & ~0xffff,
1446: uio->uio_offset & ~0xffff, PGO_CLEANIT);
1447: if (error)
1448: break;
1449: }
1.1 pooka 1450: }
1.8 pooka 1451:
1.15 pooka 1452: if (error == 0 && ap->a_ioflag & IO_SYNC) {
1.8 pooka 1453: simple_lock(&vp->v_interlock);
1454: error = VOP_PUTPAGES(vp, trunc_page(origoff),
1.15 pooka 1455: round_page(uio->uio_offset),
1456: PGO_CLEANIT | PGO_SYNCIO);
1.1 pooka 1457: }
1458:
1.8 pooka 1459: puffs_updatenode(vp, uflags);
1460: } else {
1.19 pooka 1461: /* tomove is non-increasing */
1.1 pooka 1462: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.8 pooka 1463: argsize = sizeof(struct puffs_vnreq_write) + tomove;
1464: write_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
1465:
1466: while (uio->uio_resid > 0) {
1467: write_argp->pvnr_ioflag = ap->a_ioflag;
1468: write_argp->pvnr_resid = tomove;
1469: write_argp->pvnr_offset = uio->uio_offset;
1470: puffs_credcvt(&write_argp->pvnr_cred, ap->a_cred);
1471: error = uiomove(write_argp->pvnr_data, tomove, uio);
1472: if (error)
1473: break;
1474:
1475: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
1476: PUFFS_VN_WRITE, write_argp, argsize,
1477: VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1478: if (error) {
1479: /* restore uiomove */
1480: uio->uio_resid += tomove;
1481: uio->uio_offset -= tomove;
1482: break;
1483: }
1484: if (write_argp->pvnr_resid > tomove) {
1485: /*
1486: * XXX: correct file size is a mystery,
1487: * we can only guess
1488: */
1489: error = EINVAL;
1490: break;
1491: }
1492:
1493: /* adjust file size */
1.20 pooka 1494: if (vp->v_size < uio->uio_offset)
1495: uvm_vnp_setsize(vp, uio->uio_offset);
1.8 pooka 1496:
1497: /* didn't move everything? bad userspace. bail */
1498: if (write_argp->pvnr_resid != 0) {
1499: uio->uio_resid += write_argp->pvnr_resid;
1500: uio->uio_offset -= write_argp->pvnr_resid;
1501: error = EIO;
1502: break;
1503: }
1504:
1505: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1506: }
1.1 pooka 1507: }
1508:
1.8 pooka 1509: if (write_argp)
1510: free(write_argp, M_PUFFS);
1.1 pooka 1511: return error;
1512: }
1513:
1514: static int puffs_fcnioctl(struct vop_ioctl_args * /*XXX*/, int);
1515:
1516: #define FCNIOCTL_ARG_MAX 1<<16
1517: int
1518: puffs_fcnioctl(struct vop_ioctl_args *ap, int puffsop)
1519: {
1.24 pooka 1520:
1521: /* currently not supported */
1522: return EOPNOTSUPP;
1523: #if 0
1.1 pooka 1524: /* struct vop_ioctl_args {
1525: const struct vnodeop_desc *a_desc;
1526: struct vnode *a_vp;
1527: u_long a_command;
1528: void *a_data;
1529: int a_fflag;
1530: kauth_cred_t a_cred;
1531: struct lwp *a_l;
1532: } *ap = v; */
1533: struct puffs_mount *pmp;
1534: struct puffs_sizepark pspark;
1535: void *kernbuf;
1536: size_t copylen;
1537: int error;
1538:
1539: PUFFS_VNREQ(fcnioctl);
1540:
1541: /*
1542: * Since this op gives the filesystem (almost) complete control on
1543: * how much it is allowed to copy from the calling process
1544: * address space, do not enable it by default, since it would
1545: * be a whopping security hole.
1546: */
1547: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1.18 pooka 1548: if ((pmp->pmp_flags & PUFFS_KFLAG_ALLOWCTL) == 0)
1.1 pooka 1549: return EINVAL; /* only shoe that fits */
1550:
1551: /* fill in sizereq and store it */
1552: pspark.pkso_reqid = puffs_getreqid(pmp);
1553: pspark.pkso_reqtype = PUFFS_SIZEOPREQ_BUF_IN;
1554: pspark.pkso_copybuf = ap->a_data;
1555: pspark.pkso_bufsize = FCNIOCTL_ARG_MAX;
1556: TAILQ_INSERT_TAIL(&pmp->pmp_req_sizepark, &pspark, pkso_entries);
1557:
1558: /* then fill in actual request and shoot it off */
1559: fcnioctl_arg.pvnr_command = ap->a_command;
1560: fcnioctl_arg.pvnr_fflag = ap->a_fflag;
1561: puffs_credcvt(&fcnioctl_arg.pvnr_cred, ap->a_cred);
1562: fcnioctl_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
1563:
1564: error = puffs_vntouser_req(MPTOPUFFSMP(ap->a_vp->v_mount), puffsop,
1565: &fcnioctl_arg, sizeof(fcnioctl_arg), VPTOPNC(ap->a_vp),
1566: pspark.pkso_reqid, NULL, NULL);
1567:
1568: /* if we don't need to copy data, we're done */
1569: if (error || !fcnioctl_arg.pvnr_copyback)
1570: return error;
1571:
1572: copylen = MIN(FCNIOCTL_ARG_MAX, fcnioctl_arg.pvnr_datalen);
1573: kernbuf = malloc(copylen, M_PUFFS, M_WAITOK);
1574: error = copyin(fcnioctl_arg.pvnr_data, kernbuf, copylen);
1575: if (error)
1576: goto out;
1577: error = copyout(kernbuf, ap->a_data, copylen);
1578:
1579: out:
1580: free(kernbuf, M_PUFFS);
1581: return error;
1.24 pooka 1582: #endif
1.1 pooka 1583: }
1584:
1585: int
1586: puffs_ioctl(void *v)
1587: {
1588:
1589: return puffs_fcnioctl(v, PUFFS_VN_IOCTL);
1590: }
1591:
1592: int
1593: puffs_fcntl(void *v)
1594: {
1595:
1596: return puffs_fcnioctl(v, PUFFS_VN_FCNTL);
1597: }
1598:
1599: int
1600: puffs_print(void *v)
1601: {
1602: struct vop_print_args /* {
1603: struct vnode *a_vp;
1604: } */ *ap = v;
1.17 pooka 1605: struct puffs_mount *pmp;
1.1 pooka 1606: struct vnode *vp = ap->a_vp;
1.2 pooka 1607: struct puffs_node *pn = vp->v_data;
1.1 pooka 1608:
1609: PUFFS_VNREQ(print);
1610:
1.17 pooka 1611: pmp = MPTOPUFFSMP(vp->v_mount);
1612:
1.1 pooka 1613: /* kernel portion */
1.2 pooka 1614: printf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
1615: " userspace cookie: %p\n", vp, pn, pn->pn_cookie);
1.6 pooka 1616: if (vp->v_type == VFIFO)
1617: fifo_printinfo(vp);
1.1 pooka 1618: lockmgr_printinfo(&vp->v_lock);
1619:
1620: /* userspace portion */
1.17 pooka 1621: if (EXISTSOP(pmp, PRINT))
1622: puffs_vntouser(pmp, PUFFS_VN_PRINT,
1623: &print_arg, sizeof(print_arg), VPTOPNC(ap->a_vp),
1624: LOCKEDVP(ap->a_vp), NULL);
1625:
1626: return 0;
1.1 pooka 1627: }
1628:
1629: int
1630: puffs_pathconf(void *v)
1631: {
1632: struct vop_pathconf_args /* {
1633: const struct vnodeop_desc *a_desc;
1634: struct vnode *a_vp;
1635: int a_name;
1636: register_t *a_retval;
1637: } */ *ap = v;
1638: int error;
1639:
1640: PUFFS_VNREQ(pathconf);
1641:
1642: pathconf_arg.pvnr_name = ap->a_name;
1643:
1644: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
1645: PUFFS_VN_PATHCONF, &pathconf_arg, sizeof(pathconf_arg),
1646: VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1647: if (error)
1648: return error;
1649:
1650: *ap->a_retval = pathconf_arg.pvnr_retval;
1651:
1652: return 0;
1653: }
1654:
1655: int
1656: puffs_advlock(void *v)
1657: {
1658: struct vop_advlock_args /* {
1659: const struct vnodeop_desc *a_desc;
1660: struct vnode *a_vp;
1661: void *a_id;
1662: int a_op;
1663: struct flock *a_fl;
1664: int a_flags;
1665: } */ *ap = v;
1666: int error;
1667:
1668: PUFFS_VNREQ(advlock);
1669:
1670: error = copyin(ap->a_fl, &advlock_arg.pvnr_fl, sizeof(struct flock));
1671: if (error)
1672: return error;
1673: advlock_arg.pvnr_id = ap->a_id;
1674: advlock_arg.pvnr_op = ap->a_op;
1675: advlock_arg.pvnr_flags = ap->a_flags;
1676:
1677: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_ADVLOCK,
1678: &advlock_arg, sizeof(advlock_arg), VPTOPNC(ap->a_vp), NULL, NULL);
1679: }
1.8 pooka 1680: /*
1681: * This maps itself to PUFFS_VN_READ/WRITE for data transfer.
1682: */
1683: int
1684: puffs_strategy(void *v)
1685: {
1686: struct vop_strategy_args /* {
1687: const struct vnodeop_desc *a_desc;
1688: struct vnode *a_vp;
1689: struct buf *a_bp;
1690: } */ *ap = v;
1691: struct puffs_mount *pmp;
1.35 pooka 1692: struct vnode *vp = ap->a_vp;
1.38 ! pooka 1693: struct puffs_node *pn;
1.14 pooka 1694: struct puffs_vnreq_read *read_argp = NULL;
1695: struct puffs_vnreq_write *write_argp = NULL;
1.8 pooka 1696: struct buf *bp;
1697: size_t argsize;
1.14 pooka 1698: size_t tomove, moved;
1.35 pooka 1699: int error, dowritefaf;
1.8 pooka 1700:
1.35 pooka 1701: pmp = MPTOPUFFSMP(vp->v_mount);
1.8 pooka 1702: bp = ap->a_bp;
1.36 pooka 1703: error = 0;
1704: dowritefaf = 0;
1.38 ! pooka 1705: pn = VPTOPP(vp);
! 1706:
! 1707: if (((bp->b_flags & B_READ) && !EXISTSOP(pmp, READ))
! 1708: || (((bp->b_flags & B_READ) == 0) && !EXISTSOP(pmp, WRITE))) {
! 1709: error = EOPNOTSUPP;
! 1710: goto out;
! 1711: }
1.8 pooka 1712:
1.38 ! pooka 1713: /*
! 1714: * Short-circuit optimization: don't flush buffer in between
! 1715: * VOP_INACTIVE and VOP_RECLAIM in case the node has no references.
! 1716: */
! 1717: if (pn->pn_stat & PNODE_NOREFS) {
! 1718: bp->b_resid = 0;
! 1719: goto out;
! 1720: }
1.17 pooka 1721:
1.8 pooka 1722: #ifdef DIAGNOSTIC
1.14 pooka 1723: if (bp->b_resid > pmp->pmp_req_maxsize - PUFFS_REQSTRUCT_MAX)
1724: panic("puffs_strategy: wildly inappropriate buf resid %d",
1725: bp->b_resid);
1.8 pooka 1726: #endif
1727:
1.35 pooka 1728: /*
1729: * See explanation for the necessity of a FAF in puffs_fsync
1730: *
1731: * XXgoddamnX: B_WRITE is a "pseudo flag"
1732: */
1733: if ((bp->b_flags & B_READ) == 0) {
1734: simple_lock(&vp->v_interlock);
1735: if (vp->v_flag & VXLOCK)
1736: dowritefaf = 1;
1737: simple_unlock(&vp->v_interlock);
1738: }
1739:
1.8 pooka 1740: if (bp->b_flags & B_READ) {
1741: argsize = sizeof(struct puffs_vnreq_read);
1.14 pooka 1742: read_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);
1743: if (read_argp == NULL) {
1744: error = ENOMEM;
1745: goto out;
1746: }
1747:
1748: tomove = PUFFS_TOMOVE(bp->b_resid, pmp);
1749:
1.8 pooka 1750: read_argp->pvnr_ioflag = 0;
1.14 pooka 1751: read_argp->pvnr_resid = tomove;
1.8 pooka 1752: read_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
1.14 pooka 1753: puffs_credcvt(&read_argp->pvnr_cred, FSCRED);
1.8 pooka 1754:
1755: error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
1.35 pooka 1756: (void **)&read_argp, &argsize, read_argp->pvnr_resid,
1757: VPTOPNC(vp), LOCKEDVP(vp), NULL);
1.8 pooka 1758:
1759: if (error)
1.14 pooka 1760: goto out;
1.8 pooka 1761:
1.14 pooka 1762: if (read_argp->pvnr_resid > tomove) {
1763: error = EINVAL;
1764: goto out;
1765: }
1766:
1767: moved = tomove - read_argp->pvnr_resid;
1768:
1769: (void)memcpy(bp->b_data, read_argp->pvnr_data, moved);
1770: bp->b_resid -= moved;
1.8 pooka 1771: } else {
1772: argsize = sizeof(struct puffs_vnreq_write) + bp->b_bcount;
1.14 pooka 1773: write_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);
1774: if (write_argp == NULL) {
1775: error = ENOMEM;
1776: goto out;
1777: }
1778:
1779: tomove = PUFFS_TOMOVE(bp->b_resid, pmp);
1780:
1.8 pooka 1781: write_argp->pvnr_ioflag = 0;
1.14 pooka 1782: write_argp->pvnr_resid = tomove;
1.8 pooka 1783: write_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
1.14 pooka 1784: puffs_credcvt(&write_argp->pvnr_cred, FSCRED);
1785:
1786: (void)memcpy(&write_argp->pvnr_data, bp->b_data, tomove);
1.8 pooka 1787:
1.35 pooka 1788: if (dowritefaf) {
1789: /*
1790: * assume FAF moves everything. frankly, we don't
1791: * really have a choice.
1792: */
1793: puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount),
1794: PUFFS_VN_WRITE, write_argp, argsize, VPTOPNC(vp));
1795: bp->b_resid -= tomove;
1796: } else {
1797: error = puffs_vntouser(MPTOPUFFSMP(vp->v_mount),
1798: PUFFS_VN_WRITE, write_argp, argsize, VPTOPNC(vp),
1799: vp, NULL);
1800: if (error)
1801: goto out;
1.8 pooka 1802:
1.35 pooka 1803: moved = tomove - write_argp->pvnr_resid;
1804: if (write_argp->pvnr_resid > tomove) {
1805: error = EINVAL;
1806: goto out;
1807: }
1.9 pooka 1808:
1.35 pooka 1809: bp->b_resid -= moved;
1810: if (write_argp->pvnr_resid != 0)
1811: error = EIO;
1.14 pooka 1812: }
1.8 pooka 1813: }
1814:
1815: out:
1.14 pooka 1816: if (read_argp)
1817: free(read_argp, M_PUFFS);
1.35 pooka 1818: if (write_argp && !dowritefaf)
1.14 pooka 1819: free(write_argp, M_PUFFS);
1820:
1.38 ! pooka 1821: biodone(bp);
1.8 pooka 1822: return error;
1823: }
1.1 pooka 1824:
1.21 pooka 1825: int
1826: puffs_mmap(void *v)
1827: {
1828: struct vop_mmap_args /* {
1829: const struct vnodeop_desc *a_desc;
1830: struct vnode *a_vp;
1831: int a_fflags;
1832: kauth_cred_t a_cred;
1833: struct lwp *a_l;
1834: } */ *ap = v;
1835: struct puffs_mount *pmp;
1836: int error;
1837:
1838: PUFFS_VNREQ(mmap);
1839:
1840: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1841:
1.23 pooka 1842: if (!PUFFS_DOCACHE(pmp))
1.21 pooka 1843: return genfs_eopnotsupp(v);
1844:
1845: if (EXISTSOP(pmp, MMAP)) {
1846: mmap_arg.pvnr_fflags = ap->a_fflags;
1847: puffs_credcvt(&mmap_arg.pvnr_cred, ap->a_cred);
1848: mmap_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
1849:
1850: error = puffs_vntouser(pmp, PUFFS_VN_MMAP,
1851: &mmap_arg, sizeof(mmap_arg),
1852: VPTOPNC(ap->a_vp), NULL, NULL);
1853: } else {
1854: error = genfs_mmap(v);
1855: }
1856:
1857: return error;
1858: }
1859:
1860:
1.1 pooka 1861: /*
1862: * The rest don't get a free trip to userspace and back, they
1863: * have to stay within the kernel.
1864: */
1865:
1866: /*
1.8 pooka 1867: * bmap doesn't really make any sense for puffs, so just 1:1 map it.
1868: * well, maybe somehow, somewhere, some day ....
1869: */
1870: int
1871: puffs_bmap(void *v)
1872: {
1873: struct vop_bmap_args /* {
1874: const struct vnodeop_desc *a_desc;
1875: struct vnode *a_vp;
1876: daddr_t a_bn;
1877: struct vnode **a_vpp;
1878: daddr_t *a_bnp;
1879: int *a_runp;
1880: } */ *ap = v;
1881: struct puffs_mount *pmp;
1882:
1883: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1884:
1885: if (ap->a_vpp)
1886: *ap->a_vpp = ap->a_vp;
1887: if (ap->a_bnp)
1888: *ap->a_bnp = ap->a_bn;
1889: if (ap->a_runp)
1890: *ap->a_runp = pmp->pmp_req_maxsize - PUFFS_REQSTRUCT_MAX;
1891:
1892: return 0;
1893: }
1894:
1895: /*
1.1 pooka 1896: * moreXXX: yes, todo
1897: */
1898: int
1899: puffs_lock(void *v)
1900: {
1901: struct vop_lock_args /* {
1902: struct vnode *a_vp;
1903: int a_flags;
1904: } */ *ap = v;
1905: struct vnode *vp = ap->a_vp;
1906:
1907: #if 0
1908: DPRINTF(("puffs_lock: lock %p, args 0x%x\n", vp, ap->a_flags));
1909: #endif
1910:
1911: return lockmgr(&vp->v_lock, ap->a_flags, &vp->v_interlock);
1912: }
1913:
1914: int
1915: puffs_unlock(void *v)
1916: {
1917: struct vop_unlock_args /* {
1918: struct vnode *a_vp;
1919: int a_flags;
1920: } */ *ap = v;
1921: struct vnode *vp = ap->a_vp;
1922:
1923: #if 0
1924: DPRINTF(("puffs_unlock: lock %p, args 0x%x\n", vp, ap->a_flags));
1925: #endif
1926:
1927: return lockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock);
1928: }
1929:
1930: int
1931: puffs_islocked(void *v)
1932: {
1933: struct vop_islocked_args *ap = v;
1934: int rv;
1935:
1936: rv = lockstatus(&ap->a_vp->v_lock);
1937: return rv;
1938: }
1939:
1940: int
1941: puffs_generic(void *v)
1942: {
1943: struct vop_generic_args *ap = v;
1944:
1945: (void)ap;
1946: DPRINTF(("puffs_generic: ap->a_desc = %s\n", ap->a_desc->vdesc_name));
1947:
1948: return EOPNOTSUPP;
1949: }
1.26 pooka 1950:
1951:
1952: /*
1.31 pooka 1953: * spec & fifo. These call the miscfs spec and fifo vectors, but issue
1.26 pooka 1954: * FAF update information for the puffs node first.
1955: */
1956: int
1957: puffs_spec_read(void *v)
1958: {
1959: struct vop_read_args /* {
1960: const struct vnodeop_desc *a_desc;
1961: struct vnode *a_vp;
1962: struct uio *a_uio;
1963: int a_ioflag;
1964: kauth_cred_t a_cred;
1965: } */ *ap = v;
1966:
1967: puffs_updatenode(ap->a_vp, PUFFS_UPDATEATIME);
1968: return VOCALL(spec_vnodeop_p, VOFFSET(vop_read), v);
1969: }
1970:
1971: int
1972: puffs_spec_write(void *v)
1973: {
1974: struct vop_write_args /* {
1975: const struct vnodeop_desc *a_desc;
1976: struct vnode *a_vp;
1977: struct uio *a_uio;
1978: int a_ioflag;
1979: kauth_cred_t a_cred;
1980: } */ *ap = v;
1981:
1982: puffs_updatenode(ap->a_vp, PUFFS_UPDATEMTIME);
1983: return VOCALL(spec_vnodeop_p, VOFFSET(vop_write), v);
1984: }
1985:
1986: int
1987: puffs_fifo_read(void *v)
1988: {
1989: struct vop_read_args /* {
1990: const struct vnodeop_desc *a_desc;
1991: struct vnode *a_vp;
1992: struct uio *a_uio;
1993: int a_ioflag;
1994: kauth_cred_t a_cred;
1995: } */ *ap = v;
1996:
1997: puffs_updatenode(ap->a_vp, PUFFS_UPDATEATIME);
1998: return VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), v);
1999: }
2000:
2001: int
2002: puffs_fifo_write(void *v)
2003: {
2004: struct vop_write_args /* {
2005: const struct vnodeop_desc *a_desc;
2006: struct vnode *a_vp;
2007: struct uio *a_uio;
2008: int a_ioflag;
2009: kauth_cred_t a_cred;
2010: } */ *ap = v;
2011:
2012: puffs_updatenode(ap->a_vp, PUFFS_UPDATEMTIME);
2013: return VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), v);
2014: }
CVSweb <webmaster@jp.NetBSD.org>