Annotation of src/sys/fs/puffs/puffs_vnops.c, Revision 1.40
1.40 ! pooka 1: /* $NetBSD: puffs_vnops.c,v 1.39 2007/01/25 17:43:56 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.40 ! pooka 36: __KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.39 2007/01/25 17:43:56 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: simple_lock(&pmp->pmp_lock);
1.39 pooka 803: KASSERT(pmp->pmp_root != NULL);
804: pmp->pmp_root = NULL;
1.1 pooka 805: simple_unlock(&pmp->pmp_lock);
1.34 pooka 806: goto out;
1.1 pooka 807: }
808:
1.34 pooka 809: if (!EXISTSOP(pmp, RECLAIM))
810: goto out;
1.1 pooka 811:
1.34 pooka 812: reclaim_argp = malloc(sizeof(struct puffs_vnreq_reclaim),
813: M_PUFFS, M_WAITOK | M_ZERO);
814: reclaim_argp->pvnr_pid = puffs_lwp2pid(ap->a_l);
815:
816: puffs_vntouser_faf(pmp, PUFFS_VN_RECLAIM,
817: reclaim_argp, sizeof(struct puffs_vnreq_reclaim),
818: VPTOPNC(ap->a_vp));
1.1 pooka 819:
1.34 pooka 820: out:
1.23 pooka 821: if (PUFFS_DOCACHE(pmp))
822: cache_purge(ap->a_vp);
1.1 pooka 823: puffs_putvnode(ap->a_vp);
824:
825: return 0;
826: }
827:
828: int
829: puffs_readdir(void *v)
830: {
831: struct vop_readdir_args /* {
832: const struct vnodeop_desc *a_desc;
833: struct vnode *a_vp;
834: struct uio *a_uio;
835: kauth_cred_t a_cred;
836: int *a_eofflag;
837: off_t **a_cookies;
838: int *a_ncookies;
839: } */ *ap = v;
840: struct puffs_vnreq_readdir *readdir_argp;
841: size_t argsize;
842: struct uio *uio = ap->a_uio;
843: size_t howmuch;
844: int error;
845:
846: /* worry about these later */
847: if (!(ap->a_cookies == NULL && ap->a_ncookies == NULL))
848: return EOPNOTSUPP;
849:
850: argsize = sizeof(struct puffs_vnreq_readdir);
851: readdir_argp = malloc(argsize, M_PUFFS, M_ZERO | M_WAITOK);
852:
853: puffs_credcvt(&readdir_argp->pvnr_cred, ap->a_cred);
854: readdir_argp->pvnr_offset = uio->uio_offset;
855: readdir_argp->pvnr_resid = uio->uio_resid;
856:
857: error = puffs_vntouser_adjbuf(MPTOPUFFSMP(ap->a_vp->v_mount),
858: PUFFS_VN_READDIR, (void **)&readdir_argp, &argsize,
1.19 pooka 859: readdir_argp->pvnr_resid, VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1.1 pooka 860: if (error)
861: goto out;
862:
863: /* userspace is cheating? */
864: if (readdir_argp->pvnr_resid > uio->uio_resid) {
865: error = EINVAL;
866: goto out;
867: }
868:
869: /* bouncy-wouncy with the directory data */
870: howmuch = uio->uio_resid - readdir_argp->pvnr_resid;
1.29 pooka 871: /* XXX: we could let userlandia tell its opinion first time 'round */
872: if (howmuch == 0) {
873: *ap->a_eofflag = 1;
874: goto out;
875: }
1.1 pooka 876: error = uiomove(readdir_argp->pvnr_dent, howmuch, uio);
877: if (error)
878: goto out;
879: uio->uio_offset = readdir_argp->pvnr_offset;
880:
881: out:
882: free(readdir_argp, M_PUFFS);
883: return error;
884: }
885:
886: int
887: puffs_poll(void *v)
888: {
889: struct vop_poll_args /* {
890: const struct vnodeop_desc *a_desc;
891: struct vnode *a_vp;
892: int a_events;
893: struct lwp *a_l;
894: } */ *ap = v;
895:
896: PUFFS_VNREQ(poll);
897:
898: poll_arg.pvnr_events = ap->a_events;
899: poll_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
900:
901: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_POLL,
902: &poll_arg, sizeof(poll_arg), VPTOPNC(ap->a_vp), NULL, NULL);
903: }
904:
905: int
906: puffs_fsync(void *v)
907: {
908: struct vop_fsync_args /* {
909: const struct vnodeop_desc *a_desc;
910: struct vnode *a_vp;
911: kauth_cred_t a_cred;
912: int a_flags;
913: off_t a_offlo;
914: off_t a_offhi;
915: struct lwp *a_l;
916: } */ *ap = v;
1.31 pooka 917: struct puffs_mount *pmp;
1.8 pooka 918: struct puffs_vnreq_fsync *fsync_argp;
919: struct vnode *vp;
1.38 pooka 920: struct puffs_node *pn;
1.35 pooka 921: int pflags, error, dofaf;
1.1 pooka 922:
923: PUFFS_VNREQ(fsync);
924:
1.8 pooka 925: vp = ap->a_vp;
1.38 pooka 926: pn = VPTOPP(vp);
1.31 pooka 927: pmp = MPTOPUFFSMP(vp->v_mount);
1.8 pooka 928:
929: pflags = PGO_CLEANIT;
1.31 pooka 930: if (ap->a_flags & FSYNC_WAIT)
1.8 pooka 931: pflags |= PGO_SYNCIO;
932:
933: /*
934: * flush pages to avoid being overly dirty
935: */
936: simple_lock(&vp->v_interlock);
937: error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
938: round_page(ap->a_offhi), pflags);
939: if (error)
940: return error;
941:
1.31 pooka 942: /*
943: * HELLO! We exit already here if the user server does not
1.38 pooka 944: * support fsync OR if we should call fsync for a node which
945: * has references neither in the kernel or the fs server.
946: * Otherwise we continue to issue fsync() forward.
1.31 pooka 947: */
1.38 pooka 948: if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_NOREFS))
1.31 pooka 949: return 0;
950:
1.35 pooka 951: dofaf = (ap->a_flags & FSYNC_WAIT) == 0;
952: /*
953: * We abuse VXLOCK to mean "vnode is going to die", so we issue
954: * only FAFs for those. Otherwise there's a danger of deadlock,
955: * since the execution context here might be the user server
956: * doing some operation on another fs, which in turn caused a
957: * vnode to be reclaimed from the freelist for this fs.
958: */
959: if (dofaf == 0) {
960: simple_lock(&vp->v_interlock);
961: if (vp->v_flag & VXLOCK)
962: dofaf = 1;
963: simple_unlock(&vp->v_interlock);
964: }
965:
966: if (dofaf == 0) {
1.31 pooka 967: fsync_argp = &fsync_arg;
968: } else {
969: fsync_argp = malloc(sizeof(struct puffs_vnreq_fsync),
970: M_PUFFS, M_ZERO | M_NOWAIT);
971: if (fsync_argp == NULL)
972: return ENOMEM;
973: }
974:
1.8 pooka 975: puffs_credcvt(&fsync_argp->pvnr_cred, ap->a_cred);
976: fsync_argp->pvnr_flags = ap->a_flags;
977: fsync_argp->pvnr_offlo = ap->a_offlo;
978: fsync_argp->pvnr_offhi = ap->a_offhi;
979: fsync_argp->pvnr_pid = puffs_lwp2pid(ap->a_l);
1.1 pooka 980:
981: /*
982: * XXX: see comment at puffs_getattr about locking
1.8 pooka 983: *
984: * If we are not required to wait, do a FAF operation.
985: * Otherwise block here.
1.1 pooka 986: */
1.35 pooka 987: if (dofaf == 0) {
1.8 pooka 988: error = puffs_vntouser(MPTOPUFFSMP(vp->v_mount),
989: PUFFS_VN_FSYNC, fsync_argp, sizeof(*fsync_argp),
990: VPTOPNC(vp), NULL /* XXXshouldbe: vp */, NULL);
991: } else {
992: /* FAF is always "succesful" */
993: error = 0;
994: puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount),
995: PUFFS_VN_FSYNC, fsync_argp, sizeof(*fsync_argp),
996: VPTOPNC(vp));
997: }
998:
999: return error;
1.1 pooka 1000: }
1001:
1002: int
1003: puffs_seek(void *v)
1004: {
1005: struct vop_seek_args /* {
1006: const struct vnodeop_desc *a_desc;
1007: struct vnode *a_vp;
1008: off_t a_oldoff;
1009: off_t a_newoff;
1010: kauth_cred_t a_cred;
1011: } */ *ap = v;
1012:
1013: PUFFS_VNREQ(seek);
1014:
1015: seek_arg.pvnr_oldoff = ap->a_oldoff;
1016: seek_arg.pvnr_newoff = ap->a_newoff;
1017: puffs_credcvt(&seek_arg.pvnr_cred, ap->a_cred);
1018:
1019: /*
1020: * XXX: seems like seek is called with an unlocked vp, but
1021: * it can't hurt to play safe
1022: */
1023: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_SEEK,
1024: &seek_arg, sizeof(seek_arg), VPTOPNC(ap->a_vp),
1025: LOCKEDVP(ap->a_vp), NULL);
1026: }
1027:
1028: int
1029: puffs_remove(void *v)
1030: {
1031: struct vop_remove_args /* {
1032: const struct vnodeop_desc *a_desc;
1033: struct vnode *a_dvp;
1034: struct vnode *a_vp;
1035: struct componentname *a_cnp;
1036: } */ *ap = v;
1037: int error;
1038:
1039: PUFFS_VNREQ(remove);
1040:
1041: remove_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
1042: puffs_makecn(&remove_arg.pvnr_cn, ap->a_cnp);
1043:
1044: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_REMOVE,
1045: &remove_arg, sizeof(remove_arg), VPTOPNC(ap->a_dvp),
1046: ap->a_dvp, ap->a_vp);
1047:
1048: vput(ap->a_vp);
1.25 pooka 1049: if (ap->a_dvp == ap->a_vp)
1050: vrele(ap->a_dvp);
1051: else
1052: vput(ap->a_dvp);
1.1 pooka 1053:
1054: return error;
1055: }
1056:
1057: int
1058: puffs_mkdir(void *v)
1059: {
1060: struct vop_mkdir_args /* {
1061: const struct vnodeop_desc *a_desc;
1062: struct vnode *a_dvp;
1063: struct vnode **a_vpp;
1064: struct componentname *a_cnp;
1065: struct vattr *a_vap;
1066: } */ *ap = v;
1067: int error;
1068:
1069: PUFFS_VNREQ(mkdir);
1070:
1071: puffs_makecn(&mkdir_arg.pvnr_cn, ap->a_cnp);
1072: mkdir_arg.pvnr_va = *ap->a_vap;
1073:
1074: /* XXX: wouldn't need to relock dvp, but that's life */
1075: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_MKDIR,
1076: &mkdir_arg, sizeof(mkdir_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
1077: if (error)
1.4 pooka 1078: goto out;
1.1 pooka 1079:
1.4 pooka 1080: error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5 pooka 1081: mkdir_arg.pvnr_newnode, ap->a_cnp, VDIR, 0);
1.4 pooka 1082:
1083: out:
1084: if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
1085: PNBUF_PUT(ap->a_cnp->cn_pnbuf);
1086: vput(ap->a_dvp);
1087: return error;
1.1 pooka 1088: }
1089:
1090: int
1091: puffs_rmdir(void *v)
1092: {
1093: struct vop_rmdir_args /* {
1094: const struct vnodeop_desc *a_desc;
1095: struct vnode *a_dvp;
1096: struct vnode *a_vp;
1097: struct componentname *a_cnp;
1098: } */ *ap = v;
1099: int error;
1100:
1101: PUFFS_VNREQ(rmdir);
1102:
1103: rmdir_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
1104: puffs_makecn(&rmdir_arg.pvnr_cn, ap->a_cnp);
1105:
1106: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_RMDIR,
1107: &rmdir_arg, sizeof(rmdir_arg), VPTOPNC(ap->a_dvp),
1108: ap->a_dvp, ap->a_vp);
1109:
1.23 pooka 1110: /* XXX: some call cache_purge() *for both vnodes* here, investigate */
1111:
1.1 pooka 1112: vput(ap->a_dvp);
1113: vput(ap->a_vp);
1114:
1115: return error;
1116: }
1117:
1118: int
1119: puffs_link(void *v)
1120: {
1121: struct vop_link_args /* {
1122: const struct vnodeop_desc *a_desc;
1123: struct vnode *a_dvp;
1124: struct vnode *a_vp;
1125: struct componentname *a_cnp;
1126: } */ *ap = v;
1127: int error;
1128:
1129: PUFFS_VNREQ(link);
1130:
1131: link_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
1132: puffs_makecn(&link_arg.pvnr_cn, ap->a_cnp);
1133:
1134: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_LINK,
1135: &link_arg, sizeof(link_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
1136:
1137: vput(ap->a_dvp);
1138:
1139: return error;
1140: }
1141:
1142: int
1143: puffs_symlink(void *v)
1144: {
1145: struct vop_symlink_args /* {
1146: const struct vnodeop_desc *a_desc;
1147: struct vnode *a_dvp;
1148: struct vnode **a_vpp;
1149: struct componentname *a_cnp;
1150: struct vattr *a_vap;
1151: char *a_target;
1152: } */ *ap = v;
1153: int error;
1154:
1155: PUFFS_VNREQ(symlink); /* XXX: large structure */
1156:
1157: *ap->a_vpp = NULL;
1158:
1159: puffs_makecn(&symlink_arg.pvnr_cn, ap->a_cnp);
1160: symlink_arg.pvnr_va = *ap->a_vap;
1161: (void)strlcpy(symlink_arg.pvnr_link, ap->a_target,
1162: sizeof(symlink_arg.pvnr_link));
1163:
1164: /* XXX: don't need to relock parent */
1165: error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount),
1166: PUFFS_VN_SYMLINK, &symlink_arg, sizeof(symlink_arg),
1167: VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
1168: if (error)
1.4 pooka 1169: goto out;
1.1 pooka 1170:
1.4 pooka 1171: error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5 pooka 1172: symlink_arg.pvnr_newnode, ap->a_cnp, VLNK, 0);
1.4 pooka 1173:
1174: out:
1175: if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
1176: PNBUF_PUT(ap->a_cnp->cn_pnbuf);
1177: vput(ap->a_dvp);
1178: return error;
1.1 pooka 1179: }
1180:
1181: int
1182: puffs_readlink(void *v)
1183: {
1184: struct vop_readlink_args /* {
1185: const struct vnodeop_desc *a_desc;
1186: struct vnode *a_vp;
1187: struct uio *a_uio;
1188: kauth_cred_t a_cred;
1189: } */ *ap = v;
1190: int error;
1191:
1192: PUFFS_VNREQ(readlink);
1193:
1194: puffs_credcvt(&readlink_arg.pvnr_cred, ap->a_cred);
1195: readlink_arg.pvnr_linklen = sizeof(readlink_arg.pvnr_link);
1196:
1197: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
1198: PUFFS_VN_READLINK, &readlink_arg, sizeof(readlink_arg),
1199: VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1200: if (error)
1201: return error;
1202:
1203: readlink_arg.pvnr_link[readlink_arg.pvnr_linklen] = '\0';
1204: return uiomove(&readlink_arg.pvnr_link, readlink_arg.pvnr_linklen,
1205: ap->a_uio);
1206: }
1207:
1208: /* XXXXXXX: think about locking & userspace op delocking... */
1209: int
1210: puffs_rename(void *v)
1211: {
1212: struct vop_rename_args /* {
1213: const struct vnodeop_desc *a_desc;
1214: struct vnode *a_fdvp;
1215: struct vnode *a_fvp;
1216: struct componentname *a_fcnp;
1217: struct vnode *a_tdvp;
1218: struct vnode *a_tvp;
1219: struct componentname *a_tcnp;
1220: } */ *ap = v;
1221: int error;
1222:
1223: PUFFS_VNREQ(rename);
1224:
1225: if (ap->a_fvp->v_mount != ap->a_tdvp->v_mount) {
1226: error = EXDEV;
1227: goto out;
1228: }
1229:
1230: rename_arg.pvnr_cookie_src = VPTOPNC(ap->a_fvp);
1231: rename_arg.pvnr_cookie_targdir = VPTOPNC(ap->a_tdvp);
1232: if (ap->a_tvp)
1233: rename_arg.pvnr_cookie_targ = VPTOPNC(ap->a_tvp);
1234: else
1235: rename_arg.pvnr_cookie_targ = NULL;
1236: puffs_makecn(&rename_arg.pvnr_cn_src, ap->a_fcnp);
1237: puffs_makecn(&rename_arg.pvnr_cn_targ, ap->a_tcnp);
1238:
1239: error = puffs_vntouser(MPTOPUFFSMP(ap->a_fdvp->v_mount),
1240: PUFFS_VN_RENAME, &rename_arg, sizeof(rename_arg),
1241: VPTOPNC(ap->a_fdvp), NULL, NULL);
1242:
1243: out:
1244: if (ap->a_tvp != NULL)
1245: vput(ap->a_tvp);
1.28 pooka 1246: if (ap->a_tdvp == ap->a_tvp)
1247: vrele(ap->a_tdvp);
1248: else
1249: vput(ap->a_tdvp);
1.1 pooka 1250:
1251: vrele(ap->a_fdvp);
1252: vrele(ap->a_fvp);
1253:
1254: return error;
1255: }
1256:
1257: int
1258: puffs_read(void *v)
1259: {
1260: struct vop_read_args /* {
1261: const struct vnodeop_desc *a_desc;
1262: struct vnode *a_vp;
1263: struct uio *a_uio;
1264: int a_ioflag;
1265: kauth_cred_t a_cred;
1266: } */ *ap = v;
1267: struct puffs_vnreq_read *read_argp;
1268: struct puffs_mount *pmp;
1.8 pooka 1269: struct vnode *vp;
1.1 pooka 1270: struct uio *uio;
1.8 pooka 1271: void *win;
1.1 pooka 1272: size_t tomove, argsize;
1.8 pooka 1273: vsize_t bytelen;
1.11 pooka 1274: int error, ubcflags;
1.1 pooka 1275:
1276: uio = ap->a_uio;
1.8 pooka 1277: vp = ap->a_vp;
1278: read_argp = NULL;
1279: error = 0;
1.11 pooka 1280: pmp = MPTOPUFFSMP(vp->v_mount);
1.1 pooka 1281:
1.8 pooka 1282: /* std sanity */
1283: if (uio->uio_resid == 0)
1284: return 0;
1285: if (uio->uio_offset < 0)
1286: return EINVAL;
1.1 pooka 1287:
1.23 pooka 1288: if (vp->v_type == VREG && PUFFS_DOCACHE(pmp)) {
1.8 pooka 1289: const int advice = IO_ADV_DECODE(ap->a_ioflag);
1.1 pooka 1290:
1.12 pooka 1291: ubcflags = 0;
1.15 pooka 1292: if (UBC_WANT_UNMAP(vp))
1.12 pooka 1293: ubcflags = UBC_UNMAP;
1294:
1.8 pooka 1295: while (uio->uio_resid > 0) {
1296: bytelen = MIN(uio->uio_resid,
1297: vp->v_size - uio->uio_offset);
1298: if (bytelen == 0)
1299: break;
1300:
1301: win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
1302: &bytelen, advice, UBC_READ);
1303: error = uiomove(win, bytelen, uio);
1.11 pooka 1304: ubc_release(win, ubcflags);
1.8 pooka 1305: if (error)
1306: break;
1.1 pooka 1307: }
1308:
1.8 pooka 1309: if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
1310: puffs_updatenode(vp, PUFFS_UPDATEATIME);
1311: } else {
1.1 pooka 1312: /*
1.15 pooka 1313: * in case it's not a regular file or we're operating
1314: * uncached, do read in the old-fashioned style,
1315: * i.e. explicit read operations
1.1 pooka 1316: */
1317:
1318: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.8 pooka 1319: argsize = sizeof(struct puffs_vnreq_read);
1320: read_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
1321:
1322: error = 0;
1323: while (uio->uio_resid > 0) {
1324: read_argp->pvnr_ioflag = ap->a_ioflag;
1325: read_argp->pvnr_resid = tomove;
1326: read_argp->pvnr_offset = uio->uio_offset;
1327: puffs_credcvt(&read_argp->pvnr_cred, ap->a_cred);
1328:
1329: argsize = sizeof(struct puffs_vnreq_read);
1330: error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
1331: (void **)&read_argp, &argsize,
1.19 pooka 1332: read_argp->pvnr_resid, VPTOPNC(ap->a_vp),
1.8 pooka 1333: ap->a_vp, NULL);
1334: if (error)
1335: break;
1336:
1337: if (read_argp->pvnr_resid > tomove) {
1338: error = EINVAL;
1339: break;
1340: }
1341:
1342: error = uiomove(read_argp->pvnr_data,
1343: tomove - read_argp->pvnr_resid, uio);
1344:
1345: /*
1346: * in case the file is out of juice, resid from
1347: * userspace is != 0. and the error-case is
1348: * quite obvious
1349: */
1350: if (error || read_argp->pvnr_resid)
1351: break;
1352:
1353: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1354: }
1.1 pooka 1355: }
1356:
1.8 pooka 1357: if (read_argp)
1358: free(read_argp, M_PUFFS);
1.1 pooka 1359: return error;
1360: }
1361:
1362: int
1363: puffs_write(void *v)
1364: {
1365: struct vop_write_args /* {
1366: const struct vnodeop_desc *a_desc;
1367: struct vnode *a_vp;
1368: struct uio *a_uio;
1369: int a_ioflag;
1370: kauth_cred_t a_cred;
1371: } */ *ap = v;
1372: struct puffs_vnreq_write *write_argp;
1373: struct puffs_mount *pmp;
1374: struct uio *uio;
1.8 pooka 1375: struct vnode *vp;
1376: void *win;
1.1 pooka 1377: size_t tomove, argsize;
1.8 pooka 1378: off_t oldoff, newoff, origoff;
1379: vsize_t bytelen;
1.15 pooka 1380: int error, uflags;
1.11 pooka 1381: int async, ubcflags;
1.1 pooka 1382:
1.8 pooka 1383: vp = ap->a_vp;
1.1 pooka 1384: uio = ap->a_uio;
1.8 pooka 1385: async = vp->v_mount->mnt_flag & MNT_ASYNC;
1386: error = uflags = 0;
1387: write_argp = NULL;
1.11 pooka 1388: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1389:
1.23 pooka 1390: if (vp->v_type == VREG && PUFFS_DOCACHE(pmp)) {
1.12 pooka 1391: ubcflags = 0;
1.15 pooka 1392: if (UBC_WANT_UNMAP(vp))
1.12 pooka 1393: ubcflags = UBC_UNMAP;
1394:
1.8 pooka 1395: /*
1396: * userspace *should* be allowed to control this,
1397: * but with UBC it's a bit unclear how to handle it
1398: */
1399: if (ap->a_ioflag & IO_APPEND)
1400: uio->uio_offset = vp->v_size;
1.1 pooka 1401:
1.8 pooka 1402: origoff = uio->uio_offset;
1403: while (uio->uio_resid > 0) {
1404: uflags |= PUFFS_UPDATECTIME;
1405: uflags |= PUFFS_UPDATEMTIME;
1406: oldoff = uio->uio_offset;
1407: bytelen = uio->uio_resid;
1408:
1409: win = ubc_alloc(&vp->v_uobj, oldoff, &bytelen,
1410: UVM_ADV_NORMAL, UBC_WRITE);
1411: error = uiomove(win, bytelen, uio);
1412:
1413: /*
1414: * did we grow the file?
1415: * XXX: should probably ask userspace to extend
1416: * it's idea of the *first* before growing it
1417: * here. Or we need some mechanism to "rollback"
1418: * in case putpages fails.
1419: */
1420: newoff = oldoff + bytelen;
1421: if (vp->v_size < newoff) {
1422: uflags |= PUFFS_UPDATESIZE;
1423: uvm_vnp_setsize(vp, newoff);
1424:
1425: /*
1426: * in case we couldn't copy data to the
1427: * window, zero it out so that we don't
1428: * have any random leftovers in there.
1429: */
1430: if (error)
1431: memset(win, 0, bytelen);
1432: }
1.1 pooka 1433:
1.11 pooka 1434: ubc_release(win, ubcflags);
1.8 pooka 1435: if (error)
1436: break;
1437:
1438: /* ok, I really need to admit: why's this? */
1439: if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
1440: simple_lock(&vp->v_interlock);
1441: error = VOP_PUTPAGES(vp, oldoff & ~0xffff,
1442: uio->uio_offset & ~0xffff, PGO_CLEANIT);
1443: if (error)
1444: break;
1445: }
1.1 pooka 1446: }
1.8 pooka 1447:
1.15 pooka 1448: if (error == 0 && ap->a_ioflag & IO_SYNC) {
1.8 pooka 1449: simple_lock(&vp->v_interlock);
1450: error = VOP_PUTPAGES(vp, trunc_page(origoff),
1.15 pooka 1451: round_page(uio->uio_offset),
1452: PGO_CLEANIT | PGO_SYNCIO);
1.1 pooka 1453: }
1454:
1.8 pooka 1455: puffs_updatenode(vp, uflags);
1456: } else {
1.19 pooka 1457: /* tomove is non-increasing */
1.1 pooka 1458: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.8 pooka 1459: argsize = sizeof(struct puffs_vnreq_write) + tomove;
1460: write_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
1461:
1462: while (uio->uio_resid > 0) {
1463: write_argp->pvnr_ioflag = ap->a_ioflag;
1464: write_argp->pvnr_resid = tomove;
1465: write_argp->pvnr_offset = uio->uio_offset;
1466: puffs_credcvt(&write_argp->pvnr_cred, ap->a_cred);
1467: error = uiomove(write_argp->pvnr_data, tomove, uio);
1468: if (error)
1469: break;
1470:
1471: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
1472: PUFFS_VN_WRITE, write_argp, argsize,
1473: VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1474: if (error) {
1475: /* restore uiomove */
1476: uio->uio_resid += tomove;
1477: uio->uio_offset -= tomove;
1478: break;
1479: }
1480: if (write_argp->pvnr_resid > tomove) {
1481: /*
1482: * XXX: correct file size is a mystery,
1483: * we can only guess
1484: */
1485: error = EINVAL;
1486: break;
1487: }
1488:
1489: /* adjust file size */
1.20 pooka 1490: if (vp->v_size < uio->uio_offset)
1491: uvm_vnp_setsize(vp, uio->uio_offset);
1.8 pooka 1492:
1493: /* didn't move everything? bad userspace. bail */
1494: if (write_argp->pvnr_resid != 0) {
1495: uio->uio_resid += write_argp->pvnr_resid;
1496: uio->uio_offset -= write_argp->pvnr_resid;
1497: error = EIO;
1498: break;
1499: }
1500:
1501: tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1502: }
1.1 pooka 1503: }
1504:
1.8 pooka 1505: if (write_argp)
1506: free(write_argp, M_PUFFS);
1.1 pooka 1507: return error;
1508: }
1509:
1510: static int puffs_fcnioctl(struct vop_ioctl_args * /*XXX*/, int);
1511:
1512: #define FCNIOCTL_ARG_MAX 1<<16
1513: int
1514: puffs_fcnioctl(struct vop_ioctl_args *ap, int puffsop)
1515: {
1.24 pooka 1516:
1517: /* currently not supported */
1518: return EOPNOTSUPP;
1519: #if 0
1.1 pooka 1520: /* struct vop_ioctl_args {
1521: const struct vnodeop_desc *a_desc;
1522: struct vnode *a_vp;
1523: u_long a_command;
1524: void *a_data;
1525: int a_fflag;
1526: kauth_cred_t a_cred;
1527: struct lwp *a_l;
1528: } *ap = v; */
1529: struct puffs_mount *pmp;
1530: struct puffs_sizepark pspark;
1531: void *kernbuf;
1532: size_t copylen;
1533: int error;
1534:
1535: PUFFS_VNREQ(fcnioctl);
1536:
1537: /*
1538: * Since this op gives the filesystem (almost) complete control on
1539: * how much it is allowed to copy from the calling process
1540: * address space, do not enable it by default, since it would
1541: * be a whopping security hole.
1542: */
1543: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1.18 pooka 1544: if ((pmp->pmp_flags & PUFFS_KFLAG_ALLOWCTL) == 0)
1.1 pooka 1545: return EINVAL; /* only shoe that fits */
1546:
1547: /* fill in sizereq and store it */
1548: pspark.pkso_reqid = puffs_getreqid(pmp);
1549: pspark.pkso_reqtype = PUFFS_SIZEOPREQ_BUF_IN;
1550: pspark.pkso_copybuf = ap->a_data;
1551: pspark.pkso_bufsize = FCNIOCTL_ARG_MAX;
1552: TAILQ_INSERT_TAIL(&pmp->pmp_req_sizepark, &pspark, pkso_entries);
1553:
1554: /* then fill in actual request and shoot it off */
1555: fcnioctl_arg.pvnr_command = ap->a_command;
1556: fcnioctl_arg.pvnr_fflag = ap->a_fflag;
1557: puffs_credcvt(&fcnioctl_arg.pvnr_cred, ap->a_cred);
1558: fcnioctl_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
1559:
1560: error = puffs_vntouser_req(MPTOPUFFSMP(ap->a_vp->v_mount), puffsop,
1561: &fcnioctl_arg, sizeof(fcnioctl_arg), VPTOPNC(ap->a_vp),
1562: pspark.pkso_reqid, NULL, NULL);
1563:
1564: /* if we don't need to copy data, we're done */
1565: if (error || !fcnioctl_arg.pvnr_copyback)
1566: return error;
1567:
1568: copylen = MIN(FCNIOCTL_ARG_MAX, fcnioctl_arg.pvnr_datalen);
1569: kernbuf = malloc(copylen, M_PUFFS, M_WAITOK);
1570: error = copyin(fcnioctl_arg.pvnr_data, kernbuf, copylen);
1571: if (error)
1572: goto out;
1573: error = copyout(kernbuf, ap->a_data, copylen);
1574:
1575: out:
1576: free(kernbuf, M_PUFFS);
1577: return error;
1.24 pooka 1578: #endif
1.1 pooka 1579: }
1580:
1581: int
1582: puffs_ioctl(void *v)
1583: {
1584:
1585: return puffs_fcnioctl(v, PUFFS_VN_IOCTL);
1586: }
1587:
1588: int
1589: puffs_fcntl(void *v)
1590: {
1591:
1592: return puffs_fcnioctl(v, PUFFS_VN_FCNTL);
1593: }
1594:
1595: int
1596: puffs_print(void *v)
1597: {
1598: struct vop_print_args /* {
1599: struct vnode *a_vp;
1600: } */ *ap = v;
1.17 pooka 1601: struct puffs_mount *pmp;
1.1 pooka 1602: struct vnode *vp = ap->a_vp;
1.2 pooka 1603: struct puffs_node *pn = vp->v_data;
1.1 pooka 1604:
1605: PUFFS_VNREQ(print);
1606:
1.17 pooka 1607: pmp = MPTOPUFFSMP(vp->v_mount);
1608:
1.1 pooka 1609: /* kernel portion */
1.2 pooka 1610: printf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
1611: " userspace cookie: %p\n", vp, pn, pn->pn_cookie);
1.6 pooka 1612: if (vp->v_type == VFIFO)
1613: fifo_printinfo(vp);
1.1 pooka 1614: lockmgr_printinfo(&vp->v_lock);
1615:
1616: /* userspace portion */
1.17 pooka 1617: if (EXISTSOP(pmp, PRINT))
1618: puffs_vntouser(pmp, PUFFS_VN_PRINT,
1619: &print_arg, sizeof(print_arg), VPTOPNC(ap->a_vp),
1620: LOCKEDVP(ap->a_vp), NULL);
1621:
1622: return 0;
1.1 pooka 1623: }
1624:
1625: int
1626: puffs_pathconf(void *v)
1627: {
1628: struct vop_pathconf_args /* {
1629: const struct vnodeop_desc *a_desc;
1630: struct vnode *a_vp;
1631: int a_name;
1632: register_t *a_retval;
1633: } */ *ap = v;
1634: int error;
1635:
1636: PUFFS_VNREQ(pathconf);
1637:
1638: pathconf_arg.pvnr_name = ap->a_name;
1639:
1640: error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
1641: PUFFS_VN_PATHCONF, &pathconf_arg, sizeof(pathconf_arg),
1642: VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1643: if (error)
1644: return error;
1645:
1646: *ap->a_retval = pathconf_arg.pvnr_retval;
1647:
1648: return 0;
1649: }
1650:
1651: int
1652: puffs_advlock(void *v)
1653: {
1654: struct vop_advlock_args /* {
1655: const struct vnodeop_desc *a_desc;
1656: struct vnode *a_vp;
1657: void *a_id;
1658: int a_op;
1659: struct flock *a_fl;
1660: int a_flags;
1661: } */ *ap = v;
1662: int error;
1663:
1664: PUFFS_VNREQ(advlock);
1665:
1666: error = copyin(ap->a_fl, &advlock_arg.pvnr_fl, sizeof(struct flock));
1667: if (error)
1668: return error;
1669: advlock_arg.pvnr_id = ap->a_id;
1670: advlock_arg.pvnr_op = ap->a_op;
1671: advlock_arg.pvnr_flags = ap->a_flags;
1672:
1673: return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_ADVLOCK,
1674: &advlock_arg, sizeof(advlock_arg), VPTOPNC(ap->a_vp), NULL, NULL);
1675: }
1.8 pooka 1676: /*
1677: * This maps itself to PUFFS_VN_READ/WRITE for data transfer.
1678: */
1679: int
1680: puffs_strategy(void *v)
1681: {
1682: struct vop_strategy_args /* {
1683: const struct vnodeop_desc *a_desc;
1684: struct vnode *a_vp;
1685: struct buf *a_bp;
1686: } */ *ap = v;
1687: struct puffs_mount *pmp;
1.35 pooka 1688: struct vnode *vp = ap->a_vp;
1.38 pooka 1689: struct puffs_node *pn;
1.14 pooka 1690: struct puffs_vnreq_read *read_argp = NULL;
1691: struct puffs_vnreq_write *write_argp = NULL;
1.8 pooka 1692: struct buf *bp;
1693: size_t argsize;
1.14 pooka 1694: size_t tomove, moved;
1.35 pooka 1695: int error, dowritefaf;
1.8 pooka 1696:
1.35 pooka 1697: pmp = MPTOPUFFSMP(vp->v_mount);
1.8 pooka 1698: bp = ap->a_bp;
1.36 pooka 1699: error = 0;
1700: dowritefaf = 0;
1.38 pooka 1701: pn = VPTOPP(vp);
1702:
1703: if (((bp->b_flags & B_READ) && !EXISTSOP(pmp, READ))
1704: || (((bp->b_flags & B_READ) == 0) && !EXISTSOP(pmp, WRITE))) {
1705: error = EOPNOTSUPP;
1706: goto out;
1707: }
1.8 pooka 1708:
1.38 pooka 1709: /*
1710: * Short-circuit optimization: don't flush buffer in between
1711: * VOP_INACTIVE and VOP_RECLAIM in case the node has no references.
1712: */
1713: if (pn->pn_stat & PNODE_NOREFS) {
1714: bp->b_resid = 0;
1715: goto out;
1716: }
1.17 pooka 1717:
1.8 pooka 1718: #ifdef DIAGNOSTIC
1.14 pooka 1719: if (bp->b_resid > pmp->pmp_req_maxsize - PUFFS_REQSTRUCT_MAX)
1720: panic("puffs_strategy: wildly inappropriate buf resid %d",
1721: bp->b_resid);
1.8 pooka 1722: #endif
1723:
1.35 pooka 1724: /*
1725: * See explanation for the necessity of a FAF in puffs_fsync
1726: *
1727: * XXgoddamnX: B_WRITE is a "pseudo flag"
1728: */
1729: if ((bp->b_flags & B_READ) == 0) {
1730: simple_lock(&vp->v_interlock);
1731: if (vp->v_flag & VXLOCK)
1732: dowritefaf = 1;
1733: simple_unlock(&vp->v_interlock);
1734: }
1735:
1.8 pooka 1736: if (bp->b_flags & B_READ) {
1737: argsize = sizeof(struct puffs_vnreq_read);
1.14 pooka 1738: read_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);
1739: if (read_argp == NULL) {
1740: error = ENOMEM;
1741: goto out;
1742: }
1743:
1744: tomove = PUFFS_TOMOVE(bp->b_resid, pmp);
1745:
1.8 pooka 1746: read_argp->pvnr_ioflag = 0;
1.14 pooka 1747: read_argp->pvnr_resid = tomove;
1.8 pooka 1748: read_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
1.14 pooka 1749: puffs_credcvt(&read_argp->pvnr_cred, FSCRED);
1.8 pooka 1750:
1751: error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
1.35 pooka 1752: (void **)&read_argp, &argsize, read_argp->pvnr_resid,
1753: VPTOPNC(vp), LOCKEDVP(vp), NULL);
1.8 pooka 1754:
1755: if (error)
1.14 pooka 1756: goto out;
1.8 pooka 1757:
1.14 pooka 1758: if (read_argp->pvnr_resid > tomove) {
1759: error = EINVAL;
1760: goto out;
1761: }
1762:
1763: moved = tomove - read_argp->pvnr_resid;
1764:
1765: (void)memcpy(bp->b_data, read_argp->pvnr_data, moved);
1766: bp->b_resid -= moved;
1.8 pooka 1767: } else {
1768: argsize = sizeof(struct puffs_vnreq_write) + bp->b_bcount;
1.14 pooka 1769: write_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);
1770: if (write_argp == NULL) {
1771: error = ENOMEM;
1772: goto out;
1773: }
1774:
1775: tomove = PUFFS_TOMOVE(bp->b_resid, pmp);
1776:
1.8 pooka 1777: write_argp->pvnr_ioflag = 0;
1.14 pooka 1778: write_argp->pvnr_resid = tomove;
1.8 pooka 1779: write_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
1.14 pooka 1780: puffs_credcvt(&write_argp->pvnr_cred, FSCRED);
1781:
1782: (void)memcpy(&write_argp->pvnr_data, bp->b_data, tomove);
1.8 pooka 1783:
1.35 pooka 1784: if (dowritefaf) {
1785: /*
1786: * assume FAF moves everything. frankly, we don't
1787: * really have a choice.
1788: */
1789: puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount),
1790: PUFFS_VN_WRITE, write_argp, argsize, VPTOPNC(vp));
1791: bp->b_resid -= tomove;
1792: } else {
1793: error = puffs_vntouser(MPTOPUFFSMP(vp->v_mount),
1794: PUFFS_VN_WRITE, write_argp, argsize, VPTOPNC(vp),
1795: vp, NULL);
1796: if (error)
1797: goto out;
1.8 pooka 1798:
1.35 pooka 1799: moved = tomove - write_argp->pvnr_resid;
1800: if (write_argp->pvnr_resid > tomove) {
1801: error = EINVAL;
1802: goto out;
1803: }
1.9 pooka 1804:
1.35 pooka 1805: bp->b_resid -= moved;
1806: if (write_argp->pvnr_resid != 0)
1807: error = EIO;
1.14 pooka 1808: }
1.8 pooka 1809: }
1810:
1811: out:
1.14 pooka 1812: if (read_argp)
1813: free(read_argp, M_PUFFS);
1.35 pooka 1814: if (write_argp && !dowritefaf)
1.14 pooka 1815: free(write_argp, M_PUFFS);
1816:
1.40 ! pooka 1817: if (error) {
! 1818: bp->b_error = error;
! 1819: bp->b_flags |= B_ERROR;
! 1820: }
! 1821:
1.38 pooka 1822: biodone(bp);
1.8 pooka 1823: return error;
1824: }
1.1 pooka 1825:
1.21 pooka 1826: int
1827: puffs_mmap(void *v)
1828: {
1829: struct vop_mmap_args /* {
1830: const struct vnodeop_desc *a_desc;
1831: struct vnode *a_vp;
1832: int a_fflags;
1833: kauth_cred_t a_cred;
1834: struct lwp *a_l;
1835: } */ *ap = v;
1836: struct puffs_mount *pmp;
1837: int error;
1838:
1839: PUFFS_VNREQ(mmap);
1840:
1841: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1842:
1.23 pooka 1843: if (!PUFFS_DOCACHE(pmp))
1.21 pooka 1844: return genfs_eopnotsupp(v);
1845:
1846: if (EXISTSOP(pmp, MMAP)) {
1847: mmap_arg.pvnr_fflags = ap->a_fflags;
1848: puffs_credcvt(&mmap_arg.pvnr_cred, ap->a_cred);
1849: mmap_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
1850:
1851: error = puffs_vntouser(pmp, PUFFS_VN_MMAP,
1852: &mmap_arg, sizeof(mmap_arg),
1853: VPTOPNC(ap->a_vp), NULL, NULL);
1854: } else {
1855: error = genfs_mmap(v);
1856: }
1857:
1858: return error;
1859: }
1860:
1861:
1.1 pooka 1862: /*
1863: * The rest don't get a free trip to userspace and back, they
1864: * have to stay within the kernel.
1865: */
1866:
1867: /*
1.8 pooka 1868: * bmap doesn't really make any sense for puffs, so just 1:1 map it.
1869: * well, maybe somehow, somewhere, some day ....
1870: */
1871: int
1872: puffs_bmap(void *v)
1873: {
1874: struct vop_bmap_args /* {
1875: const struct vnodeop_desc *a_desc;
1876: struct vnode *a_vp;
1877: daddr_t a_bn;
1878: struct vnode **a_vpp;
1879: daddr_t *a_bnp;
1880: int *a_runp;
1881: } */ *ap = v;
1882: struct puffs_mount *pmp;
1883:
1884: pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1885:
1886: if (ap->a_vpp)
1887: *ap->a_vpp = ap->a_vp;
1888: if (ap->a_bnp)
1889: *ap->a_bnp = ap->a_bn;
1890: if (ap->a_runp)
1891: *ap->a_runp = pmp->pmp_req_maxsize - PUFFS_REQSTRUCT_MAX;
1892:
1893: return 0;
1894: }
1895:
1896: /*
1.1 pooka 1897: * moreXXX: yes, todo
1898: */
1899: int
1900: puffs_lock(void *v)
1901: {
1902: struct vop_lock_args /* {
1903: struct vnode *a_vp;
1904: int a_flags;
1905: } */ *ap = v;
1906: struct vnode *vp = ap->a_vp;
1907:
1908: #if 0
1909: DPRINTF(("puffs_lock: lock %p, args 0x%x\n", vp, ap->a_flags));
1910: #endif
1911:
1912: return lockmgr(&vp->v_lock, ap->a_flags, &vp->v_interlock);
1913: }
1914:
1915: int
1916: puffs_unlock(void *v)
1917: {
1918: struct vop_unlock_args /* {
1919: struct vnode *a_vp;
1920: int a_flags;
1921: } */ *ap = v;
1922: struct vnode *vp = ap->a_vp;
1923:
1924: #if 0
1925: DPRINTF(("puffs_unlock: lock %p, args 0x%x\n", vp, ap->a_flags));
1926: #endif
1927:
1928: return lockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock);
1929: }
1930:
1931: int
1932: puffs_islocked(void *v)
1933: {
1934: struct vop_islocked_args *ap = v;
1935: int rv;
1936:
1937: rv = lockstatus(&ap->a_vp->v_lock);
1938: return rv;
1939: }
1940:
1941: int
1942: puffs_generic(void *v)
1943: {
1944: struct vop_generic_args *ap = v;
1945:
1946: (void)ap;
1947: DPRINTF(("puffs_generic: ap->a_desc = %s\n", ap->a_desc->vdesc_name));
1948:
1949: return EOPNOTSUPP;
1950: }
1.26 pooka 1951:
1952:
1953: /*
1.31 pooka 1954: * spec & fifo. These call the miscfs spec and fifo vectors, but issue
1.26 pooka 1955: * FAF update information for the puffs node first.
1956: */
1957: int
1958: puffs_spec_read(void *v)
1959: {
1960: struct vop_read_args /* {
1961: const struct vnodeop_desc *a_desc;
1962: struct vnode *a_vp;
1963: struct uio *a_uio;
1964: int a_ioflag;
1965: kauth_cred_t a_cred;
1966: } */ *ap = v;
1967:
1968: puffs_updatenode(ap->a_vp, PUFFS_UPDATEATIME);
1969: return VOCALL(spec_vnodeop_p, VOFFSET(vop_read), v);
1970: }
1971:
1972: int
1973: puffs_spec_write(void *v)
1974: {
1975: struct vop_write_args /* {
1976: const struct vnodeop_desc *a_desc;
1977: struct vnode *a_vp;
1978: struct uio *a_uio;
1979: int a_ioflag;
1980: kauth_cred_t a_cred;
1981: } */ *ap = v;
1982:
1983: puffs_updatenode(ap->a_vp, PUFFS_UPDATEMTIME);
1984: return VOCALL(spec_vnodeop_p, VOFFSET(vop_write), v);
1985: }
1986:
1987: int
1988: puffs_fifo_read(void *v)
1989: {
1990: struct vop_read_args /* {
1991: const struct vnodeop_desc *a_desc;
1992: struct vnode *a_vp;
1993: struct uio *a_uio;
1994: int a_ioflag;
1995: kauth_cred_t a_cred;
1996: } */ *ap = v;
1997:
1998: puffs_updatenode(ap->a_vp, PUFFS_UPDATEATIME);
1999: return VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), v);
2000: }
2001:
2002: int
2003: puffs_fifo_write(void *v)
2004: {
2005: struct vop_write_args /* {
2006: const struct vnodeop_desc *a_desc;
2007: struct vnode *a_vp;
2008: struct uio *a_uio;
2009: int a_ioflag;
2010: kauth_cred_t a_cred;
2011: } */ *ap = v;
2012:
2013: puffs_updatenode(ap->a_vp, PUFFS_UPDATEMTIME);
2014: return VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), v);
2015: }
CVSweb <webmaster@jp.NetBSD.org>