Annotation of src/sys/miscfs/kernfs/kernfs_vnops.c, Revision 1.129
1.129 ! chs 1: /* $NetBSD: kernfs_vnops.c,v 1.128 2006/11/16 01:33:38 christos Exp $ */
1.27 cgd 2:
1.1 cgd 3: /*
1.23 mycroft 4: * Copyright (c) 1992, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
1.17 cgd 7: * This code is derived from software donated to Berkeley by
1.1 cgd 8: * Jan-Simon Pendry.
9: *
1.2 cgd 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.
1.89 agc 18: * 3. Neither the name of the University nor the names of its contributors
1.2 cgd 19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
1.1 cgd 21: *
1.2 cgd 22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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
28: * OR 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.
1.1 cgd 33: *
1.57 fvdl 34: * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95
1.1 cgd 35: */
36:
37: /*
1.23 mycroft 38: * Kernel parameter filesystem (/kern)
1.1 cgd 39: */
1.77 lukem 40:
41: #include <sys/cdefs.h>
1.129 ! chs 42: __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.128 2006/11/16 01:33:38 christos Exp $");
1.90 itojun 43:
44: #ifdef _KERNEL_OPT
45: #include "opt_ipsec.h"
46: #endif
1.55 mrg 47:
1.14 mycroft 48: #include <sys/param.h>
49: #include <sys/systm.h>
50: #include <sys/kernel.h>
1.23 mycroft 51: #include <sys/vmmeter.h>
1.14 mycroft 52: #include <sys/time.h>
53: #include <sys/proc.h>
1.23 mycroft 54: #include <sys/vnode.h>
55: #include <sys/malloc.h>
1.14 mycroft 56: #include <sys/file.h>
57: #include <sys/stat.h>
58: #include <sys/mount.h>
59: #include <sys/namei.h>
60: #include <sys/buf.h>
1.23 mycroft 61: #include <sys/dirent.h>
1.28 mycroft 62: #include <sys/msgbuf.h>
1.44 mycroft 63:
64: #include <miscfs/genfs/genfs.h>
1.17 cgd 65: #include <miscfs/kernfs/kernfs.h>
1.63 mrg 66:
1.90 itojun 67: #ifdef IPSEC
68: #include <sys/mbuf.h>
69: #include <net/route.h>
70: #include <netinet/in.h>
71: #include <netinet6/ipsec.h>
72: #include <netkey/key.h>
73: #endif
74:
1.54 mrg 75: #include <uvm/uvm_extern.h>
76:
1.17 cgd 77: #define KSTRING 256 /* Largest I/O available via this filesystem */
78: #define UIO_MX 32
1.1 cgd 79:
1.23 mycroft 80: #define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH)
81: #define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
1.101 cl 82: #define UREAD_MODE (S_IRUSR)
1.102 cl 83: #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
84: #define UDIR_MODE (S_IRUSR|S_IXUSR)
1.23 mycroft 85:
1.90 itojun 86: #define N(s) sizeof(s)-1, s
1.75 jdolecek 87: const struct kern_target kern_targets[] = {
1.1 cgd 88: /* NOTE: The name must be less than UIO_MX-16 chars in length */
1.23 mycroft 89: /* name data tag type ro/rw */
1.98 darcy 90: { DT_DIR, N("."), 0, KFSkern, VDIR, DIR_MODE },
91: { DT_DIR, N(".."), 0, KFSroot, VDIR, DIR_MODE },
92: { DT_REG, N("boottime"), &boottime.tv_sec, KFSint, VREG, READ_MODE },
1.109 christos 93: /* XXXUNCONST */
94: { DT_REG, N("copyright"), __UNCONST(copyright),
1.98 darcy 95: KFSstring, VREG, READ_MODE },
96: { DT_REG, N("hostname"), 0, KFShostname, VREG, WRITE_MODE },
97: { DT_REG, N("hz"), &hz, KFSint, VREG, READ_MODE },
1.90 itojun 98: #ifdef IPSEC
1.98 darcy 99: { DT_DIR, N("ipsecsa"), 0, KFSipsecsadir, VDIR, UDIR_MODE },
100: { DT_DIR, N("ipsecsp"), 0, KFSipsecspdir, VDIR, UDIR_MODE },
1.90 itojun 101: #endif
1.98 darcy 102: { DT_REG, N("loadavg"), 0, KFSavenrun, VREG, READ_MODE },
103: { DT_REG, N("msgbuf"), 0, KFSmsgbuf, VREG, READ_MODE },
104: { DT_REG, N("pagesize"), &uvmexp.pagesize, KFSint, VREG, READ_MODE },
105: { DT_REG, N("physmem"), &physmem, KFSint, VREG, READ_MODE },
1.17 cgd 106: #if 0
1.98 darcy 107: { DT_DIR, N("root"), 0, KFSnull, VDIR, DIR_MODE },
1.17 cgd 108: #endif
1.98 darcy 109: { DT_BLK, N("rootdev"), &rootdev, KFSdevice, VBLK, READ_MODE },
110: { DT_CHR, N("rrootdev"), &rrootdev, KFSdevice, VCHR, READ_MODE },
111: { DT_REG, N("time"), 0, KFStime, VREG, READ_MODE },
1.109 christos 112: /* XXXUNCONST */
113: { DT_REG, N("version"), __UNCONST(version),
1.98 darcy 114: KFSstring, VREG, READ_MODE },
1.90 itojun 115: };
1.102 cl 116: const struct kern_target subdir_targets[] = {
117: /* NOTE: The name must be less than UIO_MX-16 chars in length */
118: /* name data tag type ro/rw */
119: { DT_DIR, N("."), 0, KFSsubdir, VDIR, DIR_MODE },
120: { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
121: };
1.90 itojun 122: #ifdef IPSEC
123: const struct kern_target ipsecsa_targets[] = {
124: /* NOTE: The name must be less than UIO_MX-16 chars in length */
125: /* name data tag type ro/rw */
1.98 darcy 126: { DT_DIR, N("."), 0, KFSipsecsadir, VDIR, DIR_MODE },
127: { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
1.90 itojun 128: };
129: const struct kern_target ipsecsp_targets[] = {
130: /* NOTE: The name must be less than UIO_MX-16 chars in length */
131: /* name data tag type ro/rw */
1.98 darcy 132: { DT_DIR, N("."), 0, KFSipsecspdir, VDIR, DIR_MODE },
133: { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
1.90 itojun 134: };
1.101 cl 135: const struct kern_target ipsecsa_kt =
136: { DT_DIR, N(""), 0, KFSipsecsa, VREG, UREAD_MODE };
137: const struct kern_target ipsecsp_kt =
138: { DT_DIR, N(""), 0, KFSipsecsp, VREG, UREAD_MODE };
1.90 itojun 139: #endif
1.23 mycroft 140: #undef N
1.102 cl 141: SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
142: SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
1.90 itojun 143: int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.102 cl 144: const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.90 itojun 145: #ifdef IPSEC
146: int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
147: int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
1.102 cl 148: int nkern_dirs = 4; /* 2 extra subdirs */
149: #else
150: int nkern_dirs = 2;
1.90 itojun 151: #endif
152:
1.102 cl 153: int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
1.124 bouyer 154: int kernfs_try_xread(kfstype, const struct kernfs_node *, char **,
1.123 bouyer 155: size_t, int);
1.102 cl 156: int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
157: size_t, int);
158:
1.123 bouyer 159: static int kernfs_default_xread(void *v);
1.102 cl 160: static int kernfs_default_xwrite(void *v);
161: static int kernfs_default_fileop_getattr(void *);
162:
163: /* must include all fileop's */
164: const struct kernfs_fileop kernfs_default_fileops[] = {
1.123 bouyer 165: { .kf_fileop = KERNFS_XREAD },
1.102 cl 166: { .kf_fileop = KERNFS_XWRITE },
167: { .kf_fileop = KERNFS_FILEOP_OPEN },
168: { .kf_fileop = KERNFS_FILEOP_GETATTR,
1.125 christos 169: .kf_vop = kernfs_default_fileop_getattr },
1.102 cl 170: { .kf_fileop = KERNFS_FILEOP_IOCTL },
171: { .kf_fileop = KERNFS_FILEOP_CLOSE },
1.125 christos 172: { .kf_fileop = KERNFS_FILEOP_READ,
173: .kf_vop = kernfs_default_xread },
174: { .kf_fileop = KERNFS_FILEOP_WRITE,
175: .kf_vop = kernfs_default_xwrite },
1.102 cl 176: };
1.1 cgd 177:
1.110 xtraeme 178: int kernfs_lookup(void *);
1.85 jdolecek 179: #define kernfs_create genfs_eopnotsupp
180: #define kernfs_mknod genfs_eopnotsupp
1.110 xtraeme 181: int kernfs_open(void *);
182: int kernfs_close(void *);
183: int kernfs_access(void *);
184: int kernfs_getattr(void *);
185: int kernfs_setattr(void *);
186: int kernfs_read(void *);
187: int kernfs_write(void *);
1.65 wrstuden 188: #define kernfs_fcntl genfs_fcntl
1.110 xtraeme 189: int kernfs_ioctl(void *);
1.45 mycroft 190: #define kernfs_poll genfs_poll
1.57 fvdl 191: #define kernfs_revoke genfs_revoke
1.44 mycroft 192: #define kernfs_fsync genfs_nullop
193: #define kernfs_seek genfs_nullop
1.85 jdolecek 194: #define kernfs_remove genfs_eopnotsupp
1.110 xtraeme 195: int kernfs_link(void *);
1.85 jdolecek 196: #define kernfs_rename genfs_eopnotsupp
197: #define kernfs_mkdir genfs_eopnotsupp
198: #define kernfs_rmdir genfs_eopnotsupp
1.110 xtraeme 199: int kernfs_symlink(void *);
200: int kernfs_readdir(void *);
1.44 mycroft 201: #define kernfs_readlink genfs_eopnotsupp
202: #define kernfs_abortop genfs_abortop
1.110 xtraeme 203: int kernfs_inactive(void *);
204: int kernfs_reclaim(void *);
1.64 wrstuden 205: #define kernfs_lock genfs_lock
206: #define kernfs_unlock genfs_unlock
1.44 mycroft 207: #define kernfs_bmap genfs_badop
208: #define kernfs_strategy genfs_badop
1.110 xtraeme 209: int kernfs_print(void *);
1.64 wrstuden 210: #define kernfs_islocked genfs_islocked
1.110 xtraeme 211: int kernfs_pathconf(void *);
1.62 kleink 212: #define kernfs_advlock genfs_einval
1.44 mycroft 213: #define kernfs_bwrite genfs_eopnotsupp
1.79 chs 214: #define kernfs_putpages genfs_putpages
1.41 christos 215:
1.110 xtraeme 216: static int kernfs_xread(struct kernfs_node *, int, char **,
217: size_t, size_t *);
218: static int kernfs_xwrite(const struct kernfs_node *, char *, size_t);
1.41 christos 219:
1.110 xtraeme 220: int (**kernfs_vnodeop_p)(void *);
1.71 jdolecek 221: const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
1.41 christos 222: { &vop_default_desc, vn_default_error },
1.44 mycroft 223: { &vop_lookup_desc, kernfs_lookup }, /* lookup */
224: { &vop_create_desc, kernfs_create }, /* create */
225: { &vop_mknod_desc, kernfs_mknod }, /* mknod */
226: { &vop_open_desc, kernfs_open }, /* open */
227: { &vop_close_desc, kernfs_close }, /* close */
228: { &vop_access_desc, kernfs_access }, /* access */
229: { &vop_getattr_desc, kernfs_getattr }, /* getattr */
230: { &vop_setattr_desc, kernfs_setattr }, /* setattr */
231: { &vop_read_desc, kernfs_read }, /* read */
232: { &vop_write_desc, kernfs_write }, /* write */
1.65 wrstuden 233: { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */
1.44 mycroft 234: { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
1.45 mycroft 235: { &vop_poll_desc, kernfs_poll }, /* poll */
1.57 fvdl 236: { &vop_revoke_desc, kernfs_revoke }, /* revoke */
1.44 mycroft 237: { &vop_fsync_desc, kernfs_fsync }, /* fsync */
238: { &vop_seek_desc, kernfs_seek }, /* seek */
239: { &vop_remove_desc, kernfs_remove }, /* remove */
240: { &vop_link_desc, kernfs_link }, /* link */
241: { &vop_rename_desc, kernfs_rename }, /* rename */
242: { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
243: { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
244: { &vop_symlink_desc, kernfs_symlink }, /* symlink */
245: { &vop_readdir_desc, kernfs_readdir }, /* readdir */
246: { &vop_readlink_desc, kernfs_readlink }, /* readlink */
247: { &vop_abortop_desc, kernfs_abortop }, /* abortop */
248: { &vop_inactive_desc, kernfs_inactive }, /* inactive */
249: { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
250: { &vop_lock_desc, kernfs_lock }, /* lock */
251: { &vop_unlock_desc, kernfs_unlock }, /* unlock */
252: { &vop_bmap_desc, kernfs_bmap }, /* bmap */
253: { &vop_strategy_desc, kernfs_strategy }, /* strategy */
254: { &vop_print_desc, kernfs_print }, /* print */
255: { &vop_islocked_desc, kernfs_islocked }, /* islocked */
256: { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */
257: { &vop_advlock_desc, kernfs_advlock }, /* advlock */
258: { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
1.79 chs 259: { &vop_putpages_desc, kernfs_putpages }, /* putpages */
1.76 chs 260: { NULL, NULL }
1.41 christos 261: };
1.71 jdolecek 262: const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
1.41 christos 263: { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
264:
1.116 perry 265: static inline int
1.102 cl 266: kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
267: {
268: if (a->kf_type < b->kf_type)
269: return -1;
270: if (a->kf_type > b->kf_type)
271: return 1;
272: if (a->kf_fileop < b->kf_fileop)
273: return -1;
274: if (a->kf_fileop > b->kf_fileop)
275: return 1;
276: return (0);
277: }
278:
279: SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
280: SPLAY_INITIALIZER(kfsfileoptree);
281: SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
282: SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
283:
284: kfstype
285: kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
286: {
287: static u_char nextfreetype = KFSlasttype;
288: struct kernfs_fileop *dkf, *fkf, skf;
289: int i;
290:
291: /* XXX need to keep track of dkf's memory if we support
292: deallocating types */
293: dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
294: memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
295:
296: for (i = 0; i < sizeof(kernfs_default_fileops) /
297: sizeof(kernfs_default_fileops[0]); i++) {
298: dkf[i].kf_type = nextfreetype;
299: SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
300: }
301:
302: for (i = 0; i < nkf; i++) {
303: skf.kf_type = nextfreetype;
304: skf.kf_fileop = kf[i].kf_fileop;
305: if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
1.125 christos 306: fkf->kf_vop = kf[i].kf_vop;
1.102 cl 307: }
308:
309: return nextfreetype++;
310: }
311:
312: int
313: kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
314: {
315: struct kernfs_fileop *kf, skf;
316:
317: skf.kf_type = type;
318: skf.kf_fileop = fileop;
319: if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
320: if (kf->kf_vop)
321: return kf->kf_vop(v);
322: return error;
323: }
324:
325: int
1.124 bouyer 326: kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp,
327: size_t len, int error)
328: {
329: struct kernfs_fileop *kf, skf;
330:
331: skf.kf_type = type;
332: skf.kf_fileop = KERNFS_XREAD;
333: if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
334: if (kf->kf_xread)
335: return kf->kf_xread(kfs, bfp, len);
336: return error;
337: }
338:
339: int
1.109 christos 340: kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,
1.102 cl 341: size_t len, int error)
342: {
343: struct kernfs_fileop *kf, skf;
344:
345: skf.kf_type = type;
346: skf.kf_fileop = KERNFS_XWRITE;
347: if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
348: if (kf->kf_xwrite)
1.109 christos 349: return kf->kf_xwrite(kfs, bf, len);
1.102 cl 350: return error;
351: }
352:
353: int
354: kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
355: {
356: struct kernfs_subdir *ks, *parent;
357:
358: if (pkt == NULL) {
359: SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
360: nkern_targets++;
361: if (dkt->dkt_kt.kt_vtype == VDIR)
362: nkern_dirs++;
363: } else {
364: parent = (struct kernfs_subdir *)pkt->kt_data;
365: SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
366: parent->ks_nentries++;
367: if (dkt->dkt_kt.kt_vtype == VDIR)
368: parent->ks_dirs++;
369: }
370: if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
371: ks = malloc(sizeof(struct kernfs_subdir),
372: M_TEMP, M_WAITOK);
373: SIMPLEQ_INIT(&ks->ks_entries);
374: ks->ks_nentries = 2; /* . and .. */
375: ks->ks_dirs = 2;
376: ks->ks_parent = pkt ? pkt : &kern_targets[0];
377: dkt->dkt_kt.kt_data = ks;
378: }
379: return 0;
380: }
381:
1.82 jdolecek 382: static int
1.90 itojun 383: kernfs_xread(kfs, off, bufp, len, wrlen)
384: struct kernfs_node *kfs;
1.28 mycroft 385: int off;
386: char **bufp;
1.82 jdolecek 387: size_t len;
388: size_t *wrlen;
1.1 cgd 389: {
1.90 itojun 390: const struct kern_target *kt;
391: #ifdef IPSEC
392: struct mbuf *m;
393: #endif
1.124 bouyer 394: int err;
1.90 itojun 395:
396: kt = kfs->kfs_kt;
1.1 cgd 397:
1.90 itojun 398: switch (kfs->kfs_type) {
1.98 darcy 399: case KFStime: {
1.1 cgd 400: struct timeval tv;
1.28 mycroft 401:
1.1 cgd 402: microtime(&tv);
1.90 itojun 403: snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
1.1 cgd 404: break;
405: }
406:
1.98 darcy 407: case KFSint: {
1.1 cgd 408: int *ip = kt->kt_data;
1.28 mycroft 409:
1.90 itojun 410: snprintf(*bufp, len, "%d\n", *ip);
1.1 cgd 411: break;
412: }
413:
1.98 darcy 414: case KFSstring: {
1.1 cgd 415: char *cp = kt->kt_data;
416:
1.28 mycroft 417: *bufp = cp;
418: break;
419: }
1.1 cgd 420:
1.98 darcy 421: case KFSmsgbuf: {
1.28 mycroft 422: long n;
423:
1.52 leo 424: /*
425: * deal with cases where the message buffer has
426: * become corrupted.
427: */
428: if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
429: msgbufenabled = 0;
430: return (ENXIO);
431: }
432:
433: /*
434: * Note that reads of /kern/msgbuf won't necessarily yield
435: * consistent results, if the message buffer is modified
436: * while the read is in progress. The worst that can happen
437: * is that incorrect data will be read. There's no way
438: * that this can crash the system unless the values in the
439: * message buffer header are corrupted, but that'll cause
440: * the system to die anyway.
441: */
1.82 jdolecek 442: if (off >= msgbufp->msg_bufs) {
443: *wrlen = 0;
1.28 mycroft 444: return (0);
1.82 jdolecek 445: }
1.28 mycroft 446: n = msgbufp->msg_bufx + off;
1.52 leo 447: if (n >= msgbufp->msg_bufs)
448: n -= msgbufp->msg_bufs;
449: len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
1.28 mycroft 450: *bufp = msgbufp->msg_bufc + n;
1.82 jdolecek 451: *wrlen = len;
452: return (0);
1.1 cgd 453: }
454:
1.98 darcy 455: case KFShostname: {
1.1 cgd 456: char *cp = hostname;
1.127 jmmv 457: size_t xlen = hostnamelen;
1.1 cgd 458:
1.90 itojun 459: if (xlen >= (len - 2))
1.1 cgd 460: return (EINVAL);
461:
1.60 perry 462: memcpy(*bufp, cp, xlen);
1.28 mycroft 463: (*bufp)[xlen] = '\n';
464: (*bufp)[xlen+1] = '\0';
1.90 itojun 465: len = strlen(*bufp);
1.1 cgd 466: break;
467: }
468:
1.98 darcy 469: case KFSavenrun:
1.31 mycroft 470: averunnable.fscale = FSCALE;
1.90 itojun 471: snprintf(*bufp, len, "%d %d %d %ld\n",
1.23 mycroft 472: averunnable.ldavg[0], averunnable.ldavg[1],
473: averunnable.ldavg[2], averunnable.fscale);
1.1 cgd 474: break;
475:
1.90 itojun 476: #ifdef IPSEC
1.98 darcy 477: case KFSipsecsa:
1.90 itojun 478: /*
479: * Note that SA configuration could be changed during the
480: * read operation, resulting in garbled output.
481: */
482: m = key_setdumpsa_spi(htonl(kfs->kfs_value));
483: if (!m)
484: return (ENOBUFS);
485: if (off >= m->m_pkthdr.len) {
486: *wrlen = 0;
487: m_freem(m);
488: return (0);
489: }
490: if (len > m->m_pkthdr.len - off)
491: len = m->m_pkthdr.len - off;
492: m_copydata(m, off, len, *bufp);
493: *wrlen = len;
494: m_freem(m);
495: return (0);
496:
1.98 darcy 497: case KFSipsecsp:
1.90 itojun 498: /*
499: * Note that SP configuration could be changed during the
500: * read operation, resulting in garbled output.
501: */
502: if (!kfs->kfs_v) {
503: struct secpolicy *sp;
504:
505: sp = key_getspbyid(kfs->kfs_value);
506: if (sp)
507: kfs->kfs_v = sp;
508: else
509: return (ENOENT);
510: }
511: m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
512: SADB_X_SPDGET, 0, 0);
513: if (!m)
514: return (ENOBUFS);
515: if (off >= m->m_pkthdr.len) {
516: *wrlen = 0;
517: m_freem(m);
518: return (0);
519: }
520: if (len > m->m_pkthdr.len - off)
521: len = m->m_pkthdr.len - off;
522: m_copydata(m, off, len, *bufp);
523: *wrlen = len;
524: m_freem(m);
525: return (0);
526: #endif
527:
1.1 cgd 528: default:
1.124 bouyer 529: err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len,
530: EOPNOTSUPP);
531: if (err)
532: return err;
1.1 cgd 533: }
534:
1.28 mycroft 535: len = strlen(*bufp);
536: if (len <= off)
1.82 jdolecek 537: *wrlen = 0;
538: else {
539: *bufp += off;
540: *wrlen = len - off;
541: }
542: return (0);
1.1 cgd 543: }
544:
1.82 jdolecek 545: static int
1.109 christos 546: kernfs_xwrite(kfs, bf, len)
1.90 itojun 547: const struct kernfs_node *kfs;
1.109 christos 548: char *bf;
1.82 jdolecek 549: size_t len;
1.1 cgd 550: {
1.23 mycroft 551:
1.90 itojun 552: switch (kfs->kfs_type) {
1.98 darcy 553: case KFShostname:
1.109 christos 554: if (bf[len-1] == '\n')
1.1 cgd 555: --len;
1.109 christos 556: memcpy(hostname, bf, len);
1.17 cgd 557: hostname[len] = '\0';
1.82 jdolecek 558: hostnamelen = (size_t) len;
1.1 cgd 559: return (0);
560:
561: default:
1.109 christos 562: return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO);
1.1 cgd 563: }
564: }
565:
1.17 cgd 566:
567: /*
1.1 cgd 568: * vp is the current namei directory
569: * ndp is the name to locate in that directory...
570: */
1.41 christos 571: int
572: kernfs_lookup(v)
573: void *v;
574: {
1.23 mycroft 575: struct vop_lookup_args /* {
576: struct vnode * a_dvp;
577: struct vnode ** a_vpp;
578: struct componentname * a_cnp;
1.41 christos 579: } */ *ap = v;
1.23 mycroft 580: struct componentname *cnp = ap->a_cnp;
581: struct vnode **vpp = ap->a_vpp;
582: struct vnode *dvp = ap->a_dvp;
1.48 cgd 583: const char *pname = cnp->cn_nameptr;
1.90 itojun 584: const struct kernfs_node *kfs;
1.75 jdolecek 585: const struct kern_target *kt;
1.102 cl 586: const struct dyn_kern_target *dkt;
587: const struct kernfs_subdir *ks;
1.129 ! chs 588: int error, i;
1.90 itojun 589: #ifdef IPSEC
590: char *ep;
591: u_int32_t id;
1.1 cgd 592: #endif
1.23 mycroft 593:
1.35 mycroft 594: *vpp = NULLVP;
595:
596: if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
597: return (EROFS);
598:
1.23 mycroft 599: if (cnp->cn_namelen == 1 && *pname == '.') {
600: *vpp = dvp;
1.1 cgd 601: VREF(dvp);
602: return (0);
603: }
1.13 cgd 604:
1.90 itojun 605: kfs = VTOKERN(dvp);
606: switch (kfs->kfs_type) {
1.98 darcy 607: case KFSkern:
1.90 itojun 608: /*
609: * Shouldn't get here with .. in the root node.
610: */
611: if (cnp->cn_flags & ISDOTDOT)
612: return (EIO);
1.64 wrstuden 613:
1.102 cl 614: for (i = 0; i < static_nkern_targets; i++) {
1.90 itojun 615: kt = &kern_targets[i];
616: if (cnp->cn_namelen == kt->kt_namlen &&
617: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
618: goto found;
619: }
1.102 cl 620: SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
621: if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
622: memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
623: kt = &dkt->dkt_kt;
624: goto found;
625: }
626: }
1.90 itojun 627: break;
1.25 mycroft 628:
1.90 itojun 629: found:
630: error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
631: return (error);
1.64 wrstuden 632:
1.102 cl 633: case KFSsubdir:
634: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
635: if (cnp->cn_flags & ISDOTDOT) {
636: kt = ks->ks_parent;
637: goto found;
638: }
639:
640: SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
641: if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
642: memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
643: kt = &dkt->dkt_kt;
644: goto found;
645: }
646: }
647: break;
648:
1.90 itojun 649: #ifdef IPSEC
1.98 darcy 650: case KFSipsecsadir:
1.100 cl 651: if (cnp->cn_flags & ISDOTDOT) {
652: kt = &kern_targets[0];
653: goto found;
654: }
655:
656: for (i = 2; i < nipsecsa_targets; i++) {
1.90 itojun 657: kt = &ipsecsa_targets[i];
658: if (cnp->cn_namelen == kt->kt_namlen &&
1.100 cl 659: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
660: goto found;
1.90 itojun 661: }
1.1 cgd 662:
1.90 itojun 663: ep = NULL;
664: id = strtoul(pname, &ep, 10);
665: if (!ep || *ep || ep == pname)
666: break;
1.1 cgd 667:
1.101 cl 668: error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
1.90 itojun 669: return (error);
1.23 mycroft 670:
1.98 darcy 671: case KFSipsecspdir:
1.100 cl 672: if (cnp->cn_flags & ISDOTDOT) {
673: kt = &kern_targets[0];
674: goto found;
675: }
676:
677: for (i = 2; i < nipsecsp_targets; i++) {
1.90 itojun 678: kt = &ipsecsp_targets[i];
679: if (cnp->cn_namelen == kt->kt_namlen &&
1.100 cl 680: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
681: goto found;
1.57 fvdl 682: }
1.90 itojun 683:
684: ep = NULL;
685: id = strtoul(pname, &ep, 10);
686: if (!ep || *ep || ep == pname)
687: break;
688:
1.101 cl 689: error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
1.90 itojun 690: return (error);
691: #endif
692:
693: default:
694: return (ENOTDIR);
695: }
696:
697: return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
698: }
699:
700: int
701: kernfs_open(v)
702: void *v;
703: {
704: struct vop_open_args /* {
705: struct vnode *a_vp;
706: int a_mode;
1.120 elad 707: kauth_cred_t a_cred;
1.115 christos 708: struct lwp *a_l;
1.90 itojun 709: } */ *ap = v;
710: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
711: #ifdef IPSEC
712: struct mbuf *m;
713: struct secpolicy *sp;
714: #endif
715:
716: switch (kfs->kfs_type) {
717: #ifdef IPSEC
1.98 darcy 718: case KFSipsecsa:
1.90 itojun 719: m = key_setdumpsa_spi(htonl(kfs->kfs_value));
720: if (m) {
721: m_freem(m);
722: return (0);
723: } else
724: return (ENOENT);
725:
1.98 darcy 726: case KFSipsecsp:
1.90 itojun 727: sp = key_getspbyid(kfs->kfs_value);
728: if (sp) {
729: kfs->kfs_v = sp;
730: return (0);
731: } else
732: return (ENOENT);
733: #endif
734:
735: default:
1.102 cl 736: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
737: v, 0);
1.23 mycroft 738: }
1.90 itojun 739: }
1.1 cgd 740:
1.90 itojun 741: int
742: kernfs_close(v)
743: void *v;
744: {
745: struct vop_close_args /* {
746: struct vnode *a_vp;
747: int a_fflag;
1.120 elad 748: kauth_cred_t a_cred;
1.115 christos 749: struct lwp *a_l;
1.90 itojun 750: } */ *ap = v;
751: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
752:
753: switch (kfs->kfs_type) {
754: #ifdef IPSEC
1.98 darcy 755: case KFSipsecsp:
1.90 itojun 756: key_freesp((struct secpolicy *)kfs->kfs_v);
757: break;
1.1 cgd 758: #endif
1.90 itojun 759:
760: default:
1.102 cl 761: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
762: v, 0);
1.57 fvdl 763: }
1.23 mycroft 764:
1.1 cgd 765: return (0);
766: }
767:
1.28 mycroft 768: int
1.41 christos 769: kernfs_access(v)
770: void *v;
771: {
1.23 mycroft 772: struct vop_access_args /* {
773: struct vnode *a_vp;
1.34 mycroft 774: int a_mode;
1.120 elad 775: kauth_cred_t a_cred;
1.115 christos 776: struct lwp *a_l;
1.41 christos 777: } */ *ap = v;
1.90 itojun 778: struct vattr va;
779: int error;
1.17 cgd 780:
1.115 christos 781: if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_l)) != 0)
1.90 itojun 782: return (error);
1.49 mycroft 783:
1.90 itojun 784: return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
785: ap->a_mode, ap->a_cred));
1.23 mycroft 786: }
787:
1.102 cl 788: static int
789: kernfs_default_fileop_getattr(v)
790: void *v;
791: {
792: struct vop_getattr_args /* {
793: struct vnode *a_vp;
794: struct vattr *a_vap;
1.120 elad 795: kauth_cred_t a_cred;
1.115 christos 796: struct lwp *a_l;
1.102 cl 797: } */ *ap = v;
798: struct vattr *vap = ap->a_vap;
799:
800: vap->va_nlink = 1;
801: vap->va_bytes = vap->va_size = 0;
802:
803: return 0;
804: }
805:
1.41 christos 806: int
807: kernfs_getattr(v)
808: void *v;
809: {
1.23 mycroft 810: struct vop_getattr_args /* {
811: struct vnode *a_vp;
812: struct vattr *a_vap;
1.120 elad 813: kauth_cred_t a_cred;
1.115 christos 814: struct lwp *a_l;
1.41 christos 815: } */ *ap = v;
1.90 itojun 816: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.102 cl 817: struct kernfs_subdir *ks;
1.23 mycroft 818: struct vattr *vap = ap->a_vap;
1.1 cgd 819: int error = 0;
1.109 christos 820: char strbuf[KSTRING], *bf;
1.90 itojun 821: size_t nread, total;
1.1 cgd 822:
1.90 itojun 823: VATTR_NULL(vap);
824: vap->va_type = ap->a_vp->v_type;
1.17 cgd 825: vap->va_uid = 0;
826: vap->va_gid = 0;
1.90 itojun 827: vap->va_mode = kfs->kfs_mode;
828: vap->va_fileid = kfs->kfs_fileno;
829: vap->va_flags = 0;
1.23 mycroft 830: vap->va_size = 0;
1.1 cgd 831: vap->va_blocksize = DEV_BSIZE;
1.121 kardel 832: /* Make all times be current TOD, except for the "boottime" node. */
1.107 perry 833: if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 &&
1.92 dan 834: !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
835: TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
836: } else {
1.121 kardel 837: getnanotime(&vap->va_ctime);
1.92 dan 838: }
1.81 lukem 839: vap->va_atime = vap->va_mtime = vap->va_ctime;
1.1 cgd 840: vap->va_gen = 0;
841: vap->va_flags = 0;
842: vap->va_rdev = 0;
843: vap->va_bytes = 0;
844:
1.90 itojun 845: switch (kfs->kfs_type) {
1.98 darcy 846: case KFSkern:
1.102 cl 847: vap->va_nlink = nkern_dirs;
1.90 itojun 848: vap->va_bytes = vap->va_size = DEV_BSIZE;
849: break;
850:
1.98 darcy 851: case KFSroot:
1.90 itojun 852: vap->va_nlink = 1;
853: vap->va_bytes = vap->va_size = DEV_BSIZE;
854: break;
855:
1.102 cl 856: case KFSsubdir:
857: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
858: vap->va_nlink = ks->ks_dirs;
859: vap->va_bytes = vap->va_size = DEV_BSIZE;
860: break;
861:
1.98 darcy 862: case KFSnull:
863: case KFStime:
864: case KFSint:
865: case KFSstring:
866: case KFShostname:
867: case KFSavenrun:
868: case KFSdevice:
869: case KFSmsgbuf:
1.90 itojun 870: #ifdef IPSEC
1.98 darcy 871: case KFSipsecsa:
872: case KFSipsecsp:
1.1 cgd 873: #endif
874: vap->va_nlink = 1;
1.84 jdolecek 875: total = 0;
876: do {
1.109 christos 877: bf = strbuf;
878: error = kernfs_xread(kfs, total, &bf,
1.90 itojun 879: sizeof(strbuf), &nread);
1.84 jdolecek 880: total += nread;
881: } while (error == 0 && nread != 0);
1.90 itojun 882: vap->va_bytes = vap->va_size = total;
883: break;
884:
885: #ifdef IPSEC
1.98 darcy 886: case KFSipsecsadir:
887: case KFSipsecspdir:
1.90 itojun 888: vap->va_nlink = 2;
889: vap->va_bytes = vap->va_size = DEV_BSIZE;
890: break;
891: #endif
892:
893: default:
1.102 cl 894: error = kernfs_try_fileop(kfs->kfs_type,
895: KERNFS_FILEOP_GETATTR, v, EINVAL);
1.90 itojun 896: break;
1.1 cgd 897: }
898:
899: return (error);
900: }
901:
1.41 christos 902: /*ARGSUSED*/
903: int
1.128 christos 904: kernfs_setattr(void *v)
1.1 cgd 905: {
1.90 itojun 906:
1.1 cgd 907: /*
1.17 cgd 908: * Silently ignore attribute changes.
909: * This allows for open with truncate to have no
910: * effect until some data is written. I want to
911: * do it this way because all writes are atomic.
1.1 cgd 912: */
1.17 cgd 913: return (0);
1.1 cgd 914: }
915:
1.28 mycroft 916: int
1.123 bouyer 917: kernfs_default_xread(v)
1.41 christos 918: void *v;
919: {
1.23 mycroft 920: struct vop_read_args /* {
921: struct vnode *a_vp;
922: struct uio *a_uio;
923: int a_ioflag;
1.120 elad 924: kauth_cred_t a_cred;
1.41 christos 925: } */ *ap = v;
1.23 mycroft 926: struct uio *uio = ap->a_uio;
1.90 itojun 927: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.109 christos 928: char strbuf[KSTRING], *bf;
1.114 christos 929: int off;
1.82 jdolecek 930: size_t len;
1.28 mycroft 931: int error;
1.23 mycroft 932:
1.90 itojun 933: if (ap->a_vp->v_type == VDIR)
1.23 mycroft 934: return (EOPNOTSUPP);
935:
1.114 christos 936: off = (int)uio->uio_offset;
1.112 christos 937: /* Don't allow negative offsets */
1.114 christos 938: if (off < 0)
1.112 christos 939: return EINVAL;
940:
1.109 christos 941: bf = strbuf;
942: if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
943: error = uiomove(bf, len, uio);
1.82 jdolecek 944: return (error);
1.1 cgd 945: }
946:
1.123 bouyer 947: int
948: kernfs_read(v)
949: void *v;
950: {
951: struct vop_read_args /* {
952: struct vnode *a_vp;
953: struct uio *a_uio;
954: int a_ioflag;
955: struct ucred *a_cred;
956: } */ *ap = v;
957: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
958:
1.124 bouyer 959: if (kfs->kfs_type < KFSlasttype) {
960: /* use default function */
961: return kernfs_default_xread(v);
962: }
963: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v,
964: EOPNOTSUPP);
1.123 bouyer 965: }
966:
1.102 cl 967: static int
968: kernfs_default_xwrite(v)
1.41 christos 969: void *v;
970: {
1.23 mycroft 971: struct vop_write_args /* {
972: struct vnode *a_vp;
973: struct uio *a_uio;
974: int a_ioflag;
1.120 elad 975: kauth_cred_t a_cred;
1.41 christos 976: } */ *ap = v;
1.90 itojun 977: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.23 mycroft 978: struct uio *uio = ap->a_uio;
1.127 jmmv 979: int error;
980: size_t xlen;
1.1 cgd 981: char strbuf[KSTRING];
1.23 mycroft 982:
1.1 cgd 983: if (uio->uio_offset != 0)
984: return (EINVAL);
985:
986: xlen = min(uio->uio_resid, KSTRING-1);
1.41 christos 987: if ((error = uiomove(strbuf, xlen, uio)) != 0)
1.1 cgd 988: return (error);
989:
990: if (uio->uio_resid != 0)
991: return (EIO);
992:
993: strbuf[xlen] = '\0';
1.17 cgd 994: xlen = strlen(strbuf);
1.90 itojun 995: return (kernfs_xwrite(kfs, strbuf, xlen));
1.1 cgd 996: }
997:
1.102 cl 998: int
999: kernfs_write(v)
1000: void *v;
1001: {
1002: struct vop_write_args /* {
1003: struct vnode *a_vp;
1004: struct uio *a_uio;
1005: int a_ioflag;
1.120 elad 1006: kauth_cred_t a_cred;
1.102 cl 1007: } */ *ap = v;
1008: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1009:
1.124 bouyer 1010: if (kfs->kfs_type < KFSlasttype) {
1011: /* use default function */
1012: return kernfs_default_xwrite(v);
1013: }
1014: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v,
1015: EOPNOTSUPP);
1.102 cl 1016: }
1017:
1018: int
1019: kernfs_ioctl(v)
1020: void *v;
1021: {
1022: struct vop_ioctl_args /* {
1023: const struct vnodeop_desc *a_desc;
1024: struct vnode *a_vp;
1025: u_long a_command;
1026: void *a_data;
1027: int a_fflag;
1.120 elad 1028: kauth_cred_t a_cred;
1.115 christos 1029: struct lwp *a_l;
1.102 cl 1030: } */ *ap = v;
1031: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1032:
1033: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
1034: EPASSTHROUGH);
1035: }
1036:
1.101 cl 1037: static int
1038: kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
1039: u_int32_t value, struct vop_readdir_args *ap)
1040: {
1041: struct kernfs_node *kfs;
1042: struct vnode *vp;
1043: int error;
1044:
1045: if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
1046: value)) != 0)
1047: return error;
1048: if (kt->kt_tag == KFSdevice) {
1049: struct vattr va;
1.117 yamt 1050:
1051: error = VOP_GETATTR(vp, &va, ap->a_cred, curlwp);
1052: if (error != 0) {
1053: return error;
1054: }
1.101 cl 1055: d->d_fileno = va.va_fileid;
1056: } else {
1057: kfs = VTOKERN(vp);
1058: d->d_fileno = kfs->kfs_fileno;
1059: }
1060: vput(vp);
1061: return 0;
1062: }
1063:
1064: static int
1065: kernfs_setdirentfileno(struct dirent *d, off_t entry,
1066: struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
1067: const struct kern_target *kt, struct vop_readdir_args *ap)
1068: {
1069: const struct kern_target *ikt;
1070: int error;
1071:
1072: switch (entry) {
1073: case 0:
1074: d->d_fileno = thisdir_kfs->kfs_fileno;
1075: return 0;
1076: case 1:
1077: ikt = parent_kt;
1078: break;
1079: default:
1080: ikt = kt;
1081: break;
1082: }
1083: if (ikt != thisdir_kfs->kfs_kt) {
1084: if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
1085: return error;
1086: } else
1087: d->d_fileno = thisdir_kfs->kfs_fileno;
1088: return 0;
1089: }
1090:
1.41 christos 1091: int
1092: kernfs_readdir(v)
1093: void *v;
1094: {
1.23 mycroft 1095: struct vop_readdir_args /* {
1096: struct vnode *a_vp;
1097: struct uio *a_uio;
1.120 elad 1098: kauth_cred_t a_cred;
1.26 mycroft 1099: int *a_eofflag;
1.57 fvdl 1100: off_t **a_cookies;
1101: int a_*ncookies;
1.41 christos 1102: } */ *ap = v;
1.23 mycroft 1103: struct uio *uio = ap->a_uio;
1.37 mycroft 1104: struct dirent d;
1.90 itojun 1105: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.75 jdolecek 1106: const struct kern_target *kt;
1.102 cl 1107: const struct dyn_kern_target *dkt = NULL;
1108: const struct kernfs_subdir *ks;
1109: off_t i, j;
1.1 cgd 1110: int error;
1.57 fvdl 1111: off_t *cookies = NULL;
1.90 itojun 1112: int ncookies = 0, n;
1113: #ifdef IPSEC
1114: struct secasvar *sav, *sav2;
1115: struct secpolicy *sp;
1116: #endif
1.23 mycroft 1117:
1.37 mycroft 1118: if (uio->uio_resid < UIO_MX)
1119: return (EINVAL);
1.38 mycroft 1120: if (uio->uio_offset < 0)
1.37 mycroft 1121: return (EINVAL);
1.26 mycroft 1122:
1.1 cgd 1123: error = 0;
1.38 mycroft 1124: i = uio->uio_offset;
1.90 itojun 1125: memset(&d, 0, sizeof(d));
1126: d.d_reclen = UIO_MX;
1127: ncookies = uio->uio_resid / UIO_MX;
1128:
1129: switch (kfs->kfs_type) {
1.98 darcy 1130: case KFSkern:
1.90 itojun 1131: if (i >= nkern_targets)
1132: return (0);
1.66 sommerfe 1133:
1.90 itojun 1134: if (ap->a_ncookies) {
1135: ncookies = min(ncookies, (nkern_targets - i));
1136: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1137: M_WAITOK);
1138: *ap->a_cookies = cookies;
1139: }
1140:
1141: n = 0;
1142: for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1.102 cl 1143: if (i < static_nkern_targets)
1144: kt = &kern_targets[i];
1145: else {
1146: if (dkt == NULL) {
1147: dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
1148: for (j = static_nkern_targets; j < i &&
1149: dkt != NULL; j++)
1150: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1151: if (j != i)
1152: break;
1153: } else {
1154: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1155: }
1.119 christos 1156: if (dkt == NULL)
1157: break;
1.102 cl 1158: kt = &dkt->dkt_kt;
1159: }
1.98 darcy 1160: if (kt->kt_tag == KFSdevice) {
1.94 itojun 1161: dev_t *dp = kt->kt_data;
1162: struct vnode *fvp;
1163:
1164: if (*dp == NODEV ||
1165: !vfinddev(*dp, kt->kt_vtype, &fvp))
1166: continue;
1167: }
1.90 itojun 1168: d.d_namlen = kt->kt_namlen;
1.101 cl 1169: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1170: &kern_targets[0], kt, ap)) != 0)
1171: break;
1.90 itojun 1172: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1173: d.d_type = kt->kt_type;
1.99 jrf 1174: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1175: break;
1176: if (cookies)
1177: *cookies++ = i + 1;
1178: n++;
1179: }
1180: ncookies = n;
1181: break;
1182:
1.98 darcy 1183: case KFSroot:
1.90 itojun 1184: if (i >= 2)
1185: return 0;
1186:
1187: if (ap->a_ncookies) {
1188: ncookies = min(ncookies, (2 - i));
1189: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1190: M_WAITOK);
1191: *ap->a_cookies = cookies;
1192: }
1193:
1194: n = 0;
1195: for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1196: kt = &kern_targets[i];
1197: d.d_namlen = kt->kt_namlen;
1198: d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
1199: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1200: d.d_type = kt->kt_type;
1.99 jrf 1201: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1202: break;
1203: if (cookies)
1204: *cookies++ = i + 1;
1205: n++;
1206: }
1207: ncookies = n;
1208: break;
1209:
1.102 cl 1210: case KFSsubdir:
1211: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
1212: if (i >= ks->ks_nentries)
1213: return (0);
1214:
1215: if (ap->a_ncookies) {
1216: ncookies = min(ncookies, (ks->ks_nentries - i));
1217: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1218: M_WAITOK);
1219: *ap->a_cookies = cookies;
1220: }
1221:
1222: dkt = SIMPLEQ_FIRST(&ks->ks_entries);
1223: for (j = 0; j < i && dkt != NULL; j++)
1224: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1225: n = 0;
1226: for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
1227: if (i < 2)
1228: kt = &subdir_targets[i];
1229: else {
1230: /* check if ks_nentries lied to us */
1231: if (dkt == NULL)
1232: break;
1233: kt = &dkt->dkt_kt;
1234: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1235: }
1236: if (kt->kt_tag == KFSdevice) {
1237: dev_t *dp = kt->kt_data;
1238: struct vnode *fvp;
1239:
1240: if (*dp == NODEV ||
1241: !vfinddev(*dp, kt->kt_vtype, &fvp))
1242: continue;
1243: }
1244: d.d_namlen = kt->kt_namlen;
1245: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1246: ks->ks_parent, kt, ap)) != 0)
1247: break;
1248: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1249: d.d_type = kt->kt_type;
1.103 jrf 1250: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.102 cl 1251: break;
1252: if (cookies)
1253: *cookies++ = i + 1;
1254: n++;
1255: }
1256: ncookies = n;
1257: break;
1258:
1.90 itojun 1259: #ifdef IPSEC
1.98 darcy 1260: case KFSipsecsadir:
1.90 itojun 1261: /* count SA in the system */
1262: n = 0;
1263: TAILQ_FOREACH(sav, &satailq, tailq) {
1264: for (sav2 = TAILQ_FIRST(&satailq);
1265: sav2 != sav;
1266: sav2 = TAILQ_NEXT(sav2, tailq)) {
1267: if (sav->spi == sav2->spi) {
1268: /* multiple SA with same SPI */
1269: break;
1270: }
1271: }
1272: if (sav == sav2 || sav->spi != sav2->spi)
1273: n++;
1274: }
1.37 mycroft 1275:
1.90 itojun 1276: if (i >= nipsecsa_targets + n)
1277: return (0);
1.57 fvdl 1278:
1.90 itojun 1279: if (ap->a_ncookies) {
1280: ncookies = min(ncookies, (n - i));
1281: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1282: M_WAITOK);
1283: *ap->a_cookies = cookies;
1284: }
1.26 mycroft 1285:
1.90 itojun 1286: n = 0;
1287: for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
1288: kt = &ipsecsa_targets[i];
1289: d.d_namlen = kt->kt_namlen;
1.101 cl 1290: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1291: &kern_targets[0], kt, ap)) != 0)
1292: break;
1.90 itojun 1293: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1294: d.d_type = kt->kt_type;
1.99 jrf 1295: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1296: break;
1297: if (cookies)
1298: *cookies++ = i + 1;
1299: n++;
1300: }
1301: if (error) {
1302: ncookies = n;
1303: break;
1304: }
1.26 mycroft 1305:
1.90 itojun 1306: TAILQ_FOREACH(sav, &satailq, tailq) {
1307: for (sav2 = TAILQ_FIRST(&satailq);
1308: sav2 != sav;
1309: sav2 = TAILQ_NEXT(sav2, tailq)) {
1310: if (sav->spi == sav2->spi) {
1311: /* multiple SA with same SPI */
1312: break;
1313: }
1314: }
1315: if (sav != sav2 && sav->spi == sav2->spi)
1.23 mycroft 1316: continue;
1.90 itojun 1317: if (uio->uio_resid < UIO_MX)
1318: break;
1.101 cl 1319: if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
1320: sav->spi, ap)) != 0)
1321: break;
1.90 itojun 1322: d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1323: "%u", ntohl(sav->spi));
1324: d.d_type = DT_REG;
1.99 jrf 1325: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1326: break;
1327: if (cookies)
1328: *cookies++ = i + 1;
1329: n++;
1330: i++;
1.23 mycroft 1331: }
1.90 itojun 1332: ncookies = n;
1333: break;
1334:
1.98 darcy 1335: case KFSipsecspdir:
1.90 itojun 1336: /* count SP in the system */
1337: n = 0;
1338: TAILQ_FOREACH(sp, &sptailq, tailq)
1339: n++;
1.26 mycroft 1340:
1.102 cl 1341: if (i >= nipsecsp_targets + n)
1.90 itojun 1342: return (0);
1343:
1344: if (ap->a_ncookies) {
1345: ncookies = min(ncookies, (n - i));
1346: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1347: M_WAITOK);
1348: *ap->a_cookies = cookies;
1349: }
1.26 mycroft 1350:
1.90 itojun 1351: n = 0;
1352: for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
1353: kt = &ipsecsp_targets[i];
1354: d.d_namlen = kt->kt_namlen;
1.101 cl 1355: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1356: &kern_targets[0], kt, ap)) != 0)
1357: break;
1.90 itojun 1358: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1359: d.d_type = kt->kt_type;
1.99 jrf 1360: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1361: break;
1362: if (cookies)
1363: *cookies++ = i + 1;
1364: n++;
1365: }
1366: if (error) {
1367: ncookies = n;
1.1 cgd 1368: break;
1.57 fvdl 1369: }
1.90 itojun 1370:
1371: TAILQ_FOREACH(sp, &sptailq, tailq) {
1372: if (uio->uio_resid < UIO_MX)
1373: break;
1.101 cl 1374: if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
1375: sp->id, ap)) != 0)
1376: break;
1.90 itojun 1377: d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1378: "%u", sp->id);
1379: d.d_type = DT_REG;
1.99 jrf 1380: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1381: break;
1382: if (cookies)
1383: *cookies++ = i + 1;
1384: n++;
1385: i++;
1386: }
1387: ncookies = n;
1388: break;
1389: #endif
1390:
1391: default:
1392: error = ENOTDIR;
1393: break;
1.57 fvdl 1394: }
1395:
1396: if (ap->a_ncookies) {
1397: if (error) {
1.90 itojun 1398: if (cookies)
1399: free(*ap->a_cookies, M_TEMP);
1.57 fvdl 1400: *ap->a_ncookies = 0;
1401: *ap->a_cookies = NULL;
1402: } else
1403: *ap->a_ncookies = ncookies;
1.1 cgd 1404: }
1405:
1.38 mycroft 1406: uio->uio_offset = i;
1.1 cgd 1407: return (error);
1408: }
1409:
1.41 christos 1410: int
1411: kernfs_inactive(v)
1412: void *v;
1413: {
1.23 mycroft 1414: struct vop_inactive_args /* {
1415: struct vnode *a_vp;
1.115 christos 1416: struct lwp *a_l;
1.41 christos 1417: } */ *ap = v;
1.23 mycroft 1418: struct vnode *vp = ap->a_vp;
1.90 itojun 1419: const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1420: #ifdef IPSEC
1421: struct mbuf *m;
1422: struct secpolicy *sp;
1423: #endif
1.23 mycroft 1424:
1.90 itojun 1425: VOP_UNLOCK(vp, 0);
1426: switch (kfs->kfs_type) {
1427: #ifdef IPSEC
1.98 darcy 1428: case KFSipsecsa:
1.90 itojun 1429: m = key_setdumpsa_spi(htonl(kfs->kfs_value));
1430: if (m)
1431: m_freem(m);
1.91 itojun 1432: else
1.90 itojun 1433: vgone(vp);
1434: break;
1.98 darcy 1435: case KFSipsecsp:
1.90 itojun 1436: sp = key_getspbyid(kfs->kfs_value);
1437: if (sp)
1438: key_freesp(sp);
1439: else {
1440: /* should never happen as we hold a refcnt */
1441: vgone(vp);
1442: }
1443: break;
1.23 mycroft 1444: #endif
1.90 itojun 1445: default:
1446: break;
1447: }
1.23 mycroft 1448: return (0);
1449: }
1450:
1.41 christos 1451: int
1452: kernfs_reclaim(v)
1453: void *v;
1454: {
1.23 mycroft 1455: struct vop_reclaim_args /* {
1456: struct vnode *a_vp;
1.41 christos 1457: } */ *ap = v;
1.23 mycroft 1458:
1.90 itojun 1459: return (kernfs_freevp(ap->a_vp));
1.1 cgd 1460: }
1461:
1462: /*
1.23 mycroft 1463: * Return POSIX pathconf information applicable to special devices.
1464: */
1.41 christos 1465: int
1466: kernfs_pathconf(v)
1467: void *v;
1468: {
1.23 mycroft 1469: struct vop_pathconf_args /* {
1470: struct vnode *a_vp;
1471: int a_name;
1.29 cgd 1472: register_t *a_retval;
1.41 christos 1473: } */ *ap = v;
1.23 mycroft 1474:
1475: switch (ap->a_name) {
1476: case _PC_LINK_MAX:
1477: *ap->a_retval = LINK_MAX;
1478: return (0);
1479: case _PC_MAX_CANON:
1480: *ap->a_retval = MAX_CANON;
1481: return (0);
1482: case _PC_MAX_INPUT:
1483: *ap->a_retval = MAX_INPUT;
1484: return (0);
1485: case _PC_PIPE_BUF:
1486: *ap->a_retval = PIPE_BUF;
1487: return (0);
1488: case _PC_CHOWN_RESTRICTED:
1489: *ap->a_retval = 1;
1490: return (0);
1491: case _PC_VDISABLE:
1492: *ap->a_retval = _POSIX_VDISABLE;
1.59 kleink 1493: return (0);
1494: case _PC_SYNC_IO:
1495: *ap->a_retval = 1;
1.23 mycroft 1496: return (0);
1497: default:
1498: return (EINVAL);
1499: }
1500: /* NOTREACHED */
1501: }
1502:
1503: /*
1504: * Print out the contents of a /dev/fd vnode.
1.1 cgd 1505: */
1506: /* ARGSUSED */
1.41 christos 1507: int
1.128 christos 1508: kernfs_print(void *v)
1.23 mycroft 1509: {
1510:
1.47 christos 1511: printf("tag VT_KERNFS, kernfs vnode\n");
1.23 mycroft 1512: return (0);
1513: }
1514:
1.40 mycroft 1515: int
1.107 perry 1516: kernfs_link(v)
1.41 christos 1517: void *v;
1518: {
1.40 mycroft 1519: struct vop_link_args /* {
1520: struct vnode *a_dvp;
1.107 perry 1521: struct vnode *a_vp;
1.40 mycroft 1522: struct componentname *a_cnp;
1.41 christos 1523: } */ *ap = v;
1.107 perry 1524:
1.40 mycroft 1525: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1526: vput(ap->a_dvp);
1527: return (EROFS);
1528: }
1529:
1530: int
1.41 christos 1531: kernfs_symlink(v)
1532: void *v;
1533: {
1.40 mycroft 1534: struct vop_symlink_args /* {
1535: struct vnode *a_dvp;
1536: struct vnode **a_vpp;
1537: struct componentname *a_cnp;
1538: struct vattr *a_vap;
1539: char *a_target;
1.41 christos 1540: } */ *ap = v;
1.107 perry 1541:
1.40 mycroft 1542: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1543: vput(ap->a_dvp);
1544: return (EROFS);
1.1 cgd 1545: }
CVSweb <webmaster@jp.NetBSD.org>