ia64/xen-unstable

view netbsd-2.0-xen-sparse/sys/miscfs/kernfs/kernfs_vnops.c @ 6462:af3750d1ec53

Bug fixes from Kevin (x2) and Anthony
Missing prototypes (Kevin)
Bad n_rid_blocks computation (Anthony)
Bad pte when single-entry dtlb lookup is successful (Kevin)
author djm@kirby.fc.hp.com
date Fri Sep 02 11:59:08 2005 -0600 (2005-09-02)
parents a01199a95070
children
line source
1 /* $NetBSD: kernfs_vnops.c,v 1.98.2.3 2004/05/15 13:35:27 tron Exp $ */
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software donated to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
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.
33 *
34 * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95
35 */
37 /*
38 * Kernel parameter filesystem (/kern)
39 */
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.98.2.3 2004/05/15 13:35:27 tron Exp $");
44 #ifdef _KERNEL_OPT
45 #include "opt_ipsec.h"
46 #endif
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/vmmeter.h>
52 #include <sys/time.h>
53 #include <sys/proc.h>
54 #include <sys/vnode.h>
55 #include <sys/malloc.h>
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>
61 #include <sys/dirent.h>
62 #include <sys/msgbuf.h>
64 #include <miscfs/genfs/genfs.h>
65 #include <miscfs/kernfs/kernfs.h>
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
75 #include <uvm/uvm_extern.h>
77 #define KSTRING 256 /* Largest I/O available via this filesystem */
78 #define UIO_MX 32
80 #define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH)
81 #define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
82 #define UREAD_MODE (S_IRUSR)
83 #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
84 #define UDIR_MODE (S_IRUSR|S_IXUSR)
86 #define N(s) sizeof(s)-1, s
87 const struct kern_target kern_targets[] = {
88 /* NOTE: The name must be less than UIO_MX-16 chars in length */
89 /* name data tag type ro/rw */
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 },
93 /* XXX cast away const */
94 { DT_REG, N("copyright"), (void *)copyright,
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 },
98 #ifdef IPSEC
99 { DT_DIR, N("ipsecsa"), 0, KFSipsecsadir, VDIR, UDIR_MODE },
100 { DT_DIR, N("ipsecsp"), 0, KFSipsecspdir, VDIR, UDIR_MODE },
101 #endif
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 },
106 #if 0
107 { DT_DIR, N("root"), 0, KFSnull, VDIR, DIR_MODE },
108 #endif
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 },
112 /* XXX cast away const */
113 { DT_REG, N("version"), (void *)version,
114 KFSstring, VREG, READ_MODE },
115 };
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 };
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 */
126 { DT_DIR, N("."), 0, KFSipsecsadir, VDIR, DIR_MODE },
127 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
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 */
132 { DT_DIR, N("."), 0, KFSipsecspdir, VDIR, DIR_MODE },
133 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
134 };
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 };
139 #endif
140 #undef N
141 SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
142 SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
143 int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
144 const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
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]);
148 int nkern_dirs = 4; /* 2 extra subdirs */
149 #else
150 int nkern_dirs = 2;
151 #endif
153 int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
154 int kernfs_try_xread(kfstype, const struct kernfs_node *, int, char **,
155 size_t, size_t *, int);
156 int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
157 size_t, int);
159 static int kernfs_default_xread(void *v);
160 static int kernfs_default_xwrite(void *v);
161 static int kernfs_default_fileop_getattr(void *);
163 /* must include all fileop's */
164 const struct kernfs_fileop kernfs_default_fileops[] = {
165 { .kf_fileop = KERNFS_XREAD },
166 { .kf_fileop = KERNFS_XWRITE },
167 { .kf_fileop = KERNFS_FILEOP_OPEN },
168 { .kf_fileop = KERNFS_FILEOP_GETATTR,
169 .kf_genop = {kernfs_default_fileop_getattr} },
170 { .kf_fileop = KERNFS_FILEOP_IOCTL },
171 { .kf_fileop = KERNFS_FILEOP_MMAP },
172 { .kf_fileop = KERNFS_FILEOP_CLOSE },
173 { .kf_fileop = KERNFS_FILEOP_READ, .kf_genop = {kernfs_default_xread} },
174 { .kf_fileop = KERNFS_FILEOP_WRITE, .kf_genop = {kernfs_default_xwrite} },
175 };
177 int kernfs_lookup __P((void *));
178 #define kernfs_create genfs_eopnotsupp
179 #define kernfs_mknod genfs_eopnotsupp
180 int kernfs_open __P((void *));
181 int kernfs_close __P((void *));
182 int kernfs_access __P((void *));
183 int kernfs_getattr __P((void *));
184 int kernfs_setattr __P((void *));
185 int kernfs_read __P((void *));
186 int kernfs_write __P((void *));
187 #define kernfs_fcntl genfs_fcntl
188 int kernfs_ioctl __P((void *));
189 #define kernfs_poll genfs_poll
190 #define kernfs_revoke genfs_revoke
191 int kernfs_mmap __P((void *));
192 #define kernfs_fsync genfs_nullop
193 #define kernfs_seek genfs_nullop
194 #define kernfs_remove genfs_eopnotsupp
195 int kernfs_link __P((void *));
196 #define kernfs_rename genfs_eopnotsupp
197 #define kernfs_mkdir genfs_eopnotsupp
198 #define kernfs_rmdir genfs_eopnotsupp
199 int kernfs_symlink __P((void *));
200 int kernfs_readdir __P((void *));
201 #define kernfs_readlink genfs_eopnotsupp
202 #define kernfs_abortop genfs_abortop
203 int kernfs_inactive __P((void *));
204 int kernfs_reclaim __P((void *));
205 #define kernfs_lock genfs_lock
206 #define kernfs_unlock genfs_unlock
207 #define kernfs_bmap genfs_badop
208 #define kernfs_strategy genfs_badop
209 int kernfs_print __P((void *));
210 #define kernfs_islocked genfs_islocked
211 int kernfs_pathconf __P((void *));
212 #define kernfs_advlock genfs_einval
213 #define kernfs_blkatoff genfs_eopnotsupp
214 #define kernfs_valloc genfs_eopnotsupp
215 #define kernfs_vfree genfs_nullop
216 #define kernfs_truncate genfs_eopnotsupp
217 #define kernfs_update genfs_nullop
218 #define kernfs_bwrite genfs_eopnotsupp
219 #define kernfs_putpages genfs_putpages
221 static int kernfs_xread __P((struct kernfs_node *, int, char **, size_t, size_t *));
222 static int kernfs_xwrite __P((const struct kernfs_node *, char *, size_t));
224 int (**kernfs_vnodeop_p) __P((void *));
225 const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
226 { &vop_default_desc, vn_default_error },
227 { &vop_lookup_desc, kernfs_lookup }, /* lookup */
228 { &vop_create_desc, kernfs_create }, /* create */
229 { &vop_mknod_desc, kernfs_mknod }, /* mknod */
230 { &vop_open_desc, kernfs_open }, /* open */
231 { &vop_close_desc, kernfs_close }, /* close */
232 { &vop_access_desc, kernfs_access }, /* access */
233 { &vop_getattr_desc, kernfs_getattr }, /* getattr */
234 { &vop_setattr_desc, kernfs_setattr }, /* setattr */
235 { &vop_read_desc, kernfs_read }, /* read */
236 { &vop_write_desc, kernfs_write }, /* write */
237 { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */
238 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
239 { &vop_poll_desc, kernfs_poll }, /* poll */
240 { &vop_revoke_desc, kernfs_revoke }, /* revoke */
241 { &vop_mmap_desc, kernfs_mmap }, /* mmap */
242 { &vop_fsync_desc, kernfs_fsync }, /* fsync */
243 { &vop_seek_desc, kernfs_seek }, /* seek */
244 { &vop_remove_desc, kernfs_remove }, /* remove */
245 { &vop_link_desc, kernfs_link }, /* link */
246 { &vop_rename_desc, kernfs_rename }, /* rename */
247 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
248 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
249 { &vop_symlink_desc, kernfs_symlink }, /* symlink */
250 { &vop_readdir_desc, kernfs_readdir }, /* readdir */
251 { &vop_readlink_desc, kernfs_readlink }, /* readlink */
252 { &vop_abortop_desc, kernfs_abortop }, /* abortop */
253 { &vop_inactive_desc, kernfs_inactive }, /* inactive */
254 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
255 { &vop_lock_desc, kernfs_lock }, /* lock */
256 { &vop_unlock_desc, kernfs_unlock }, /* unlock */
257 { &vop_bmap_desc, kernfs_bmap }, /* bmap */
258 { &vop_strategy_desc, kernfs_strategy }, /* strategy */
259 { &vop_print_desc, kernfs_print }, /* print */
260 { &vop_islocked_desc, kernfs_islocked }, /* islocked */
261 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */
262 { &vop_advlock_desc, kernfs_advlock }, /* advlock */
263 { &vop_blkatoff_desc, kernfs_blkatoff }, /* blkatoff */
264 { &vop_valloc_desc, kernfs_valloc }, /* valloc */
265 { &vop_vfree_desc, kernfs_vfree }, /* vfree */
266 { &vop_truncate_desc, kernfs_truncate }, /* truncate */
267 { &vop_update_desc, kernfs_update }, /* update */
268 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
269 { &vop_putpages_desc, kernfs_putpages }, /* putpages */
270 { NULL, NULL }
271 };
272 const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
273 { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
275 static __inline int
276 kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
277 {
278 if (a->kf_type < b->kf_type)
279 return -1;
280 if (a->kf_type > b->kf_type)
281 return 1;
282 if (a->kf_fileop < b->kf_fileop)
283 return -1;
284 if (a->kf_fileop > b->kf_fileop)
285 return 1;
286 return (0);
287 }
289 SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
290 SPLAY_INITIALIZER(kfsfileoptree);
291 SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
292 SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
294 kfstype
295 kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
296 {
297 static u_char nextfreetype = KFSlasttype;
298 struct kernfs_fileop *dkf, *fkf, skf;
299 int i;
301 /* XXX need to keep track of dkf's memory if we support
302 deallocating types */
303 dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
304 memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
306 for (i = 0; i < sizeof(kernfs_default_fileops) /
307 sizeof(kernfs_default_fileops[0]); i++) {
308 dkf[i].kf_type = nextfreetype;
309 SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
310 }
312 for (i = 0; i < nkf; i++) {
313 skf.kf_type = nextfreetype;
314 skf.kf_fileop = kf[i].kf_fileop;
315 if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
316 fkf->kf_genop = kf[i].kf_genop;
317 }
319 return nextfreetype++;
320 }
322 int
323 kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
324 {
325 const struct kernfs_fileop *kf;
326 struct kernfs_fileop skf;
328 skf.kf_type = type;
329 skf.kf_fileop = fileop;
330 kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
331 if (kf == NULL)
332 kf = &kernfs_default_fileops[fileop];
333 if (kf->kf_vop)
334 return kf->kf_vop(v);
335 return error;
336 }
338 int
339 kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, int off,
340 char **bufp, size_t len, size_t *wrlen, int error)
341 {
342 const struct kernfs_fileop *kf;
343 struct kernfs_fileop skf;
345 skf.kf_type = type;
346 skf.kf_fileop = KERNFS_XREAD;
347 kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
348 if (kf == NULL)
349 kf = &kernfs_default_fileops[KERNFS_XREAD];
350 if (kf->kf_xread)
351 return kf->kf_xread(kfs, off, bufp, len, wrlen);
352 *wrlen = 0;
353 return error;
354 }
356 int
357 kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *buf,
358 size_t len, int error)
359 {
360 const struct kernfs_fileop *kf;
361 struct kernfs_fileop skf;
363 skf.kf_type = type;
364 skf.kf_fileop = KERNFS_XWRITE;
365 kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf);
366 if (kf == NULL)
367 kf = &kernfs_default_fileops[KERNFS_XWRITE];
368 if (kf->kf_xwrite)
369 return kf->kf_xwrite(kfs, buf, len);
370 return error;
371 }
373 int
374 kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
375 {
376 struct kernfs_subdir *ks, *parent;
378 if (pkt == NULL) {
379 SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
380 nkern_targets++;
381 if (dkt->dkt_kt.kt_vtype == VDIR)
382 nkern_dirs++;
383 } else {
384 parent = (struct kernfs_subdir *)pkt->kt_data;
385 SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
386 parent->ks_nentries++;
387 if (dkt->dkt_kt.kt_vtype == VDIR)
388 parent->ks_dirs++;
389 }
390 if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
391 ks = malloc(sizeof(struct kernfs_subdir),
392 M_TEMP, M_WAITOK);
393 SIMPLEQ_INIT(&ks->ks_entries);
394 ks->ks_nentries = 2; /* . and .. */
395 ks->ks_dirs = 2;
396 ks->ks_parent = pkt ? pkt : &kern_targets[0];
397 dkt->dkt_kt.kt_data = ks;
398 }
399 return 0;
400 }
402 static int
403 kernfs_xread(kfs, off, bufp, len, wrlen)
404 struct kernfs_node *kfs;
405 int off;
406 char **bufp;
407 size_t len;
408 size_t *wrlen;
409 {
410 const struct kern_target *kt;
411 #ifdef IPSEC
412 struct mbuf *m;
413 #endif
415 kt = kfs->kfs_kt;
417 switch (kfs->kfs_type) {
418 case KFStime: {
419 struct timeval tv;
421 microtime(&tv);
422 snprintf(*bufp, len, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
423 break;
424 }
426 case KFSint: {
427 int *ip = kt->kt_data;
429 snprintf(*bufp, len, "%d\n", *ip);
430 break;
431 }
433 case KFSstring: {
434 char *cp = kt->kt_data;
436 *bufp = cp;
437 break;
438 }
440 case KFSmsgbuf: {
441 long n;
443 /*
444 * deal with cases where the message buffer has
445 * become corrupted.
446 */
447 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
448 msgbufenabled = 0;
449 return (ENXIO);
450 }
452 /*
453 * Note that reads of /kern/msgbuf won't necessarily yield
454 * consistent results, if the message buffer is modified
455 * while the read is in progress. The worst that can happen
456 * is that incorrect data will be read. There's no way
457 * that this can crash the system unless the values in the
458 * message buffer header are corrupted, but that'll cause
459 * the system to die anyway.
460 */
461 if (off >= msgbufp->msg_bufs) {
462 *wrlen = 0;
463 return (0);
464 }
465 n = msgbufp->msg_bufx + off;
466 if (n >= msgbufp->msg_bufs)
467 n -= msgbufp->msg_bufs;
468 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
469 *bufp = msgbufp->msg_bufc + n;
470 *wrlen = len;
471 return (0);
472 }
474 case KFShostname: {
475 char *cp = hostname;
476 int xlen = hostnamelen;
478 if (xlen >= (len - 2))
479 return (EINVAL);
481 memcpy(*bufp, cp, xlen);
482 (*bufp)[xlen] = '\n';
483 (*bufp)[xlen+1] = '\0';
484 len = strlen(*bufp);
485 break;
486 }
488 case KFSavenrun:
489 averunnable.fscale = FSCALE;
490 snprintf(*bufp, len, "%d %d %d %ld\n",
491 averunnable.ldavg[0], averunnable.ldavg[1],
492 averunnable.ldavg[2], averunnable.fscale);
493 break;
495 #ifdef IPSEC
496 case KFSipsecsa:
497 /*
498 * Note that SA configuration could be changed during the
499 * read operation, resulting in garbled output.
500 */
501 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
502 if (!m)
503 return (ENOBUFS);
504 if (off >= m->m_pkthdr.len) {
505 *wrlen = 0;
506 m_freem(m);
507 return (0);
508 }
509 if (len > m->m_pkthdr.len - off)
510 len = m->m_pkthdr.len - off;
511 m_copydata(m, off, len, *bufp);
512 *wrlen = len;
513 m_freem(m);
514 return (0);
516 case KFSipsecsp:
517 /*
518 * Note that SP configuration could be changed during the
519 * read operation, resulting in garbled output.
520 */
521 if (!kfs->kfs_v) {
522 struct secpolicy *sp;
524 sp = key_getspbyid(kfs->kfs_value);
525 if (sp)
526 kfs->kfs_v = sp;
527 else
528 return (ENOENT);
529 }
530 m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
531 SADB_X_SPDGET, 0, 0);
532 if (!m)
533 return (ENOBUFS);
534 if (off >= m->m_pkthdr.len) {
535 *wrlen = 0;
536 m_freem(m);
537 return (0);
538 }
539 if (len > m->m_pkthdr.len - off)
540 len = m->m_pkthdr.len - off;
541 m_copydata(m, off, len, *bufp);
542 *wrlen = len;
543 m_freem(m);
544 return (0);
545 #endif
547 default:
548 return kernfs_try_xread(kfs->kfs_type, kfs, off, bufp, len,
549 wrlen, 0);
550 }
552 len = strlen(*bufp);
553 if (len <= off)
554 *wrlen = 0;
555 else {
556 *bufp += off;
557 *wrlen = len - off;
558 }
559 return (0);
560 }
562 static int
563 kernfs_xwrite(kfs, buf, len)
564 const struct kernfs_node *kfs;
565 char *buf;
566 size_t len;
567 {
569 switch (kfs->kfs_type) {
570 case KFShostname:
571 if (buf[len-1] == '\n')
572 --len;
573 memcpy(hostname, buf, len);
574 hostname[len] = '\0';
575 hostnamelen = (size_t) len;
576 return (0);
578 default:
579 return kernfs_try_xwrite(kfs->kfs_type, kfs, buf, len, EIO);
580 }
581 }
584 /*
585 * vp is the current namei directory
586 * ndp is the name to locate in that directory...
587 */
588 int
589 kernfs_lookup(v)
590 void *v;
591 {
592 struct vop_lookup_args /* {
593 struct vnode * a_dvp;
594 struct vnode ** a_vpp;
595 struct componentname * a_cnp;
596 } */ *ap = v;
597 struct componentname *cnp = ap->a_cnp;
598 struct vnode **vpp = ap->a_vpp;
599 struct vnode *dvp = ap->a_dvp;
600 const char *pname = cnp->cn_nameptr;
601 const struct kernfs_node *kfs;
602 const struct kern_target *kt;
603 const struct dyn_kern_target *dkt;
604 const struct kernfs_subdir *ks;
605 int error, i, wantpunlock;
606 #ifdef IPSEC
607 char *ep;
608 u_int32_t id;
609 #endif
611 *vpp = NULLVP;
612 cnp->cn_flags &= ~PDIRUNLOCK;
614 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
615 return (EROFS);
617 if (cnp->cn_namelen == 1 && *pname == '.') {
618 *vpp = dvp;
619 VREF(dvp);
620 return (0);
621 }
623 wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
624 kfs = VTOKERN(dvp);
625 switch (kfs->kfs_type) {
626 case KFSkern:
627 /*
628 * Shouldn't get here with .. in the root node.
629 */
630 if (cnp->cn_flags & ISDOTDOT)
631 return (EIO);
633 for (i = 0; i < static_nkern_targets; i++) {
634 kt = &kern_targets[i];
635 if (cnp->cn_namelen == kt->kt_namlen &&
636 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
637 goto found;
638 }
639 SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
640 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
641 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
642 kt = &dkt->dkt_kt;
643 goto found;
644 }
645 }
646 break;
648 found:
649 error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
650 if ((error == 0) && wantpunlock) {
651 VOP_UNLOCK(dvp, 0);
652 cnp->cn_flags |= PDIRUNLOCK;
653 }
654 return (error);
656 case KFSsubdir:
657 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
658 if (cnp->cn_flags & ISDOTDOT) {
659 kt = ks->ks_parent;
660 goto found;
661 }
663 SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
664 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
665 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
666 kt = &dkt->dkt_kt;
667 goto found;
668 }
669 }
670 break;
672 #ifdef IPSEC
673 case KFSipsecsadir:
674 if (cnp->cn_flags & ISDOTDOT) {
675 kt = &kern_targets[0];
676 goto found;
677 }
679 for (i = 2; i < nipsecsa_targets; i++) {
680 kt = &ipsecsa_targets[i];
681 if (cnp->cn_namelen == kt->kt_namlen &&
682 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
683 goto found;
684 }
686 ep = NULL;
687 id = strtoul(pname, &ep, 10);
688 if (!ep || *ep || ep == pname)
689 break;
691 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
692 if ((error == 0) && wantpunlock) {
693 VOP_UNLOCK(dvp, 0);
694 cnp->cn_flags |= PDIRUNLOCK;
695 }
696 return (error);
698 case KFSipsecspdir:
699 if (cnp->cn_flags & ISDOTDOT) {
700 kt = &kern_targets[0];
701 goto found;
702 }
704 for (i = 2; i < nipsecsp_targets; i++) {
705 kt = &ipsecsp_targets[i];
706 if (cnp->cn_namelen == kt->kt_namlen &&
707 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
708 goto found;
709 }
711 ep = NULL;
712 id = strtoul(pname, &ep, 10);
713 if (!ep || *ep || ep == pname)
714 break;
716 error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
717 if ((error == 0) && wantpunlock) {
718 VOP_UNLOCK(dvp, 0);
719 cnp->cn_flags |= PDIRUNLOCK;
720 }
721 return (error);
722 #endif
724 default:
725 return (ENOTDIR);
726 }
728 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
729 }
731 int
732 kernfs_open(v)
733 void *v;
734 {
735 struct vop_open_args /* {
736 struct vnode *a_vp;
737 int a_mode;
738 struct ucred *a_cred;
739 struct proc *a_p;
740 } */ *ap = v;
741 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
742 #ifdef IPSEC
743 struct mbuf *m;
744 struct secpolicy *sp;
745 #endif
747 switch (kfs->kfs_type) {
748 #ifdef IPSEC
749 case KFSipsecsa:
750 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
751 if (m) {
752 m_freem(m);
753 return (0);
754 } else
755 return (ENOENT);
757 case KFSipsecsp:
758 sp = key_getspbyid(kfs->kfs_value);
759 if (sp) {
760 kfs->kfs_v = sp;
761 return (0);
762 } else
763 return (ENOENT);
764 #endif
766 default:
767 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
768 v, 0);
769 }
770 }
772 int
773 kernfs_close(v)
774 void *v;
775 {
776 struct vop_close_args /* {
777 struct vnode *a_vp;
778 int a_fflag;
779 struct ucred *a_cred;
780 struct proc *a_p;
781 } */ *ap = v;
782 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
784 switch (kfs->kfs_type) {
785 #ifdef IPSEC
786 case KFSipsecsp:
787 key_freesp((struct secpolicy *)kfs->kfs_v);
788 break;
789 #endif
791 default:
792 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
793 v, 0);
794 }
796 return (0);
797 }
799 int
800 kernfs_access(v)
801 void *v;
802 {
803 struct vop_access_args /* {
804 struct vnode *a_vp;
805 int a_mode;
806 struct ucred *a_cred;
807 struct proc *a_p;
808 } */ *ap = v;
809 struct vattr va;
810 int error;
812 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0)
813 return (error);
815 return (vaccess(va.va_type, va.va_mode, va.va_uid, va.va_gid,
816 ap->a_mode, ap->a_cred));
817 }
819 static int
820 kernfs_default_fileop_getattr(v)
821 void *v;
822 {
823 struct vop_getattr_args /* {
824 struct vnode *a_vp;
825 struct vattr *a_vap;
826 struct ucred *a_cred;
827 struct proc *a_p;
828 } */ *ap = v;
829 struct vattr *vap = ap->a_vap;
831 vap->va_nlink = 1;
832 vap->va_bytes = vap->va_size = 0;
834 return 0;
835 }
837 int
838 kernfs_getattr(v)
839 void *v;
840 {
841 struct vop_getattr_args /* {
842 struct vnode *a_vp;
843 struct vattr *a_vap;
844 struct ucred *a_cred;
845 struct proc *a_p;
846 } */ *ap = v;
847 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
848 struct kernfs_subdir *ks;
849 struct vattr *vap = ap->a_vap;
850 int error = 0;
851 char strbuf[KSTRING], *buf;
852 size_t nread, total;
854 VATTR_NULL(vap);
855 vap->va_type = ap->a_vp->v_type;
856 vap->va_uid = 0;
857 vap->va_gid = 0;
858 vap->va_mode = kfs->kfs_mode;
859 vap->va_fileid = kfs->kfs_fileno;
860 vap->va_flags = 0;
861 vap->va_size = 0;
862 vap->va_blocksize = DEV_BSIZE;
863 /*
864 * Make all times be current TOD, except for the "boottime" node.
865 * Avoid microtime(9), it's slow.
866 * We don't guard the read from time(9) with splclock(9) since we
867 * don't actually need to be THAT sure the access is atomic.
868 */
869 if (kfs->kfs_kt && kfs->kfs_kt->kt_namlen == 8 &&
870 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
871 TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_ctime);
872 } else {
873 TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);
874 }
875 vap->va_atime = vap->va_mtime = vap->va_ctime;
876 vap->va_gen = 0;
877 vap->va_flags = 0;
878 vap->va_rdev = 0;
879 vap->va_bytes = 0;
881 switch (kfs->kfs_type) {
882 case KFSkern:
883 vap->va_nlink = nkern_dirs;
884 vap->va_bytes = vap->va_size = DEV_BSIZE;
885 break;
887 case KFSroot:
888 vap->va_nlink = 1;
889 vap->va_bytes = vap->va_size = DEV_BSIZE;
890 break;
892 case KFSsubdir:
893 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
894 vap->va_nlink = ks->ks_dirs;
895 vap->va_bytes = vap->va_size = DEV_BSIZE;
896 break;
898 case KFSnull:
899 case KFStime:
900 case KFSint:
901 case KFSstring:
902 case KFShostname:
903 case KFSavenrun:
904 case KFSdevice:
905 case KFSmsgbuf:
906 #ifdef IPSEC
907 case KFSipsecsa:
908 case KFSipsecsp:
909 #endif
910 vap->va_nlink = 1;
911 total = 0;
912 do {
913 buf = strbuf;
914 error = kernfs_xread(kfs, total, &buf,
915 sizeof(strbuf), &nread);
916 total += nread;
917 } while (error == 0 && nread != 0);
918 vap->va_bytes = vap->va_size = total;
919 break;
921 #ifdef IPSEC
922 case KFSipsecsadir:
923 case KFSipsecspdir:
924 vap->va_nlink = 2;
925 vap->va_bytes = vap->va_size = DEV_BSIZE;
926 break;
927 #endif
929 default:
930 error = kernfs_try_fileop(kfs->kfs_type,
931 KERNFS_FILEOP_GETATTR, v, EINVAL);
932 break;
933 }
935 return (error);
936 }
938 /*ARGSUSED*/
939 int
940 kernfs_setattr(v)
941 void *v;
942 {
944 /*
945 * Silently ignore attribute changes.
946 * This allows for open with truncate to have no
947 * effect until some data is written. I want to
948 * do it this way because all writes are atomic.
949 */
950 return (0);
951 }
953 static int
954 kernfs_default_xread(v)
955 void *v;
956 {
957 struct vop_read_args /* {
958 struct vnode *a_vp;
959 struct uio *a_uio;
960 int a_ioflag;
961 struct ucred *a_cred;
962 } */ *ap = v;
963 struct uio *uio = ap->a_uio;
964 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
965 char strbuf[KSTRING], *buf;
966 off_t off;
967 size_t len;
968 int error;
970 if (ap->a_vp->v_type == VDIR)
971 return (EOPNOTSUPP);
973 off = uio->uio_offset;
974 buf = strbuf;
975 if ((error = kernfs_xread(kfs, off, &buf, sizeof(strbuf), &len)) == 0)
976 error = uiomove(buf, len, uio);
977 return (error);
978 }
980 int
981 kernfs_read(v)
982 void *v;
983 {
984 struct vop_read_args /* {
985 struct vnode *a_vp;
986 struct uio *a_uio;
987 int a_ioflag;
988 struct ucred *a_cred;
989 } */ *ap = v;
990 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
992 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v, 0);
993 }
995 static int
996 kernfs_default_xwrite(v)
997 void *v;
998 {
999 struct vop_write_args /* {
1000 struct vnode *a_vp;
1001 struct uio *a_uio;
1002 int a_ioflag;
1003 struct ucred *a_cred;
1004 } */ *ap = v;
1005 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1006 struct uio *uio = ap->a_uio;
1007 int error, xlen;
1008 char strbuf[KSTRING];
1010 if (uio->uio_offset != 0)
1011 return (EINVAL);
1013 xlen = min(uio->uio_resid, KSTRING-1);
1014 if ((error = uiomove(strbuf, xlen, uio)) != 0)
1015 return (error);
1017 if (uio->uio_resid != 0)
1018 return (EIO);
1020 strbuf[xlen] = '\0';
1021 xlen = strlen(strbuf);
1022 return (kernfs_xwrite(kfs, strbuf, xlen));
1025 int
1026 kernfs_write(v)
1027 void *v;
1029 struct vop_write_args /* {
1030 struct vnode *a_vp;
1031 struct uio *a_uio;
1032 int a_ioflag;
1033 struct ucred *a_cred;
1034 } */ *ap = v;
1035 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1037 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 0);
1040 int
1041 kernfs_ioctl(v)
1042 void *v;
1044 struct vop_ioctl_args /* {
1045 const struct vnodeop_desc *a_desc;
1046 struct vnode *a_vp;
1047 u_long a_command;
1048 void *a_data;
1049 int a_fflag;
1050 struct ucred *a_cred;
1051 struct proc *a_p;
1052 } */ *ap = v;
1053 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1055 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
1056 EPASSTHROUGH);
1059 int
1060 kernfs_mmap(v)
1061 void *v;
1063 struct vop_mmap_args /* {
1064 const struct vnodeop_desc *a_desc;
1065 struct vnode *a_vp;
1066 int a_fflags;
1067 struct ucred *a_cred;
1068 struct proc *a_p;
1069 } */ *ap = v;
1070 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1072 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_MMAP, v, 0);
1075 static int
1076 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
1077 u_int32_t value, struct vop_readdir_args *ap)
1079 struct kernfs_node *kfs;
1080 struct vnode *vp;
1081 int error;
1083 if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
1084 value)) != 0)
1085 return error;
1086 if (kt->kt_tag == KFSdevice) {
1087 struct vattr va;
1088 if ((error = VOP_GETATTR(vp, &va, ap->a_cred,
1089 ap->a_uio->uio_segflg == UIO_USERSPACE ?
1090 ap->a_uio->uio_procp : &proc0)) != 0)
1091 return (error);
1092 d->d_fileno = va.va_fileid;
1093 } else {
1094 kfs = VTOKERN(vp);
1095 d->d_fileno = kfs->kfs_fileno;
1097 vput(vp);
1098 return 0;
1101 static int
1102 kernfs_setdirentfileno(struct dirent *d, off_t entry,
1103 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
1104 const struct kern_target *kt, struct vop_readdir_args *ap)
1106 const struct kern_target *ikt;
1107 int error;
1109 switch (entry) {
1110 case 0:
1111 d->d_fileno = thisdir_kfs->kfs_fileno;
1112 return 0;
1113 case 1:
1114 ikt = parent_kt;
1115 break;
1116 default:
1117 ikt = kt;
1118 break;
1120 if (ikt != thisdir_kfs->kfs_kt) {
1121 if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
1122 return error;
1123 } else
1124 d->d_fileno = thisdir_kfs->kfs_fileno;
1125 return 0;
1128 int
1129 kernfs_readdir(v)
1130 void *v;
1132 struct vop_readdir_args /* {
1133 struct vnode *a_vp;
1134 struct uio *a_uio;
1135 struct ucred *a_cred;
1136 int *a_eofflag;
1137 off_t **a_cookies;
1138 int a_*ncookies;
1139 } */ *ap = v;
1140 struct uio *uio = ap->a_uio;
1141 struct dirent d;
1142 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1143 const struct kern_target *kt;
1144 const struct dyn_kern_target *dkt = NULL;
1145 const struct kernfs_subdir *ks;
1146 off_t i, j;
1147 int error;
1148 off_t *cookies = NULL;
1149 int ncookies = 0, n;
1150 #ifdef IPSEC
1151 struct secasvar *sav, *sav2;
1152 struct secpolicy *sp;
1153 #endif
1155 if (uio->uio_resid < UIO_MX)
1156 return (EINVAL);
1157 if (uio->uio_offset < 0)
1158 return (EINVAL);
1160 error = 0;
1161 i = uio->uio_offset;
1162 memset(&d, 0, sizeof(d));
1163 d.d_reclen = UIO_MX;
1164 ncookies = uio->uio_resid / UIO_MX;
1166 switch (kfs->kfs_type) {
1167 case KFSkern:
1168 if (i >= nkern_targets)
1169 return (0);
1171 if (ap->a_ncookies) {
1172 ncookies = min(ncookies, (nkern_targets - i));
1173 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1174 M_WAITOK);
1175 *ap->a_cookies = cookies;
1178 n = 0;
1179 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1180 if (i < static_nkern_targets)
1181 kt = &kern_targets[i];
1182 else {
1183 if (dkt == NULL) {
1184 dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
1185 for (j = static_nkern_targets; j < i &&
1186 dkt != NULL; j++)
1187 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1188 if (j != i)
1189 break;
1190 } else {
1191 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1192 if (dkt == NULL)
1193 break;
1195 kt = &dkt->dkt_kt;
1197 if (kt->kt_tag == KFSdevice) {
1198 dev_t *dp = kt->kt_data;
1199 struct vnode *fvp;
1201 if (*dp == NODEV ||
1202 !vfinddev(*dp, kt->kt_vtype, &fvp))
1203 continue;
1205 d.d_namlen = kt->kt_namlen;
1206 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1207 &kern_targets[0], kt, ap)) != 0)
1208 break;
1209 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1210 d.d_type = kt->kt_type;
1211 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1212 break;
1213 if (cookies)
1214 *cookies++ = i + 1;
1215 n++;
1217 ncookies = n;
1218 break;
1220 case KFSroot:
1221 if (i >= 2)
1222 return 0;
1224 if (ap->a_ncookies) {
1225 ncookies = min(ncookies, (2 - i));
1226 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1227 M_WAITOK);
1228 *ap->a_cookies = cookies;
1231 n = 0;
1232 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1233 kt = &kern_targets[i];
1234 d.d_namlen = kt->kt_namlen;
1235 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
1236 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1237 d.d_type = kt->kt_type;
1238 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1239 break;
1240 if (cookies)
1241 *cookies++ = i + 1;
1242 n++;
1244 ncookies = n;
1245 break;
1247 case KFSsubdir:
1248 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
1249 if (i >= ks->ks_nentries)
1250 return (0);
1252 if (ap->a_ncookies) {
1253 ncookies = min(ncookies, (ks->ks_nentries - i));
1254 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1255 M_WAITOK);
1256 *ap->a_cookies = cookies;
1259 dkt = SIMPLEQ_FIRST(&ks->ks_entries);
1260 for (j = 0; j < i && dkt != NULL; j++)
1261 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1262 n = 0;
1263 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
1264 if (i < 2)
1265 kt = &subdir_targets[i];
1266 else {
1267 /* check if ks_nentries lied to us */
1268 if (dkt == NULL)
1269 break;
1270 kt = &dkt->dkt_kt;
1271 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1273 if (kt->kt_tag == KFSdevice) {
1274 dev_t *dp = kt->kt_data;
1275 struct vnode *fvp;
1277 if (*dp == NODEV ||
1278 !vfinddev(*dp, kt->kt_vtype, &fvp))
1279 continue;
1281 d.d_namlen = kt->kt_namlen;
1282 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1283 ks->ks_parent, kt, ap)) != 0)
1284 break;
1285 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1286 d.d_type = kt->kt_type;
1287 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1288 break;
1289 if (cookies)
1290 *cookies++ = i + 1;
1291 n++;
1293 ncookies = n;
1294 break;
1296 #ifdef IPSEC
1297 case KFSipsecsadir:
1298 /* count SA in the system */
1299 n = 0;
1300 TAILQ_FOREACH(sav, &satailq, tailq) {
1301 for (sav2 = TAILQ_FIRST(&satailq);
1302 sav2 != sav;
1303 sav2 = TAILQ_NEXT(sav2, tailq)) {
1304 if (sav->spi == sav2->spi) {
1305 /* multiple SA with same SPI */
1306 break;
1309 if (sav == sav2 || sav->spi != sav2->spi)
1310 n++;
1313 if (i >= nipsecsa_targets + n)
1314 return (0);
1316 if (ap->a_ncookies) {
1317 ncookies = min(ncookies, (n - i));
1318 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1319 M_WAITOK);
1320 *ap->a_cookies = cookies;
1323 n = 0;
1324 for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
1325 kt = &ipsecsa_targets[i];
1326 d.d_namlen = kt->kt_namlen;
1327 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1328 &kern_targets[0], kt, ap)) != 0)
1329 break;
1330 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1331 d.d_type = kt->kt_type;
1332 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1333 break;
1334 if (cookies)
1335 *cookies++ = i + 1;
1336 n++;
1338 if (error) {
1339 ncookies = n;
1340 break;
1343 TAILQ_FOREACH(sav, &satailq, tailq) {
1344 for (sav2 = TAILQ_FIRST(&satailq);
1345 sav2 != sav;
1346 sav2 = TAILQ_NEXT(sav2, tailq)) {
1347 if (sav->spi == sav2->spi) {
1348 /* multiple SA with same SPI */
1349 break;
1352 if (sav != sav2 && sav->spi == sav2->spi)
1353 continue;
1354 if (uio->uio_resid < UIO_MX)
1355 break;
1356 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
1357 sav->spi, ap)) != 0)
1358 break;
1359 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1360 "%u", ntohl(sav->spi));
1361 d.d_type = DT_REG;
1362 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1363 break;
1364 if (cookies)
1365 *cookies++ = i + 1;
1366 n++;
1367 i++;
1369 ncookies = n;
1370 break;
1372 case KFSipsecspdir:
1373 /* count SP in the system */
1374 n = 0;
1375 TAILQ_FOREACH(sp, &sptailq, tailq)
1376 n++;
1378 if (i >= nipsecsp_targets + n)
1379 return (0);
1381 if (ap->a_ncookies) {
1382 ncookies = min(ncookies, (n - i));
1383 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1384 M_WAITOK);
1385 *ap->a_cookies = cookies;
1388 n = 0;
1389 for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
1390 kt = &ipsecsp_targets[i];
1391 d.d_namlen = kt->kt_namlen;
1392 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1393 &kern_targets[0], kt, ap)) != 0)
1394 break;
1395 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1396 d.d_type = kt->kt_type;
1397 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1398 break;
1399 if (cookies)
1400 *cookies++ = i + 1;
1401 n++;
1403 if (error) {
1404 ncookies = n;
1405 break;
1408 TAILQ_FOREACH(sp, &sptailq, tailq) {
1409 if (uio->uio_resid < UIO_MX)
1410 break;
1411 if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
1412 sp->id, ap)) != 0)
1413 break;
1414 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1415 "%u", sp->id);
1416 d.d_type = DT_REG;
1417 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1418 break;
1419 if (cookies)
1420 *cookies++ = i + 1;
1421 n++;
1422 i++;
1424 ncookies = n;
1425 break;
1426 #endif
1428 default:
1429 error = ENOTDIR;
1430 break;
1433 if (ap->a_ncookies) {
1434 if (error) {
1435 if (cookies)
1436 free(*ap->a_cookies, M_TEMP);
1437 *ap->a_ncookies = 0;
1438 *ap->a_cookies = NULL;
1439 } else
1440 *ap->a_ncookies = ncookies;
1443 uio->uio_offset = i;
1444 return (error);
1447 int
1448 kernfs_inactive(v)
1449 void *v;
1451 struct vop_inactive_args /* {
1452 struct vnode *a_vp;
1453 struct proc *a_p;
1454 } */ *ap = v;
1455 struct vnode *vp = ap->a_vp;
1456 const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1457 #ifdef IPSEC
1458 struct mbuf *m;
1459 struct secpolicy *sp;
1460 #endif
1462 VOP_UNLOCK(vp, 0);
1463 switch (kfs->kfs_type) {
1464 #ifdef IPSEC
1465 case KFSipsecsa:
1466 m = key_setdumpsa_spi(htonl(kfs->kfs_value));
1467 if (m)
1468 m_freem(m);
1469 else
1470 vgone(vp);
1471 break;
1472 case KFSipsecsp:
1473 sp = key_getspbyid(kfs->kfs_value);
1474 if (sp)
1475 key_freesp(sp);
1476 else {
1477 /* should never happen as we hold a refcnt */
1478 vgone(vp);
1480 break;
1481 #endif
1482 default:
1483 break;
1485 return (0);
1488 int
1489 kernfs_reclaim(v)
1490 void *v;
1492 struct vop_reclaim_args /* {
1493 struct vnode *a_vp;
1494 } */ *ap = v;
1496 return (kernfs_freevp(ap->a_vp));
1499 /*
1500 * Return POSIX pathconf information applicable to special devices.
1501 */
1502 int
1503 kernfs_pathconf(v)
1504 void *v;
1506 struct vop_pathconf_args /* {
1507 struct vnode *a_vp;
1508 int a_name;
1509 register_t *a_retval;
1510 } */ *ap = v;
1512 switch (ap->a_name) {
1513 case _PC_LINK_MAX:
1514 *ap->a_retval = LINK_MAX;
1515 return (0);
1516 case _PC_MAX_CANON:
1517 *ap->a_retval = MAX_CANON;
1518 return (0);
1519 case _PC_MAX_INPUT:
1520 *ap->a_retval = MAX_INPUT;
1521 return (0);
1522 case _PC_PIPE_BUF:
1523 *ap->a_retval = PIPE_BUF;
1524 return (0);
1525 case _PC_CHOWN_RESTRICTED:
1526 *ap->a_retval = 1;
1527 return (0);
1528 case _PC_VDISABLE:
1529 *ap->a_retval = _POSIX_VDISABLE;
1530 return (0);
1531 case _PC_SYNC_IO:
1532 *ap->a_retval = 1;
1533 return (0);
1534 default:
1535 return (EINVAL);
1537 /* NOTREACHED */
1540 /*
1541 * Print out the contents of a /dev/fd vnode.
1542 */
1543 /* ARGSUSED */
1544 int
1545 kernfs_print(v)
1546 void *v;
1549 printf("tag VT_KERNFS, kernfs vnode\n");
1550 return (0);
1553 int
1554 kernfs_link(v)
1555 void *v;
1557 struct vop_link_args /* {
1558 struct vnode *a_dvp;
1559 struct vnode *a_vp;
1560 struct componentname *a_cnp;
1561 } */ *ap = v;
1563 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1564 vput(ap->a_dvp);
1565 return (EROFS);
1568 int
1569 kernfs_symlink(v)
1570 void *v;
1572 struct vop_symlink_args /* {
1573 struct vnode *a_dvp;
1574 struct vnode **a_vpp;
1575 struct componentname *a_cnp;
1576 struct vattr *a_vap;
1577 char *a_target;
1578 } */ *ap = v;
1580 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1581 vput(ap->a_dvp);
1582 return (EROFS);