Annotation of src/sys/miscfs/kernfs/kernfs_vnops.c, revision 1.112
1.112 ! christos 1: /* $NetBSD: kernfs_vnops.c,v 1.111 2005/08/31 09:54:54 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.112 ! christos 42: __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.111 2005/08/31 09:54:54 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);
154: int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
155: size_t, int);
156:
157: static int kernfs_default_xwrite(void *v);
158: static int kernfs_default_fileop_getattr(void *);
159:
160: /* must include all fileop's */
161: const struct kernfs_fileop kernfs_default_fileops[] = {
162: { .kf_fileop = KERNFS_XWRITE },
163: { .kf_fileop = KERNFS_FILEOP_OPEN },
164: { .kf_fileop = KERNFS_FILEOP_GETATTR,
1.104 cl 165: .kf_genop = {kernfs_default_fileop_getattr} },
1.102 cl 166: { .kf_fileop = KERNFS_FILEOP_IOCTL },
167: { .kf_fileop = KERNFS_FILEOP_CLOSE },
1.104 cl 168: { .kf_fileop = KERNFS_FILEOP_WRITE, .kf_genop = {kernfs_default_xwrite} },
1.102 cl 169: };
1.1 cgd 170:
1.110 xtraeme 171: int kernfs_lookup(void *);
1.85 jdolecek 172: #define kernfs_create genfs_eopnotsupp
173: #define kernfs_mknod genfs_eopnotsupp
1.110 xtraeme 174: int kernfs_open(void *);
175: int kernfs_close(void *);
176: int kernfs_access(void *);
177: int kernfs_getattr(void *);
178: int kernfs_setattr(void *);
179: int kernfs_read(void *);
180: int kernfs_write(void *);
1.65 wrstuden 181: #define kernfs_fcntl genfs_fcntl
1.110 xtraeme 182: int kernfs_ioctl(void *);
1.45 mycroft 183: #define kernfs_poll genfs_poll
1.57 fvdl 184: #define kernfs_revoke genfs_revoke
1.44 mycroft 185: #define kernfs_fsync genfs_nullop
186: #define kernfs_seek genfs_nullop
1.85 jdolecek 187: #define kernfs_remove genfs_eopnotsupp
1.110 xtraeme 188: int kernfs_link(void *);
1.85 jdolecek 189: #define kernfs_rename genfs_eopnotsupp
190: #define kernfs_mkdir genfs_eopnotsupp
191: #define kernfs_rmdir genfs_eopnotsupp
1.110 xtraeme 192: int kernfs_symlink(void *);
193: int kernfs_readdir(void *);
1.44 mycroft 194: #define kernfs_readlink genfs_eopnotsupp
195: #define kernfs_abortop genfs_abortop
1.110 xtraeme 196: int kernfs_inactive(void *);
197: int kernfs_reclaim(void *);
1.64 wrstuden 198: #define kernfs_lock genfs_lock
199: #define kernfs_unlock genfs_unlock
1.44 mycroft 200: #define kernfs_bmap genfs_badop
201: #define kernfs_strategy genfs_badop
1.110 xtraeme 202: int kernfs_print(void *);
1.64 wrstuden 203: #define kernfs_islocked genfs_islocked
1.110 xtraeme 204: int kernfs_pathconf(void *);
1.62 kleink 205: #define kernfs_advlock genfs_einval
1.44 mycroft 206: #define kernfs_blkatoff genfs_eopnotsupp
207: #define kernfs_valloc genfs_eopnotsupp
208: #define kernfs_vfree genfs_nullop
209: #define kernfs_truncate genfs_eopnotsupp
210: #define kernfs_update genfs_nullop
211: #define kernfs_bwrite genfs_eopnotsupp
1.79 chs 212: #define kernfs_putpages genfs_putpages
1.41 christos 213:
1.110 xtraeme 214: static int kernfs_xread(struct kernfs_node *, int, char **,
215: size_t, size_t *);
216: static int kernfs_xwrite(const struct kernfs_node *, char *, size_t);
1.41 christos 217:
1.110 xtraeme 218: int (**kernfs_vnodeop_p)(void *);
1.71 jdolecek 219: const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
1.41 christos 220: { &vop_default_desc, vn_default_error },
1.44 mycroft 221: { &vop_lookup_desc, kernfs_lookup }, /* lookup */
222: { &vop_create_desc, kernfs_create }, /* create */
223: { &vop_mknod_desc, kernfs_mknod }, /* mknod */
224: { &vop_open_desc, kernfs_open }, /* open */
225: { &vop_close_desc, kernfs_close }, /* close */
226: { &vop_access_desc, kernfs_access }, /* access */
227: { &vop_getattr_desc, kernfs_getattr }, /* getattr */
228: { &vop_setattr_desc, kernfs_setattr }, /* setattr */
229: { &vop_read_desc, kernfs_read }, /* read */
230: { &vop_write_desc, kernfs_write }, /* write */
1.65 wrstuden 231: { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */
1.44 mycroft 232: { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
1.45 mycroft 233: { &vop_poll_desc, kernfs_poll }, /* poll */
1.57 fvdl 234: { &vop_revoke_desc, kernfs_revoke }, /* revoke */
1.44 mycroft 235: { &vop_fsync_desc, kernfs_fsync }, /* fsync */
236: { &vop_seek_desc, kernfs_seek }, /* seek */
237: { &vop_remove_desc, kernfs_remove }, /* remove */
238: { &vop_link_desc, kernfs_link }, /* link */
239: { &vop_rename_desc, kernfs_rename }, /* rename */
240: { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
241: { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
242: { &vop_symlink_desc, kernfs_symlink }, /* symlink */
243: { &vop_readdir_desc, kernfs_readdir }, /* readdir */
244: { &vop_readlink_desc, kernfs_readlink }, /* readlink */
245: { &vop_abortop_desc, kernfs_abortop }, /* abortop */
246: { &vop_inactive_desc, kernfs_inactive }, /* inactive */
247: { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
248: { &vop_lock_desc, kernfs_lock }, /* lock */
249: { &vop_unlock_desc, kernfs_unlock }, /* unlock */
250: { &vop_bmap_desc, kernfs_bmap }, /* bmap */
251: { &vop_strategy_desc, kernfs_strategy }, /* strategy */
252: { &vop_print_desc, kernfs_print }, /* print */
253: { &vop_islocked_desc, kernfs_islocked }, /* islocked */
254: { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */
255: { &vop_advlock_desc, kernfs_advlock }, /* advlock */
256: { &vop_blkatoff_desc, kernfs_blkatoff }, /* blkatoff */
257: { &vop_valloc_desc, kernfs_valloc }, /* valloc */
258: { &vop_vfree_desc, kernfs_vfree }, /* vfree */
259: { &vop_truncate_desc, kernfs_truncate }, /* truncate */
260: { &vop_update_desc, kernfs_update }, /* update */
261: { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
1.79 chs 262: { &vop_putpages_desc, kernfs_putpages }, /* putpages */
1.76 chs 263: { NULL, NULL }
1.41 christos 264: };
1.71 jdolecek 265: const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
1.41 christos 266: { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
267:
1.102 cl 268: static __inline int
269: kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
270: {
271: if (a->kf_type < b->kf_type)
272: return -1;
273: if (a->kf_type > b->kf_type)
274: return 1;
275: if (a->kf_fileop < b->kf_fileop)
276: return -1;
277: if (a->kf_fileop > b->kf_fileop)
278: return 1;
279: return (0);
280: }
281:
282: SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
283: SPLAY_INITIALIZER(kfsfileoptree);
284: SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
285: SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
286:
287: kfstype
288: kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
289: {
290: static u_char nextfreetype = KFSlasttype;
291: struct kernfs_fileop *dkf, *fkf, skf;
292: int i;
293:
294: /* XXX need to keep track of dkf's memory if we support
295: deallocating types */
296: dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
297: memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
298:
299: for (i = 0; i < sizeof(kernfs_default_fileops) /
300: sizeof(kernfs_default_fileops[0]); i++) {
301: dkf[i].kf_type = nextfreetype;
302: SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
303: }
304:
305: for (i = 0; i < nkf; i++) {
306: skf.kf_type = nextfreetype;
307: skf.kf_fileop = kf[i].kf_fileop;
308: if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
309: fkf->kf_genop = kf[i].kf_genop;
310: }
311:
312: return nextfreetype++;
313: }
314:
315: int
316: kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
317: {
318: struct kernfs_fileop *kf, skf;
319:
320: skf.kf_type = type;
321: skf.kf_fileop = fileop;
322: if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
323: if (kf->kf_vop)
324: return kf->kf_vop(v);
325: return error;
326: }
327:
328: int
1.109 christos 329: kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,
1.102 cl 330: size_t len, int error)
331: {
332: struct kernfs_fileop *kf, skf;
333:
334: skf.kf_type = type;
335: skf.kf_fileop = KERNFS_XWRITE;
336: if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
337: if (kf->kf_xwrite)
1.109 christos 338: return kf->kf_xwrite(kfs, bf, len);
1.102 cl 339: return error;
340: }
341:
342: int
343: kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
344: {
345: struct kernfs_subdir *ks, *parent;
346:
347: if (pkt == NULL) {
348: SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
349: nkern_targets++;
350: if (dkt->dkt_kt.kt_vtype == VDIR)
351: nkern_dirs++;
352: } else {
353: parent = (struct kernfs_subdir *)pkt->kt_data;
354: SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
355: parent->ks_nentries++;
356: if (dkt->dkt_kt.kt_vtype == VDIR)
357: parent->ks_dirs++;
358: }
359: if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
360: ks = malloc(sizeof(struct kernfs_subdir),
361: M_TEMP, M_WAITOK);
362: SIMPLEQ_INIT(&ks->ks_entries);
363: ks->ks_nentries = 2; /* . and .. */
364: ks->ks_dirs = 2;
365: ks->ks_parent = pkt ? pkt : &kern_targets[0];
366: dkt->dkt_kt.kt_data = ks;
367: }
368: return 0;
369: }
370:
1.82 jdolecek 371: static int
1.90 itojun 372: kernfs_xread(kfs, off, bufp, len, wrlen)
373: struct kernfs_node *kfs;
1.28 mycroft 374: int off;
375: char **bufp;
1.82 jdolecek 376: size_t len;
377: size_t *wrlen;
1.1 cgd 378: {
1.90 itojun 379: const struct kern_target *kt;
380: #ifdef IPSEC
381: struct mbuf *m;
382: #endif
383:
384: kt = kfs->kfs_kt;
1.1 cgd 385:
1.90 itojun 386: switch (kfs->kfs_type) {
1.98 darcy 387: case KFStime: {
1.1 cgd 388: struct timeval tv;
1.28 mycroft 389:
1.1 cgd 390: microtime(&tv);
1.90 itojun 391: snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
1.1 cgd 392: break;
393: }
394:
1.98 darcy 395: case KFSint: {
1.1 cgd 396: int *ip = kt->kt_data;
1.28 mycroft 397:
1.90 itojun 398: snprintf(*bufp, len, "%d\n", *ip);
1.1 cgd 399: break;
400: }
401:
1.98 darcy 402: case KFSstring: {
1.1 cgd 403: char *cp = kt->kt_data;
404:
1.28 mycroft 405: *bufp = cp;
406: break;
407: }
1.1 cgd 408:
1.98 darcy 409: case KFSmsgbuf: {
1.28 mycroft 410: long n;
411:
1.52 leo 412: /*
413: * deal with cases where the message buffer has
414: * become corrupted.
415: */
416: if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
417: msgbufenabled = 0;
418: return (ENXIO);
419: }
420:
421: /*
422: * Note that reads of /kern/msgbuf won't necessarily yield
423: * consistent results, if the message buffer is modified
424: * while the read is in progress. The worst that can happen
425: * is that incorrect data will be read. There's no way
426: * that this can crash the system unless the values in the
427: * message buffer header are corrupted, but that'll cause
428: * the system to die anyway.
429: */
1.82 jdolecek 430: if (off >= msgbufp->msg_bufs) {
431: *wrlen = 0;
1.28 mycroft 432: return (0);
1.82 jdolecek 433: }
1.28 mycroft 434: n = msgbufp->msg_bufx + off;
1.52 leo 435: if (n >= msgbufp->msg_bufs)
436: n -= msgbufp->msg_bufs;
437: len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
1.28 mycroft 438: *bufp = msgbufp->msg_bufc + n;
1.82 jdolecek 439: *wrlen = len;
440: return (0);
1.1 cgd 441: }
442:
1.98 darcy 443: case KFShostname: {
1.1 cgd 444: char *cp = hostname;
445: int xlen = hostnamelen;
446:
1.90 itojun 447: if (xlen >= (len - 2))
1.1 cgd 448: return (EINVAL);
449:
1.60 perry 450: memcpy(*bufp, cp, xlen);
1.28 mycroft 451: (*bufp)[xlen] = '\n';
452: (*bufp)[xlen+1] = '\0';
1.90 itojun 453: len = strlen(*bufp);
1.1 cgd 454: break;
455: }
456:
1.98 darcy 457: case KFSavenrun:
1.31 mycroft 458: averunnable.fscale = FSCALE;
1.90 itojun 459: snprintf(*bufp, len, "%d %d %d %ld\n",
1.23 mycroft 460: averunnable.ldavg[0], averunnable.ldavg[1],
461: averunnable.ldavg[2], averunnable.fscale);
1.1 cgd 462: break;
463:
1.90 itojun 464: #ifdef IPSEC
1.98 darcy 465: case KFSipsecsa:
1.90 itojun 466: /*
467: * Note that SA configuration could be changed during the
468: * read operation, resulting in garbled output.
469: */
470: m = key_setdumpsa_spi(htonl(kfs->kfs_value));
471: if (!m)
472: return (ENOBUFS);
473: if (off >= m->m_pkthdr.len) {
474: *wrlen = 0;
475: m_freem(m);
476: return (0);
477: }
478: if (len > m->m_pkthdr.len - off)
479: len = m->m_pkthdr.len - off;
480: m_copydata(m, off, len, *bufp);
481: *wrlen = len;
482: m_freem(m);
483: return (0);
484:
1.98 darcy 485: case KFSipsecsp:
1.90 itojun 486: /*
487: * Note that SP configuration could be changed during the
488: * read operation, resulting in garbled output.
489: */
490: if (!kfs->kfs_v) {
491: struct secpolicy *sp;
492:
493: sp = key_getspbyid(kfs->kfs_value);
494: if (sp)
495: kfs->kfs_v = sp;
496: else
497: return (ENOENT);
498: }
499: m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
500: SADB_X_SPDGET, 0, 0);
501: if (!m)
502: return (ENOBUFS);
503: if (off >= m->m_pkthdr.len) {
504: *wrlen = 0;
505: m_freem(m);
506: return (0);
507: }
508: if (len > m->m_pkthdr.len - off)
509: len = m->m_pkthdr.len - off;
510: m_copydata(m, off, len, *bufp);
511: *wrlen = len;
512: m_freem(m);
513: return (0);
514: #endif
515:
1.1 cgd 516: default:
1.82 jdolecek 517: *wrlen = 0;
1.28 mycroft 518: return (0);
1.1 cgd 519: }
520:
1.28 mycroft 521: len = strlen(*bufp);
522: if (len <= off)
1.82 jdolecek 523: *wrlen = 0;
524: else {
525: *bufp += off;
526: *wrlen = len - off;
527: }
528: return (0);
1.1 cgd 529: }
530:
1.82 jdolecek 531: static int
1.109 christos 532: kernfs_xwrite(kfs, bf, len)
1.90 itojun 533: const struct kernfs_node *kfs;
1.109 christos 534: char *bf;
1.82 jdolecek 535: size_t len;
1.1 cgd 536: {
1.23 mycroft 537:
1.90 itojun 538: switch (kfs->kfs_type) {
1.98 darcy 539: case KFShostname:
1.109 christos 540: if (bf[len-1] == '\n')
1.1 cgd 541: --len;
1.109 christos 542: memcpy(hostname, bf, len);
1.17 cgd 543: hostname[len] = '\0';
1.82 jdolecek 544: hostnamelen = (size_t) len;
1.1 cgd 545: return (0);
546:
547: default:
1.109 christos 548: return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO);
1.1 cgd 549: }
550: }
551:
1.17 cgd 552:
553: /*
1.1 cgd 554: * vp is the current namei directory
555: * ndp is the name to locate in that directory...
556: */
1.41 christos 557: int
558: kernfs_lookup(v)
559: void *v;
560: {
1.23 mycroft 561: struct vop_lookup_args /* {
562: struct vnode * a_dvp;
563: struct vnode ** a_vpp;
564: struct componentname * a_cnp;
1.41 christos 565: } */ *ap = v;
1.23 mycroft 566: struct componentname *cnp = ap->a_cnp;
567: struct vnode **vpp = ap->a_vpp;
568: struct vnode *dvp = ap->a_dvp;
1.48 cgd 569: const char *pname = cnp->cn_nameptr;
1.90 itojun 570: const struct kernfs_node *kfs;
1.75 jdolecek 571: const struct kern_target *kt;
1.102 cl 572: const struct dyn_kern_target *dkt;
573: const struct kernfs_subdir *ks;
1.64 wrstuden 574: int error, i, wantpunlock;
1.90 itojun 575: #ifdef IPSEC
576: char *ep;
577: u_int32_t id;
1.1 cgd 578: #endif
1.23 mycroft 579:
1.35 mycroft 580: *vpp = NULLVP;
1.64 wrstuden 581: cnp->cn_flags &= ~PDIRUNLOCK;
1.35 mycroft 582:
583: if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
584: return (EROFS);
585:
1.23 mycroft 586: if (cnp->cn_namelen == 1 && *pname == '.') {
587: *vpp = dvp;
1.1 cgd 588: VREF(dvp);
589: return (0);
590: }
1.13 cgd 591:
1.90 itojun 592: wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
593: kfs = VTOKERN(dvp);
594: switch (kfs->kfs_type) {
1.98 darcy 595: case KFSkern:
1.90 itojun 596: /*
597: * Shouldn't get here with .. in the root node.
598: */
599: if (cnp->cn_flags & ISDOTDOT)
600: return (EIO);
1.64 wrstuden 601:
1.102 cl 602: for (i = 0; i < static_nkern_targets; i++) {
1.90 itojun 603: kt = &kern_targets[i];
604: if (cnp->cn_namelen == kt->kt_namlen &&
605: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
606: goto found;
607: }
1.102 cl 608: SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
609: if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
610: memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
611: kt = &dkt->dkt_kt;
612: goto found;
613: }
614: }
1.90 itojun 615: break;
1.25 mycroft 616:
1.90 itojun 617: found:
618: error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
619: if ((error == 0) && wantpunlock) {
620: VOP_UNLOCK(dvp, 0);
621: cnp->cn_flags |= PDIRUNLOCK;
622: }
623: return (error);
1.64 wrstuden 624:
1.102 cl 625: case KFSsubdir:
626: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
627: if (cnp->cn_flags & ISDOTDOT) {
628: kt = ks->ks_parent;
629: goto found;
630: }
631:
632: SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
633: if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
634: memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
635: kt = &dkt->dkt_kt;
636: goto found;
637: }
638: }
639: break;
640:
1.90 itojun 641: #ifdef IPSEC
1.98 darcy 642: case KFSipsecsadir:
1.100 cl 643: if (cnp->cn_flags & ISDOTDOT) {
644: kt = &kern_targets[0];
645: goto found;
646: }
647:
648: for (i = 2; i < nipsecsa_targets; i++) {
1.90 itojun 649: kt = &ipsecsa_targets[i];
650: if (cnp->cn_namelen == kt->kt_namlen &&
1.100 cl 651: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
652: goto found;
1.90 itojun 653: }
1.1 cgd 654:
1.90 itojun 655: ep = NULL;
656: id = strtoul(pname, &ep, 10);
657: if (!ep || *ep || ep == pname)
658: break;
1.1 cgd 659:
1.101 cl 660: error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
1.90 itojun 661: if ((error == 0) && wantpunlock) {
662: VOP_UNLOCK(dvp, 0);
663: cnp->cn_flags |= PDIRUNLOCK;
664: }
665: return (error);
1.23 mycroft 666:
1.98 darcy 667: case KFSipsecspdir:
1.100 cl 668: if (cnp->cn_flags & ISDOTDOT) {
669: kt = &kern_targets[0];
670: goto found;
671: }
672:
673: for (i = 2; i < nipsecsp_targets; i++) {
1.90 itojun 674: kt = &ipsecsp_targets[i];
675: if (cnp->cn_namelen == kt->kt_namlen &&
1.100 cl 676: memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
677: goto found;
1.57 fvdl 678: }
1.90 itojun 679:
680: ep = NULL;
681: id = strtoul(pname, &ep, 10);
682: if (!ep || *ep || ep == pname)
683: break;
684:
1.101 cl 685: error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
1.90 itojun 686: if ((error == 0) && wantpunlock) {
1.64 wrstuden 687: VOP_UNLOCK(dvp, 0);
688: cnp->cn_flags |= PDIRUNLOCK;
689: }
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;
707: struct ucred *a_cred;
708: struct proc *a_p;
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;
748: struct ucred *a_cred;
749: struct proc *a_p;
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.23 mycroft 775: struct ucred *a_cred;
776: struct proc *a_p;
1.41 christos 777: } */ *ap = v;
1.90 itojun 778: struct vattr va;
779: int error;
1.17 cgd 780:
1.90 itojun 781: if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)
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;
795: struct ucred *a_cred;
796: struct proc *a_p;
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;
813: struct ucred *a_cred;
814: struct proc *a_p;
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.81 lukem 832: /*
1.92 dan 833: * Make all times be current TOD, except for the "boottime" node.
1.93 simonb 834: * Avoid microtime(9), it's slow.
1.83 simonb 835: * We don't guard the read from time(9) with splclock(9) since we
1.107 perry 836: * don't actually need to be THAT sure the access is atomic.
1.81 lukem 837: */
1.107 perry 838: if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 &&
1.92 dan 839: !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
840: TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
841: } else {
842: TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);
843: }
1.81 lukem 844: vap->va_atime = vap->va_mtime = vap->va_ctime;
1.1 cgd 845: vap->va_gen = 0;
846: vap->va_flags = 0;
847: vap->va_rdev = 0;
848: vap->va_bytes = 0;
849:
1.90 itojun 850: switch (kfs->kfs_type) {
1.98 darcy 851: case KFSkern:
1.102 cl 852: vap->va_nlink = nkern_dirs;
1.90 itojun 853: vap->va_bytes = vap->va_size = DEV_BSIZE;
854: break;
855:
1.98 darcy 856: case KFSroot:
1.90 itojun 857: vap->va_nlink = 1;
858: vap->va_bytes = vap->va_size = DEV_BSIZE;
859: break;
860:
1.102 cl 861: case KFSsubdir:
862: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
863: vap->va_nlink = ks->ks_dirs;
864: vap->va_bytes = vap->va_size = DEV_BSIZE;
865: break;
866:
1.98 darcy 867: case KFSnull:
868: case KFStime:
869: case KFSint:
870: case KFSstring:
871: case KFShostname:
872: case KFSavenrun:
873: case KFSdevice:
874: case KFSmsgbuf:
1.90 itojun 875: #ifdef IPSEC
1.98 darcy 876: case KFSipsecsa:
877: case KFSipsecsp:
1.1 cgd 878: #endif
879: vap->va_nlink = 1;
1.84 jdolecek 880: total = 0;
881: do {
1.109 christos 882: bf = strbuf;
883: error = kernfs_xread(kfs, total, &bf,
1.90 itojun 884: sizeof(strbuf), &nread);
1.84 jdolecek 885: total += nread;
886: } while (error == 0 && nread != 0);
1.90 itojun 887: vap->va_bytes = vap->va_size = total;
888: break;
889:
890: #ifdef IPSEC
1.98 darcy 891: case KFSipsecsadir:
892: case KFSipsecspdir:
1.90 itojun 893: vap->va_nlink = 2;
894: vap->va_bytes = vap->va_size = DEV_BSIZE;
895: break;
896: #endif
897:
898: default:
1.102 cl 899: error = kernfs_try_fileop(kfs->kfs_type,
900: KERNFS_FILEOP_GETATTR, v, EINVAL);
1.90 itojun 901: break;
1.1 cgd 902: }
903:
904: return (error);
905: }
906:
1.41 christos 907: /*ARGSUSED*/
908: int
909: kernfs_setattr(v)
910: void *v;
1.1 cgd 911: {
1.90 itojun 912:
1.1 cgd 913: /*
1.17 cgd 914: * Silently ignore attribute changes.
915: * This allows for open with truncate to have no
916: * effect until some data is written. I want to
917: * do it this way because all writes are atomic.
1.1 cgd 918: */
1.17 cgd 919: return (0);
1.1 cgd 920: }
921:
1.28 mycroft 922: int
1.41 christos 923: kernfs_read(v)
924: void *v;
925: {
1.23 mycroft 926: struct vop_read_args /* {
927: struct vnode *a_vp;
928: struct uio *a_uio;
929: int a_ioflag;
930: struct ucred *a_cred;
1.41 christos 931: } */ *ap = v;
1.23 mycroft 932: struct uio *uio = ap->a_uio;
1.90 itojun 933: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.109 christos 934: char strbuf[KSTRING], *bf;
1.82 jdolecek 935: off_t off;
936: size_t len;
1.28 mycroft 937: int error;
1.23 mycroft 938:
1.90 itojun 939: if (ap->a_vp->v_type == VDIR)
1.23 mycroft 940: return (EOPNOTSUPP);
941:
1.112 ! christos 942: /* Don't allow negative offsets */
! 943: if (uio->uio_offset < 0)
! 944: return EINVAL;
! 945:
1.28 mycroft 946: off = uio->uio_offset;
1.109 christos 947: bf = strbuf;
948: if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
949: error = uiomove(bf, len, uio);
1.82 jdolecek 950: return (error);
1.1 cgd 951: }
952:
1.102 cl 953: static int
954: kernfs_default_xwrite(v)
1.41 christos 955: void *v;
956: {
1.23 mycroft 957: struct vop_write_args /* {
958: struct vnode *a_vp;
959: struct uio *a_uio;
960: int a_ioflag;
961: struct ucred *a_cred;
1.41 christos 962: } */ *ap = v;
1.90 itojun 963: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.23 mycroft 964: struct uio *uio = ap->a_uio;
965: int error, xlen;
1.1 cgd 966: char strbuf[KSTRING];
1.23 mycroft 967:
1.1 cgd 968: if (uio->uio_offset != 0)
969: return (EINVAL);
970:
971: xlen = min(uio->uio_resid, KSTRING-1);
1.41 christos 972: if ((error = uiomove(strbuf, xlen, uio)) != 0)
1.1 cgd 973: return (error);
974:
975: if (uio->uio_resid != 0)
976: return (EIO);
977:
978: strbuf[xlen] = '\0';
1.17 cgd 979: xlen = strlen(strbuf);
1.90 itojun 980: return (kernfs_xwrite(kfs, strbuf, xlen));
1.1 cgd 981: }
982:
1.102 cl 983: int
984: kernfs_write(v)
985: void *v;
986: {
987: struct vop_write_args /* {
988: struct vnode *a_vp;
989: struct uio *a_uio;
990: int a_ioflag;
991: struct ucred *a_cred;
992: } */ *ap = v;
993: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
994:
995: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 0);
996: }
997:
998: int
999: kernfs_ioctl(v)
1000: void *v;
1001: {
1002: struct vop_ioctl_args /* {
1003: const struct vnodeop_desc *a_desc;
1004: struct vnode *a_vp;
1005: u_long a_command;
1006: void *a_data;
1007: int a_fflag;
1008: struct ucred *a_cred;
1009: struct proc *a_p;
1010: } */ *ap = v;
1011: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1012:
1013: return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
1014: EPASSTHROUGH);
1015: }
1016:
1.101 cl 1017: static int
1018: kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
1019: u_int32_t value, struct vop_readdir_args *ap)
1020: {
1021: struct kernfs_node *kfs;
1022: struct vnode *vp;
1023: int error;
1024:
1025: if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
1026: value)) != 0)
1027: return error;
1028: if (kt->kt_tag == KFSdevice) {
1029: struct vattr va;
1030: if ((error = VOP_GETATTR(vp, &va, ap->a_cred,
1031: ap->a_uio->uio_segflg == UIO_USERSPACE ?
1.106 skrll 1032: ap->a_uio->uio_procp : &proc0)) != 0)
1.101 cl 1033: return (error);
1034: d->d_fileno = va.va_fileid;
1035: } else {
1036: kfs = VTOKERN(vp);
1037: d->d_fileno = kfs->kfs_fileno;
1038: }
1039: vput(vp);
1040: return 0;
1041: }
1042:
1043: static int
1044: kernfs_setdirentfileno(struct dirent *d, off_t entry,
1045: struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
1046: const struct kern_target *kt, struct vop_readdir_args *ap)
1047: {
1048: const struct kern_target *ikt;
1049: int error;
1050:
1051: switch (entry) {
1052: case 0:
1053: d->d_fileno = thisdir_kfs->kfs_fileno;
1054: return 0;
1055: case 1:
1056: ikt = parent_kt;
1057: break;
1058: default:
1059: ikt = kt;
1060: break;
1061: }
1062: if (ikt != thisdir_kfs->kfs_kt) {
1063: if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
1064: return error;
1065: } else
1066: d->d_fileno = thisdir_kfs->kfs_fileno;
1067: return 0;
1068: }
1069:
1.41 christos 1070: int
1071: kernfs_readdir(v)
1072: void *v;
1073: {
1.23 mycroft 1074: struct vop_readdir_args /* {
1075: struct vnode *a_vp;
1076: struct uio *a_uio;
1077: struct ucred *a_cred;
1.26 mycroft 1078: int *a_eofflag;
1.57 fvdl 1079: off_t **a_cookies;
1080: int a_*ncookies;
1.41 christos 1081: } */ *ap = v;
1.23 mycroft 1082: struct uio *uio = ap->a_uio;
1.37 mycroft 1083: struct dirent d;
1.90 itojun 1084: struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.75 jdolecek 1085: const struct kern_target *kt;
1.102 cl 1086: const struct dyn_kern_target *dkt = NULL;
1087: const struct kernfs_subdir *ks;
1088: off_t i, j;
1.1 cgd 1089: int error;
1.57 fvdl 1090: off_t *cookies = NULL;
1.90 itojun 1091: int ncookies = 0, n;
1092: #ifdef IPSEC
1093: struct secasvar *sav, *sav2;
1094: struct secpolicy *sp;
1095: #endif
1.23 mycroft 1096:
1.37 mycroft 1097: if (uio->uio_resid < UIO_MX)
1098: return (EINVAL);
1.38 mycroft 1099: if (uio->uio_offset < 0)
1.37 mycroft 1100: return (EINVAL);
1.26 mycroft 1101:
1.1 cgd 1102: error = 0;
1.38 mycroft 1103: i = uio->uio_offset;
1.90 itojun 1104: memset(&d, 0, sizeof(d));
1105: d.d_reclen = UIO_MX;
1106: ncookies = uio->uio_resid / UIO_MX;
1107:
1108: switch (kfs->kfs_type) {
1.98 darcy 1109: case KFSkern:
1.90 itojun 1110: if (i >= nkern_targets)
1111: return (0);
1.66 sommerfe 1112:
1.90 itojun 1113: if (ap->a_ncookies) {
1114: ncookies = min(ncookies, (nkern_targets - i));
1115: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1116: M_WAITOK);
1117: *ap->a_cookies = cookies;
1118: }
1119:
1120: n = 0;
1121: for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1.102 cl 1122: if (i < static_nkern_targets)
1123: kt = &kern_targets[i];
1124: else {
1125: if (dkt == NULL) {
1126: dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
1127: for (j = static_nkern_targets; j < i &&
1128: dkt != NULL; j++)
1129: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1130: if (j != i)
1131: break;
1132: } else {
1133: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1134: if (dkt == NULL)
1135: break;
1136: }
1137: kt = &dkt->dkt_kt;
1138: }
1.98 darcy 1139: if (kt->kt_tag == KFSdevice) {
1.94 itojun 1140: dev_t *dp = kt->kt_data;
1141: struct vnode *fvp;
1142:
1143: if (*dp == NODEV ||
1144: !vfinddev(*dp, kt->kt_vtype, &fvp))
1145: continue;
1146: }
1.90 itojun 1147: d.d_namlen = kt->kt_namlen;
1.101 cl 1148: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1149: &kern_targets[0], kt, ap)) != 0)
1150: break;
1.90 itojun 1151: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1152: d.d_type = kt->kt_type;
1.99 jrf 1153: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1154: break;
1155: if (cookies)
1156: *cookies++ = i + 1;
1157: n++;
1158: }
1159: ncookies = n;
1160: break;
1161:
1.98 darcy 1162: case KFSroot:
1.90 itojun 1163: if (i >= 2)
1164: return 0;
1165:
1166: if (ap->a_ncookies) {
1167: ncookies = min(ncookies, (2 - i));
1168: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1169: M_WAITOK);
1170: *ap->a_cookies = cookies;
1171: }
1172:
1173: n = 0;
1174: for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1175: kt = &kern_targets[i];
1176: d.d_namlen = kt->kt_namlen;
1177: d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
1178: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1179: d.d_type = kt->kt_type;
1.99 jrf 1180: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1181: break;
1182: if (cookies)
1183: *cookies++ = i + 1;
1184: n++;
1185: }
1186: ncookies = n;
1187: break;
1188:
1.102 cl 1189: case KFSsubdir:
1190: ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
1191: if (i >= ks->ks_nentries)
1192: return (0);
1193:
1194: if (ap->a_ncookies) {
1195: ncookies = min(ncookies, (ks->ks_nentries - i));
1196: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1197: M_WAITOK);
1198: *ap->a_cookies = cookies;
1199: }
1200:
1201: dkt = SIMPLEQ_FIRST(&ks->ks_entries);
1202: for (j = 0; j < i && dkt != NULL; j++)
1203: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1204: n = 0;
1205: for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
1206: if (i < 2)
1207: kt = &subdir_targets[i];
1208: else {
1209: /* check if ks_nentries lied to us */
1210: if (dkt == NULL)
1211: break;
1212: kt = &dkt->dkt_kt;
1213: dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1214: }
1215: if (kt->kt_tag == KFSdevice) {
1216: dev_t *dp = kt->kt_data;
1217: struct vnode *fvp;
1218:
1219: if (*dp == NODEV ||
1220: !vfinddev(*dp, kt->kt_vtype, &fvp))
1221: continue;
1222: }
1223: d.d_namlen = kt->kt_namlen;
1224: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1225: ks->ks_parent, kt, ap)) != 0)
1226: break;
1227: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1228: d.d_type = kt->kt_type;
1.103 jrf 1229: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.102 cl 1230: break;
1231: if (cookies)
1232: *cookies++ = i + 1;
1233: n++;
1234: }
1235: ncookies = n;
1236: break;
1237:
1.90 itojun 1238: #ifdef IPSEC
1.98 darcy 1239: case KFSipsecsadir:
1.90 itojun 1240: /* count SA in the system */
1241: n = 0;
1242: TAILQ_FOREACH(sav, &satailq, tailq) {
1243: for (sav2 = TAILQ_FIRST(&satailq);
1244: sav2 != sav;
1245: sav2 = TAILQ_NEXT(sav2, tailq)) {
1246: if (sav->spi == sav2->spi) {
1247: /* multiple SA with same SPI */
1248: break;
1249: }
1250: }
1251: if (sav == sav2 || sav->spi != sav2->spi)
1252: n++;
1253: }
1.37 mycroft 1254:
1.90 itojun 1255: if (i >= nipsecsa_targets + n)
1256: return (0);
1.57 fvdl 1257:
1.90 itojun 1258: if (ap->a_ncookies) {
1259: ncookies = min(ncookies, (n - i));
1260: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1261: M_WAITOK);
1262: *ap->a_cookies = cookies;
1263: }
1.26 mycroft 1264:
1.90 itojun 1265: n = 0;
1266: for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
1267: kt = &ipsecsa_targets[i];
1268: d.d_namlen = kt->kt_namlen;
1.101 cl 1269: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1270: &kern_targets[0], kt, ap)) != 0)
1271: break;
1.90 itojun 1272: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1273: d.d_type = kt->kt_type;
1.99 jrf 1274: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1275: break;
1276: if (cookies)
1277: *cookies++ = i + 1;
1278: n++;
1279: }
1280: if (error) {
1281: ncookies = n;
1282: break;
1283: }
1.26 mycroft 1284:
1.90 itojun 1285: TAILQ_FOREACH(sav, &satailq, tailq) {
1286: for (sav2 = TAILQ_FIRST(&satailq);
1287: sav2 != sav;
1288: sav2 = TAILQ_NEXT(sav2, tailq)) {
1289: if (sav->spi == sav2->spi) {
1290: /* multiple SA with same SPI */
1291: break;
1292: }
1293: }
1294: if (sav != sav2 && sav->spi == sav2->spi)
1.23 mycroft 1295: continue;
1.90 itojun 1296: if (uio->uio_resid < UIO_MX)
1297: break;
1.101 cl 1298: if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
1299: sav->spi, ap)) != 0)
1300: break;
1.90 itojun 1301: d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1302: "%u", ntohl(sav->spi));
1303: d.d_type = DT_REG;
1.99 jrf 1304: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1305: break;
1306: if (cookies)
1307: *cookies++ = i + 1;
1308: n++;
1309: i++;
1.23 mycroft 1310: }
1.90 itojun 1311: ncookies = n;
1312: break;
1313:
1.98 darcy 1314: case KFSipsecspdir:
1.90 itojun 1315: /* count SP in the system */
1316: n = 0;
1317: TAILQ_FOREACH(sp, &sptailq, tailq)
1318: n++;
1.26 mycroft 1319:
1.102 cl 1320: if (i >= nipsecsp_targets + n)
1.90 itojun 1321: return (0);
1322:
1323: if (ap->a_ncookies) {
1324: ncookies = min(ncookies, (n - i));
1325: cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1326: M_WAITOK);
1327: *ap->a_cookies = cookies;
1328: }
1.26 mycroft 1329:
1.90 itojun 1330: n = 0;
1331: for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
1332: kt = &ipsecsp_targets[i];
1333: d.d_namlen = kt->kt_namlen;
1.101 cl 1334: if ((error = kernfs_setdirentfileno(&d, i, kfs,
1335: &kern_targets[0], kt, ap)) != 0)
1336: break;
1.90 itojun 1337: memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1338: d.d_type = kt->kt_type;
1.99 jrf 1339: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1340: break;
1341: if (cookies)
1342: *cookies++ = i + 1;
1343: n++;
1344: }
1345: if (error) {
1346: ncookies = n;
1.1 cgd 1347: break;
1.57 fvdl 1348: }
1.90 itojun 1349:
1350: TAILQ_FOREACH(sp, &sptailq, tailq) {
1351: if (uio->uio_resid < UIO_MX)
1352: break;
1.101 cl 1353: if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
1354: sp->id, ap)) != 0)
1355: break;
1.90 itojun 1356: d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1357: "%u", sp->id);
1358: d.d_type = DT_REG;
1.99 jrf 1359: if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90 itojun 1360: break;
1361: if (cookies)
1362: *cookies++ = i + 1;
1363: n++;
1364: i++;
1365: }
1366: ncookies = n;
1367: break;
1368: #endif
1369:
1370: default:
1371: error = ENOTDIR;
1372: break;
1.57 fvdl 1373: }
1374:
1375: if (ap->a_ncookies) {
1376: if (error) {
1.90 itojun 1377: if (cookies)
1378: free(*ap->a_cookies, M_TEMP);
1.57 fvdl 1379: *ap->a_ncookies = 0;
1380: *ap->a_cookies = NULL;
1381: } else
1382: *ap->a_ncookies = ncookies;
1.1 cgd 1383: }
1384:
1.38 mycroft 1385: uio->uio_offset = i;
1.1 cgd 1386: return (error);
1387: }
1388:
1.41 christos 1389: int
1390: kernfs_inactive(v)
1391: void *v;
1392: {
1.23 mycroft 1393: struct vop_inactive_args /* {
1394: struct vnode *a_vp;
1.57 fvdl 1395: struct proc *a_p;
1.41 christos 1396: } */ *ap = v;
1.23 mycroft 1397: struct vnode *vp = ap->a_vp;
1.90 itojun 1398: const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1399: #ifdef IPSEC
1400: struct mbuf *m;
1401: struct secpolicy *sp;
1402: #endif
1.23 mycroft 1403:
1.90 itojun 1404: VOP_UNLOCK(vp, 0);
1405: switch (kfs->kfs_type) {
1406: #ifdef IPSEC
1.98 darcy 1407: case KFSipsecsa:
1.90 itojun 1408: m = key_setdumpsa_spi(htonl(kfs->kfs_value));
1409: if (m)
1410: m_freem(m);
1.91 itojun 1411: else
1.90 itojun 1412: vgone(vp);
1413: break;
1.98 darcy 1414: case KFSipsecsp:
1.90 itojun 1415: sp = key_getspbyid(kfs->kfs_value);
1416: if (sp)
1417: key_freesp(sp);
1418: else {
1419: /* should never happen as we hold a refcnt */
1420: vgone(vp);
1421: }
1422: break;
1.23 mycroft 1423: #endif
1.90 itojun 1424: default:
1425: break;
1426: }
1.23 mycroft 1427: return (0);
1428: }
1429:
1.41 christos 1430: int
1431: kernfs_reclaim(v)
1432: void *v;
1433: {
1.23 mycroft 1434: struct vop_reclaim_args /* {
1435: struct vnode *a_vp;
1.41 christos 1436: } */ *ap = v;
1.23 mycroft 1437:
1.90 itojun 1438: return (kernfs_freevp(ap->a_vp));
1.1 cgd 1439: }
1440:
1441: /*
1.23 mycroft 1442: * Return POSIX pathconf information applicable to special devices.
1443: */
1.41 christos 1444: int
1445: kernfs_pathconf(v)
1446: void *v;
1447: {
1.23 mycroft 1448: struct vop_pathconf_args /* {
1449: struct vnode *a_vp;
1450: int a_name;
1.29 cgd 1451: register_t *a_retval;
1.41 christos 1452: } */ *ap = v;
1.23 mycroft 1453:
1454: switch (ap->a_name) {
1455: case _PC_LINK_MAX:
1456: *ap->a_retval = LINK_MAX;
1457: return (0);
1458: case _PC_MAX_CANON:
1459: *ap->a_retval = MAX_CANON;
1460: return (0);
1461: case _PC_MAX_INPUT:
1462: *ap->a_retval = MAX_INPUT;
1463: return (0);
1464: case _PC_PIPE_BUF:
1465: *ap->a_retval = PIPE_BUF;
1466: return (0);
1467: case _PC_CHOWN_RESTRICTED:
1468: *ap->a_retval = 1;
1469: return (0);
1470: case _PC_VDISABLE:
1471: *ap->a_retval = _POSIX_VDISABLE;
1.59 kleink 1472: return (0);
1473: case _PC_SYNC_IO:
1474: *ap->a_retval = 1;
1.23 mycroft 1475: return (0);
1476: default:
1477: return (EINVAL);
1478: }
1479: /* NOTREACHED */
1480: }
1481:
1482: /*
1483: * Print out the contents of a /dev/fd vnode.
1.1 cgd 1484: */
1485: /* ARGSUSED */
1.41 christos 1486: int
1487: kernfs_print(v)
1488: void *v;
1.23 mycroft 1489: {
1490:
1.47 christos 1491: printf("tag VT_KERNFS, kernfs vnode\n");
1.23 mycroft 1492: return (0);
1493: }
1494:
1.40 mycroft 1495: int
1.107 perry 1496: kernfs_link(v)
1.41 christos 1497: void *v;
1498: {
1.40 mycroft 1499: struct vop_link_args /* {
1500: struct vnode *a_dvp;
1.107 perry 1501: struct vnode *a_vp;
1.40 mycroft 1502: struct componentname *a_cnp;
1.41 christos 1503: } */ *ap = v;
1.107 perry 1504:
1.40 mycroft 1505: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1506: vput(ap->a_dvp);
1507: return (EROFS);
1508: }
1509:
1510: int
1.41 christos 1511: kernfs_symlink(v)
1512: void *v;
1513: {
1.40 mycroft 1514: struct vop_symlink_args /* {
1515: struct vnode *a_dvp;
1516: struct vnode **a_vpp;
1517: struct componentname *a_cnp;
1518: struct vattr *a_vap;
1519: char *a_target;
1.41 christos 1520: } */ *ap = v;
1.107 perry 1521:
1.40 mycroft 1522: VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1523: vput(ap->a_dvp);
1524: return (EROFS);
1.1 cgd 1525: }
CVSweb <webmaster@jp.NetBSD.org>