Annotation of src/sys/miscfs/kernfs/kernfs_vnops.c, Revision 1.125.6.1
1.125.6.1! yamt 1: /* $NetBSD: kernfs_vnops.c,v 1.125 2006/06/23 20:54:21 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.125.6.1! yamt 42: __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.125 2006/06/23 20:54:21 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;
457: int xlen = hostnamelen;
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.64 wrstuden 588: int error, i, wantpunlock;
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;
1.64 wrstuden 595: cnp->cn_flags &= ~PDIRUNLOCK;
1.35 mycroft 596:
597: if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
598: return (EROFS);
599:
1.23 mycroft 600: if (cnp->cn_namelen == 1 && *pname == '.') {
601: *vpp = dvp;
1.1 cgd 602: VREF(dvp);
603: return (0);
604: }
1.13 cgd 605:
1.90 itojun 606: wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
607: kfs = VTOKERN(dvp);
608: switch (kfs->kfs_type) {
1.98 darcy 609: case KFSkern:
1.90 itojun 610: /*
611: * Shouldn't get here with .. in the root node.
612: */
613: if (cnp->cn_flags & ISDOTDOT)
614: return (EIO);
1.64 wrstuden 615:
1.102 cl 616: for (i = 0; i < static_nkern_targets; i++) {
1.90 itojun 617: kt = &kern_targets[i];
618: if (cnp->cn_namelen == kt->kt_namlen &&
619: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
620: goto found;
621: }
1.102 cl 622: SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
623: if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
624: memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
625: kt = &dkt->dkt_kt;
626: goto found;
627: }
628: }
1.90 itojun 629: break;
1.25 mycroft 630:
1.90 itojun 631: found:
632: error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
633: if ((error == 0) && wantpunlock) {
634: VOP_UNLOCK(dvp, 0);
635: cnp->cn_flags |= PDIRUNLOCK;
636: }
637: return (error);
1.64 wrstuden 638:
1.102 cl 639: case KFSsubdir:
640: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
641: if (cnp->cn_flags & ISDOTDOT) {
642: kt = ks->ks_parent;
643: goto found;
644: }
645:
646: SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
647: if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
648: memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
649: kt = &dkt->dkt_kt;
650: goto found;
651: }
652: }
653: break;
654:
1.90 itojun 655: #ifdef IPSEC
1.98 darcy 656: case KFSipsecsadir:
1.100 cl 657: if (cnp->cn_flags & ISDOTDOT) {
658: kt = &kern_targets[0];
659: goto found;
660: }
661:
662: for (i = 2; i < nipsecsa_targets; i++) {
1.90 itojun 663: kt = &ipsecsa_targets[i];
664: if (cnp->cn_namelen == kt->kt_namlen &&
1.100 cl 665: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
666: goto found;
1.90 itojun 667: }
1.1 cgd 668:
1.90 itojun 669: ep = NULL;
670: id = strtoul(pname, &ep, 10);
671: if (!ep || *ep || ep == pname)
672: break;
1.1 cgd 673:
1.101 cl 674: error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
1.90 itojun 675: if ((error == 0) && wantpunlock) {
676: VOP_UNLOCK(dvp, 0);
677: cnp->cn_flags |= PDIRUNLOCK;
678: }
679: return (error);
1.23 mycroft 680:
1.98 darcy 681: case KFSipsecspdir:
1.100 cl 682: if (cnp->cn_flags & ISDOTDOT) {
683: kt = &kern_targets[0];
684: goto found;
685: }
686:
687: for (i = 2; i < nipsecsp_targets; i++) {
1.90 itojun 688: kt = &ipsecsp_targets[i];
689: if (cnp->cn_namelen == kt->kt_namlen &&
1.100 cl 690: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
691: goto found;
1.57 fvdl 692: }
1.90 itojun 693:
694: ep = NULL;
695: id = strtoul(pname, &ep, 10);
696: if (!ep || *ep || ep == pname)
697: break;
698:
1.101 cl 699: error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
1.90 itojun 700: if ((error == 0) && wantpunlock) {
1.64 wrstuden 701: VOP_UNLOCK(dvp, 0);
702: cnp->cn_flags |= PDIRUNLOCK;
703: }
1.90 itojun 704: return (error);
705: #endif
706:
707: default:
708: return (ENOTDIR);
709: }
710:
711: return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
712: }
713:
714: int
715: kernfs_open(v)
716: void *v;
717: {
718: struct vop_open_args /* {
719: struct vnode *a_vp;
720: int a_mode;
1.120 elad 721: kauth_cred_t a_cred;
1.115 christos 722: struct lwp *a_l;
1.90 itojun 723: } */ *ap = v;
724: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
725: #ifdef IPSEC
726: struct mbuf *m;
727: struct secpolicy *sp;
728: #endif
729:
730: switch (kfs->kfs_type) {
731: #ifdef IPSEC
1.98 darcy 732: case KFSipsecsa:
1.90 itojun 733: m = key_setdumpsa_spi(htonl(kfs->kfs_value));
734: if (m) {
735: m_freem(m);
736: return (0);
737: } else
738: return (ENOENT);
739:
1.98 darcy 740: case KFSipsecsp:
1.90 itojun 741: sp = key_getspbyid(kfs->kfs_value);
742: if (sp) {
743: kfs->kfs_v = sp;
744: return (0);
745: } else
746: return (ENOENT);
747: #endif
748:
749: default:
1.102 cl 750: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
751: v, 0);
1.23 mycroft 752: }
1.90 itojun 753: }
1.1 cgd 754:
1.90 itojun 755: int
756: kernfs_close(v)
757: void *v;
758: {
759: struct vop_close_args /* {
760: struct vnode *a_vp;
761: int a_fflag;
1.120 elad 762: kauth_cred_t a_cred;
1.115 christos 763: struct lwp *a_l;
1.90 itojun 764: } */ *ap = v;
765: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
766:
767: switch (kfs->kfs_type) {
768: #ifdef IPSEC
1.98 darcy 769: case KFSipsecsp:
1.90 itojun 770: key_freesp((struct secpolicy *)kfs->kfs_v);
771: break;
1.1 cgd 772: #endif
1.90 itojun 773:
774: default:
1.102 cl 775: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
776: v, 0);
1.57 fvdl 777: }
1.23 mycroft 778:
1.1 cgd 779: return (0);
780: }
781:
1.28 mycroft 782: int
1.41 christos 783: kernfs_access(v)
784: void *v;
785: {
1.23 mycroft 786: struct vop_access_args /* {
787: struct vnode *a_vp;
1.34 mycroft 788: int a_mode;
1.120 elad 789: kauth_cred_t a_cred;
1.115 christos 790: struct lwp *a_l;
1.41 christos 791: } */ *ap = v;
1.90 itojun 792: struct vattr va;
793: int error;
1.17 cgd 794:
1.115 christos 795: if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_l)) != 0)
1.90 itojun 796: return (error);
1.49 mycroft 797:
1.90 itojun 798: return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
799: ap->a_mode, ap->a_cred));
1.23 mycroft 800: }
801:
1.102 cl 802: static int
803: kernfs_default_fileop_getattr(v)
804: void *v;
805: {
806: struct vop_getattr_args /* {
807: struct vnode *a_vp;
808: struct vattr *a_vap;
1.120 elad 809: kauth_cred_t a_cred;
1.115 christos 810: struct lwp *a_l;
1.102 cl 811: } */ *ap = v;
812: struct vattr *vap = ap->a_vap;
813:
814: vap->va_nlink = 1;
815: vap->va_bytes = vap->va_size = 0;
816:
817: return 0;
818: }
819:
1.41 christos 820: int
821: kernfs_getattr(v)
822: void *v;
823: {
1.23 mycroft 824: struct vop_getattr_args /* {
825: struct vnode *a_vp;
826: struct vattr *a_vap;
1.120 elad 827: kauth_cred_t a_cred;
1.115 christos 828: struct lwp *a_l;
1.41 christos 829: } */ *ap = v;
1.90 itojun 830: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.102 cl 831: struct kernfs_subdir *ks;
1.23 mycroft 832: struct vattr *vap = ap->a_vap;
1.1 cgd 833: int error = 0;
1.109 christos 834: char strbuf[KSTRING], *bf;
1.90 itojun 835: size_t nread, total;
1.1 cgd 836:
1.90 itojun 837: VATTR_NULL(vap);
838: vap->va_type = ap->a_vp->v_type;
1.17 cgd 839: vap->va_uid = 0;
840: vap->va_gid = 0;
1.90 itojun 841: vap->va_mode = kfs->kfs_mode;
842: vap->va_fileid = kfs->kfs_fileno;
843: vap->va_flags = 0;
1.23 mycroft 844: vap->va_size = 0;
1.1 cgd 845: vap->va_blocksize = DEV_BSIZE;
1.121 kardel 846: /* Make all times be current TOD, except for the "boottime" node. */
1.107 perry 847: if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 &&
1.92 dan 848: !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
849: TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
850: } else {
1.121 kardel 851: getnanotime(&vap->va_ctime);
1.92 dan 852: }
1.81 lukem 853: vap->va_atime = vap->va_mtime = vap->va_ctime;
1.1 cgd 854: vap->va_gen = 0;
855: vap->va_flags = 0;
856: vap->va_rdev = 0;
857: vap->va_bytes = 0;
858:
1.90 itojun 859: switch (kfs->kfs_type) {
1.98 darcy 860: case KFSkern:
1.102 cl 861: vap->va_nlink = nkern_dirs;
1.90 itojun 862: vap->va_bytes = vap->va_size = DEV_BSIZE;
863: break;
864:
1.98 darcy 865: case KFSroot:
1.90 itojun 866: vap->va_nlink = 1;
867: vap->va_bytes = vap->va_size = DEV_BSIZE;
868: break;
869:
1.102 cl 870: case KFSsubdir:
871: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
872: vap->va_nlink = ks->ks_dirs;
873: vap->va_bytes = vap->va_size = DEV_BSIZE;
874: break;
875:
1.98 darcy 876: case KFSnull:
877: case KFStime:
878: case KFSint:
879: case KFSstring:
880: case KFShostname:
881: case KFSavenrun:
882: case KFSdevice:
883: case KFSmsgbuf:
1.90 itojun 884: #ifdef IPSEC
1.98 darcy 885: case KFSipsecsa:
886: case KFSipsecsp:
1.1 cgd 887: #endif
888: vap->va_nlink = 1;
1.84 jdolecek 889: total = 0;
890: do {
1.109 christos 891: bf = strbuf;
892: error = kernfs_xread(kfs, total, &bf,
1.90 itojun 893: sizeof(strbuf), &nread);
1.84 jdolecek 894: total += nread;
895: } while (error == 0 && nread != 0);
1.90 itojun 896: vap->va_bytes = vap->va_size = total;
897: break;
898:
899: #ifdef IPSEC
1.98 darcy 900: case KFSipsecsadir:
901: case KFSipsecspdir:
1.90 itojun 902: vap->va_nlink = 2;
903: vap->va_bytes = vap->va_size = DEV_BSIZE;
904: break;
905: #endif
906:
907: default:
1.102 cl 908: error = kernfs_try_fileop(kfs->kfs_type,
909: KERNFS_FILEOP_GETATTR, v, EINVAL);
1.90 itojun 910: break;
1.1 cgd 911: }
912:
913: return (error);
914: }
915:
1.41 christos 916: /*ARGSUSED*/
917: int
1.125.6.1! yamt 918: kernfs_setattr(void *v __unused)
1.1 cgd 919: {
1.90 itojun 920:
1.1 cgd 921: /*
1.17 cgd 922: * Silently ignore attribute changes.
923: * This allows for open with truncate to have no
924: * effect until some data is written. I want to
925: * do it this way because all writes are atomic.
1.1 cgd 926: */
1.17 cgd 927: return (0);
1.1 cgd 928: }
929:
1.28 mycroft 930: int
1.123 bouyer 931: kernfs_default_xread(v)
1.41 christos 932: void *v;
933: {
1.23 mycroft 934: struct vop_read_args /* {
935: struct vnode *a_vp;
936: struct uio *a_uio;
937: int a_ioflag;
1.120 elad 938: kauth_cred_t a_cred;
1.41 christos 939: } */ *ap = v;
1.23 mycroft 940: struct uio *uio = ap->a_uio;
1.90 itojun 941: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.109 christos 942: char strbuf[KSTRING], *bf;
1.114 christos 943: int off;
1.82 jdolecek 944: size_t len;
1.28 mycroft 945: int error;
1.23 mycroft 946:
1.90 itojun 947: if (ap->a_vp->v_type == VDIR)
1.23 mycroft 948: return (EOPNOTSUPP);
949:
1.114 christos 950: off = (int)uio->uio_offset;
1.112 christos 951: /* Don't allow negative offsets */
1.114 christos 952: if (off < 0)
1.112 christos 953: return EINVAL;
954:
1.109 christos 955: bf = strbuf;
956: if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
957: error = uiomove(bf, len, uio);
1.82 jdolecek 958: return (error);
1.1 cgd 959: }
960:
1.123 bouyer 961: int
962: kernfs_read(v)
963: void *v;
964: {
965: struct vop_read_args /* {
966: struct vnode *a_vp;
967: struct uio *a_uio;
968: int a_ioflag;
969: struct ucred *a_cred;
970: } */ *ap = v;
971: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
972:
1.124 bouyer 973: if (kfs->kfs_type < KFSlasttype) {
974: /* use default function */
975: return kernfs_default_xread(v);
976: }
977: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v,
978: EOPNOTSUPP);
1.123 bouyer 979: }
980:
1.102 cl 981: static int
982: kernfs_default_xwrite(v)
1.41 christos 983: void *v;
984: {
1.23 mycroft 985: struct vop_write_args /* {
986: struct vnode *a_vp;
987: struct uio *a_uio;
988: int a_ioflag;
1.120 elad 989: kauth_cred_t a_cred;
1.41 christos 990: } */ *ap = v;
1.90 itojun 991: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.23 mycroft 992: struct uio *uio = ap->a_uio;
993: int error, xlen;
1.1 cgd 994: char strbuf[KSTRING];
1.23 mycroft 995:
1.1 cgd 996: if (uio->uio_offset != 0)
997: return (EINVAL);
998:
999: xlen = min(uio->uio_resid, KSTRING-1);
1.41 christos 1000: if ((error = uiomove(strbuf, xlen, uio)) != 0)
1.1 cgd 1001: return (error);
1002:
1003: if (uio->uio_resid != 0)
1004: return (EIO);
1005:
1006: strbuf[xlen] = '\0';
1.17 cgd 1007: xlen = strlen(strbuf);
1.90 itojun 1008: return (kernfs_xwrite(kfs, strbuf, xlen));
1.1 cgd 1009: }
1010:
1.102 cl 1011: int
1012: kernfs_write(v)
1013: void *v;
1014: {
1015: struct vop_write_args /* {
1016: struct vnode *a_vp;
1017: struct uio *a_uio;
1018: int a_ioflag;
1.120 elad 1019: kauth_cred_t a_cred;
1.102 cl 1020: } */ *ap = v;
1021: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1022:
1.124 bouyer 1023: if (kfs->kfs_type < KFSlasttype) {
1024: /* use default function */
1025: return kernfs_default_xwrite(v);
1026: }
1027: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v,
1028: EOPNOTSUPP);
1.102 cl 1029: }
1030:
1031: int
1032: kernfs_ioctl(v)
1033: void *v;
1034: {
1035: struct vop_ioctl_args /* {
1036: const struct vnodeop_desc *a_desc;
1037: struct vnode *a_vp;
1038: u_long a_command;
1039: void *a_data;
1040: int a_fflag;
1.120 elad 1041: kauth_cred_t a_cred;
1.115 christos 1042: struct lwp *a_l;
1.102 cl 1043: } */ *ap = v;
1044: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1045:
1046: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
1047: EPASSTHROUGH);
1048: }
1049:
1.101 cl 1050: static int
1051: kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
1052: u_int32_t value, struct vop_readdir_args *ap)
1053: {
1054: struct kernfs_node *kfs;
1055: struct vnode *vp;
1056: int error;
1057:
1058: if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
1059: value)) != 0)
1060: return error;
1061: if (kt->kt_tag == KFSdevice) {
1062: struct vattr va;
1.117 yamt 1063:
1064: error = VOP_GETATTR(vp, &va, ap->a_cred, curlwp);
1065: if (error != 0) {
1066: return error;
1067: }
1.101 cl 1068: d->d_fileno = va.va_fileid;
1069: } else {
1070: kfs = VTOKERN(vp);
1071: d->d_fileno = kfs->kfs_fileno;
1072: }
1073: vput(vp);
1074: return 0;
1075: }
1076:
1077: static int
1078: kernfs_setdirentfileno(struct dirent *d, off_t entry,
1079: struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
1080: const struct kern_target *kt, struct vop_readdir_args *ap)
1081: {
1082: const struct kern_target *ikt;
1083: int error;
1084:
1085: switch (entry) {
1086: case 0:
1087: d->d_fileno = thisdir_kfs->kfs_fileno;
1088: return 0;
1089: case 1:
1090: ikt = parent_kt;
1091: break;
1092: default:
1093: ikt = kt;
1094: break;
1095: }
1096: if (ikt != thisdir_kfs->kfs_kt) {
1097: if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
1098: return error;
1099: } else
1100: d->d_fileno = thisdir_kfs->kfs_fileno;
1101: return 0;
1102: }
1103:
1.41 christos 1104: int
1105: kernfs_readdir(v)
1106: void *v;
1107: {
1.23 mycroft 1108: struct vop_readdir_args /* {
1109: struct vnode *a_vp;
1110: struct uio *a_uio;
1.120 elad 1111: kauth_cred_t a_cred;
1.26 mycroft 1112: int *a_eofflag;
1.57 fvdl 1113: off_t **a_cookies;
1114: int a_*ncookies;
1.41 christos 1115: } */ *ap = v;
1.23 mycroft 1116: struct uio *uio = ap->a_uio;
1.37 mycroft 1117: struct dirent d;
1.90 itojun 1118: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.75 jdolecek 1119: const struct kern_target *kt;
1.102 cl 1120: const struct dyn_kern_target *dkt = NULL;
1121: const struct kernfs_subdir *ks;
1122: off_t i, j;
1.1 cgd 1123: int error;
1.57 fvdl 1124: off_t *cookies = NULL;
1.90 itojun 1125: int ncookies = 0, n;
1126: #ifdef IPSEC
1127: struct secasvar *sav, *sav2;
1128: struct secpolicy *sp;
1129: #endif
1.23 mycroft 1130:
1.37 mycroft 1131: if (uio->uio_resid < UIO_MX)
1132: return (EINVAL);
1.38 mycroft 1133: if (uio->uio_offset < 0)
1.37 mycroft 1134: return (EINVAL);
1.26 mycroft 1135:
1.1 cgd 1136: error = 0;
1.38 mycroft 1137: i = uio->uio_offset;
1.90 itojun 1138: memset(&d, 0, sizeof(d));
1139: d.d_reclen = UIO_MX;
1140: ncookies = uio->uio_resid / UIO_MX;
1141:
1142: switch (kfs->kfs_type) {
1.98 darcy 1143: case KFSkern:
1.90 itojun 1144: if (i >= nkern_targets)
1145: return (0);
1.66 sommerfe 1146:
1.90 itojun 1147: if (ap->a_ncookies) {
1148: ncookies = min(ncookies, (nkern_targets - i));
1149: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1150: M_WAITOK);
1151: *ap->a_cookies = cookies;
1152: }
1153:
1154: n = 0;
1155: for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1.102 cl 1156: if (i < static_nkern_targets)
1157: kt = &kern_targets[i];
1158: else {
1159: if (dkt == NULL) {
1160: dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
1161: for (j = static_nkern_targets; j < i &&
1162: dkt != NULL; j++)
1163: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1164: if (j != i)
1165: break;
1166: } else {
1167: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1168: }
1.119 christos 1169: if (dkt == NULL)
1170: break;
1.102 cl 1171: kt = &dkt->dkt_kt;
1172: }
1.98 darcy 1173: if (kt->kt_tag == KFSdevice) {
1.94 itojun 1174: dev_t *dp = kt->kt_data;
1175: struct vnode *fvp;
1176:
1177: if (*dp == NODEV ||
1178: !vfinddev(*dp, kt->kt_vtype, &fvp))
1179: continue;
1180: }
1.90 itojun 1181: d.d_namlen = kt->kt_namlen;
1.101 cl 1182: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1183: &kern_targets[0], kt, ap)) != 0)
1184: break;
1.90 itojun 1185: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1186: d.d_type = kt->kt_type;
1.99 jrf 1187: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1188: break;
1189: if (cookies)
1190: *cookies++ = i + 1;
1191: n++;
1192: }
1193: ncookies = n;
1194: break;
1195:
1.98 darcy 1196: case KFSroot:
1.90 itojun 1197: if (i >= 2)
1198: return 0;
1199:
1200: if (ap->a_ncookies) {
1201: ncookies = min(ncookies, (2 - i));
1202: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1203: M_WAITOK);
1204: *ap->a_cookies = cookies;
1205: }
1206:
1207: n = 0;
1208: for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1209: kt = &kern_targets[i];
1210: d.d_namlen = kt->kt_namlen;
1211: d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
1212: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1213: d.d_type = kt->kt_type;
1.99 jrf 1214: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1215: break;
1216: if (cookies)
1217: *cookies++ = i + 1;
1218: n++;
1219: }
1220: ncookies = n;
1221: break;
1222:
1.102 cl 1223: case KFSsubdir:
1224: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
1225: if (i >= ks->ks_nentries)
1226: return (0);
1227:
1228: if (ap->a_ncookies) {
1229: ncookies = min(ncookies, (ks->ks_nentries - i));
1230: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1231: M_WAITOK);
1232: *ap->a_cookies = cookies;
1233: }
1234:
1235: dkt = SIMPLEQ_FIRST(&ks->ks_entries);
1236: for (j = 0; j < i && dkt != NULL; j++)
1237: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1238: n = 0;
1239: for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
1240: if (i < 2)
1241: kt = &subdir_targets[i];
1242: else {
1243: /* check if ks_nentries lied to us */
1244: if (dkt == NULL)
1245: break;
1246: kt = &dkt->dkt_kt;
1247: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1248: }
1249: if (kt->kt_tag == KFSdevice) {
1250: dev_t *dp = kt->kt_data;
1251: struct vnode *fvp;
1252:
1253: if (*dp == NODEV ||
1254: !vfinddev(*dp, kt->kt_vtype, &fvp))
1255: continue;
1256: }
1257: d.d_namlen = kt->kt_namlen;
1258: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1259: ks->ks_parent, kt, ap)) != 0)
1260: break;
1261: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1262: d.d_type = kt->kt_type;
1.103 jrf 1263: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.102 cl 1264: break;
1265: if (cookies)
1266: *cookies++ = i + 1;
1267: n++;
1268: }
1269: ncookies = n;
1270: break;
1271:
1.90 itojun 1272: #ifdef IPSEC
1.98 darcy 1273: case KFSipsecsadir:
1.90 itojun 1274: /* count SA in the system */
1275: n = 0;
1276: TAILQ_FOREACH(sav, &satailq, tailq) {
1277: for (sav2 = TAILQ_FIRST(&satailq);
1278: sav2 != sav;
1279: sav2 = TAILQ_NEXT(sav2, tailq)) {
1280: if (sav->spi == sav2->spi) {
1281: /* multiple SA with same SPI */
1282: break;
1283: }
1284: }
1285: if (sav == sav2 || sav->spi != sav2->spi)
1286: n++;
1287: }
1.37 mycroft 1288:
1.90 itojun 1289: if (i >= nipsecsa_targets + n)
1290: return (0);
1.57 fvdl 1291:
1.90 itojun 1292: if (ap->a_ncookies) {
1293: ncookies = min(ncookies, (n - i));
1294: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1295: M_WAITOK);
1296: *ap->a_cookies = cookies;
1297: }
1.26 mycroft 1298:
1.90 itojun 1299: n = 0;
1300: for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
1301: kt = &ipsecsa_targets[i];
1302: d.d_namlen = kt->kt_namlen;
1.101 cl 1303: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1304: &kern_targets[0], kt, ap)) != 0)
1305: break;
1.90 itojun 1306: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1307: d.d_type = kt->kt_type;
1.99 jrf 1308: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1309: break;
1310: if (cookies)
1311: *cookies++ = i + 1;
1312: n++;
1313: }
1314: if (error) {
1315: ncookies = n;
1316: break;
1317: }
1.26 mycroft 1318:
1.90 itojun 1319: TAILQ_FOREACH(sav, &satailq, tailq) {
1320: for (sav2 = TAILQ_FIRST(&satailq);
1321: sav2 != sav;
1322: sav2 = TAILQ_NEXT(sav2, tailq)) {
1323: if (sav->spi == sav2->spi) {
1324: /* multiple SA with same SPI */
1325: break;
1326: }
1327: }
1328: if (sav != sav2 && sav->spi == sav2->spi)
1.23 mycroft 1329: continue;
1.90 itojun 1330: if (uio->uio_resid < UIO_MX)
1331: break;
1.101 cl 1332: if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
1333: sav->spi, ap)) != 0)
1334: break;
1.90 itojun 1335: d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1336: "%u", ntohl(sav->spi));
1337: d.d_type = DT_REG;
1.99 jrf 1338: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1339: break;
1340: if (cookies)
1341: *cookies++ = i + 1;
1342: n++;
1343: i++;
1.23 mycroft 1344: }
1.90 itojun 1345: ncookies = n;
1346: break;
1347:
1.98 darcy 1348: case KFSipsecspdir:
1.90 itojun 1349: /* count SP in the system */
1350: n = 0;
1351: TAILQ_FOREACH(sp, &sptailq, tailq)
1352: n++;
1.26 mycroft 1353:
1.102 cl 1354: if (i >= nipsecsp_targets + n)
1.90 itojun 1355: return (0);
1356:
1357: if (ap->a_ncookies) {
1358: ncookies = min(ncookies, (n - i));
1359: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1360: M_WAITOK);
1361: *ap->a_cookies = cookies;
1362: }
1.26 mycroft 1363:
1.90 itojun 1364: n = 0;
1365: for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
1366: kt = &ipsecsp_targets[i];
1367: d.d_namlen = kt->kt_namlen;
1.101 cl 1368: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1369: &kern_targets[0], kt, ap)) != 0)
1370: break;
1.90 itojun 1371: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1372: d.d_type = kt->kt_type;
1.99 jrf 1373: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1374: break;
1375: if (cookies)
1376: *cookies++ = i + 1;
1377: n++;
1378: }
1379: if (error) {
1380: ncookies = n;
1.1 cgd 1381: break;
1.57 fvdl 1382: }
1.90 itojun 1383:
1384: TAILQ_FOREACH(sp, &sptailq, tailq) {
1385: if (uio->uio_resid < UIO_MX)
1386: break;
1.101 cl 1387: if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
1388: sp->id, ap)) != 0)
1389: break;
1.90 itojun 1390: d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1391: "%u", sp->id);
1392: d.d_type = DT_REG;
1.99 jrf 1393: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1394: break;
1395: if (cookies)
1396: *cookies++ = i + 1;
1397: n++;
1398: i++;
1399: }
1400: ncookies = n;
1401: break;
1402: #endif
1403:
1404: default:
1405: error = ENOTDIR;
1406: break;
1.57 fvdl 1407: }
1408:
1409: if (ap->a_ncookies) {
1410: if (error) {
1.90 itojun 1411: if (cookies)
1412: free(*ap->a_cookies, M_TEMP);
1.57 fvdl 1413: *ap->a_ncookies = 0;
1414: *ap->a_cookies = NULL;
1415: } else
1416: *ap->a_ncookies = ncookies;
1.1 cgd 1417: }
1418:
1.38 mycroft 1419: uio->uio_offset = i;
1.1 cgd 1420: return (error);
1421: }
1422:
1.41 christos 1423: int
1424: kernfs_inactive(v)
1425: void *v;
1426: {
1.23 mycroft 1427: struct vop_inactive_args /* {
1428: struct vnode *a_vp;
1.115 christos 1429: struct lwp *a_l;
1.41 christos 1430: } */ *ap = v;
1.23 mycroft 1431: struct vnode *vp = ap->a_vp;
1.90 itojun 1432: const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1433: #ifdef IPSEC
1434: struct mbuf *m;
1435: struct secpolicy *sp;
1436: #endif
1.23 mycroft 1437:
1.90 itojun 1438: VOP_UNLOCK(vp, 0);
1439: switch (kfs->kfs_type) {
1440: #ifdef IPSEC
1.98 darcy 1441: case KFSipsecsa:
1.90 itojun 1442: m = key_setdumpsa_spi(htonl(kfs->kfs_value));
1443: if (m)
1444: m_freem(m);
1.91 itojun 1445: else
1.90 itojun 1446: vgone(vp);
1447: break;
1.98 darcy 1448: case KFSipsecsp:
1.90 itojun 1449: sp = key_getspbyid(kfs->kfs_value);
1450: if (sp)
1451: key_freesp(sp);
1452: else {
1453: /* should never happen as we hold a refcnt */
1454: vgone(vp);
1455: }
1456: break;
1.23 mycroft 1457: #endif
1.90 itojun 1458: default:
1459: break;
1460: }
1.23 mycroft 1461: return (0);
1462: }
1463:
1.41 christos 1464: int
1465: kernfs_reclaim(v)
1466: void *v;
1467: {
1.23 mycroft 1468: struct vop_reclaim_args /* {
1469: struct vnode *a_vp;
1.41 christos 1470: } */ *ap = v;
1.23 mycroft 1471:
1.90 itojun 1472: return (kernfs_freevp(ap->a_vp));
1.1 cgd 1473: }
1474:
1475: /*
1.23 mycroft 1476: * Return POSIX pathconf information applicable to special devices.
1477: */
1.41 christos 1478: int
1479: kernfs_pathconf(v)
1480: void *v;
1481: {
1.23 mycroft 1482: struct vop_pathconf_args /* {
1483: struct vnode *a_vp;
1484: int a_name;
1.29 cgd 1485: register_t *a_retval;
1.41 christos 1486: } */ *ap = v;
1.23 mycroft 1487:
1488: switch (ap->a_name) {
1489: case _PC_LINK_MAX:
1490: *ap->a_retval = LINK_MAX;
1491: return (0);
1492: case _PC_MAX_CANON:
1493: *ap->a_retval = MAX_CANON;
1494: return (0);
1495: case _PC_MAX_INPUT:
1496: *ap->a_retval = MAX_INPUT;
1497: return (0);
1498: case _PC_PIPE_BUF:
1499: *ap->a_retval = PIPE_BUF;
1500: return (0);
1501: case _PC_CHOWN_RESTRICTED:
1502: *ap->a_retval = 1;
1503: return (0);
1504: case _PC_VDISABLE:
1505: *ap->a_retval = _POSIX_VDISABLE;
1.59 kleink 1506: return (0);
1507: case _PC_SYNC_IO:
1508: *ap->a_retval = 1;
1.23 mycroft 1509: return (0);
1510: default:
1511: return (EINVAL);
1512: }
1513: /* NOTREACHED */
1514: }
1515:
1516: /*
1517: * Print out the contents of a /dev/fd vnode.
1.1 cgd 1518: */
1519: /* ARGSUSED */
1.41 christos 1520: int
1.125.6.1! yamt 1521: kernfs_print(void *v __unused)
1.23 mycroft 1522: {
1523:
1.47 christos 1524: printf("tag VT_KERNFS, kernfs vnode\n");
1.23 mycroft 1525: return (0);
1526: }
1527:
1.40 mycroft 1528: int
1.107 perry 1529: kernfs_link(v)
1.41 christos 1530: void *v;
1531: {
1.40 mycroft 1532: struct vop_link_args /* {
1533: struct vnode *a_dvp;
1.107 perry 1534: struct vnode *a_vp;
1.40 mycroft 1535: struct componentname *a_cnp;
1.41 christos 1536: } */ *ap = v;
1.107 perry 1537:
1.40 mycroft 1538: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1539: vput(ap->a_dvp);
1540: return (EROFS);
1541: }
1542:
1543: int
1.41 christos 1544: kernfs_symlink(v)
1545: void *v;
1546: {
1.40 mycroft 1547: struct vop_symlink_args /* {
1548: struct vnode *a_dvp;
1549: struct vnode **a_vpp;
1550: struct componentname *a_cnp;
1551: struct vattr *a_vap;
1552: char *a_target;
1.41 christos 1553: } */ *ap = v;
1.107 perry 1554:
1.40 mycroft 1555: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1556: vput(ap->a_dvp);
1557: return (EROFS);
1.1 cgd 1558: }
CVSweb <webmaster@jp.NetBSD.org>