kernfs_vnops.c revision 1.52 1 /* $NetBSD: kernfs_vnops.c,v 1.52 1997/09/19 19:14:20 leo Exp $ */
2
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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kernfs_vnops.c 8.9 (Berkeley) 6/15/94
39 */
40
41 /*
42 * Kernel parameter filesystem (/kern)
43 */
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/vmmeter.h>
49 #include <sys/types.h>
50 #include <sys/time.h>
51 #include <sys/proc.h>
52 #include <sys/vnode.h>
53 #include <sys/malloc.h>
54 #include <sys/file.h>
55 #include <sys/stat.h>
56 #include <sys/mount.h>
57 #include <sys/namei.h>
58 #include <sys/buf.h>
59 #include <sys/dirent.h>
60 #include <sys/msgbuf.h>
61
62 #include <miscfs/genfs/genfs.h>
63 #include <miscfs/kernfs/kernfs.h>
64
65 #define KSTRING 256 /* Largest I/O available via this filesystem */
66 #define UIO_MX 32
67
68 #define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH)
69 #define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
70 #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
71
72 struct kern_target kern_targets[] = {
73 /* NOTE: The name must be less than UIO_MX-16 chars in length */
74 #define N(s) sizeof(s)-1, s
75 /* name data tag type ro/rw */
76 { DT_DIR, N("."), 0, KTT_NULL, VDIR, DIR_MODE },
77 { DT_DIR, N(".."), 0, KTT_NULL, VDIR, DIR_MODE },
78 { DT_REG, N("boottime"), &boottime.tv_sec, KTT_INT, VREG, READ_MODE },
79 { DT_REG, N("copyright"), copyright, KTT_STRING, VREG, READ_MODE },
80 { DT_REG, N("hostname"), 0, KTT_HOSTNAME, VREG, WRITE_MODE },
81 { DT_REG, N("hz"), &hz, KTT_INT, VREG, READ_MODE },
82 { DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE },
83 { DT_REG, N("msgbuf"), 0, KTT_MSGBUF, VREG, READ_MODE },
84 { DT_REG, N("pagesize"), &cnt.v_page_size, KTT_INT, VREG, READ_MODE },
85 { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE },
86 #if 0
87 { DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE },
88 #endif
89 { DT_BLK, N("rootdev"), &rootdev, KTT_DEVICE, VBLK, READ_MODE },
90 { DT_CHR, N("rrootdev"), &rrootdev, KTT_DEVICE, VCHR, READ_MODE },
91 { DT_REG, N("time"), 0, KTT_TIME, VREG, READ_MODE },
92 { DT_REG, N("version"), version, KTT_STRING, VREG, READ_MODE },
93 #undef N
94 };
95 static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
96
97 int kernfs_lookup __P((void *));
98 #define kernfs_create genfs_eopnotsupp
99 #define kernfs_mknod genfs_eopnotsupp
100 #define kernfs_open genfs_nullop
101 #define kernfs_close genfs_nullop
102 int kernfs_access __P((void *));
103 int kernfs_getattr __P((void *));
104 int kernfs_setattr __P((void *));
105 int kernfs_read __P((void *));
106 int kernfs_write __P((void *));
107 #define kernfs_ioctl genfs_eopnotsupp
108 #define kernfs_poll genfs_poll
109 #define kernfs_mmap genfs_eopnotsupp
110 #define kernfs_fsync genfs_nullop
111 #define kernfs_seek genfs_nullop
112 #define kernfs_remove genfs_eopnotsupp
113 int kernfs_link __P((void *));
114 #define kernfs_rename genfs_eopnotsupp
115 #define kernfs_mkdir genfs_eopnotsupp
116 #define kernfs_rmdir genfs_eopnotsupp
117 int kernfs_symlink __P((void *));
118 int kernfs_readdir __P((void *));
119 #define kernfs_readlink genfs_eopnotsupp
120 #define kernfs_abortop genfs_abortop
121 int kernfs_inactive __P((void *));
122 int kernfs_reclaim __P((void *));
123 #define kernfs_lock genfs_nullop
124 #define kernfs_unlock genfs_nullop
125 #define kernfs_bmap genfs_badop
126 #define kernfs_strategy genfs_badop
127 int kernfs_print __P((void *));
128 #define kernfs_islocked genfs_nullop
129 int kernfs_pathconf __P((void *));
130 #define kernfs_advlock genfs_eopnotsupp
131 #define kernfs_blkatoff genfs_eopnotsupp
132 #define kernfs_valloc genfs_eopnotsupp
133 #define kernfs_vfree genfs_nullop
134 #define kernfs_truncate genfs_eopnotsupp
135 #define kernfs_update genfs_nullop
136 #define kernfs_bwrite genfs_eopnotsupp
137
138 int kernfs_xread __P((struct kern_target *, int, char **, int));
139 int kernfs_xwrite __P((struct kern_target *, char *, int));
140
141 int (**kernfs_vnodeop_p) __P((void *));
142 struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
143 { &vop_default_desc, vn_default_error },
144 { &vop_lookup_desc, kernfs_lookup }, /* lookup */
145 { &vop_create_desc, kernfs_create }, /* create */
146 { &vop_mknod_desc, kernfs_mknod }, /* mknod */
147 { &vop_open_desc, kernfs_open }, /* open */
148 { &vop_close_desc, kernfs_close }, /* close */
149 { &vop_access_desc, kernfs_access }, /* access */
150 { &vop_getattr_desc, kernfs_getattr }, /* getattr */
151 { &vop_setattr_desc, kernfs_setattr }, /* setattr */
152 { &vop_read_desc, kernfs_read }, /* read */
153 { &vop_write_desc, kernfs_write }, /* write */
154 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
155 { &vop_poll_desc, kernfs_poll }, /* poll */
156 { &vop_mmap_desc, kernfs_mmap }, /* mmap */
157 { &vop_fsync_desc, kernfs_fsync }, /* fsync */
158 { &vop_seek_desc, kernfs_seek }, /* seek */
159 { &vop_remove_desc, kernfs_remove }, /* remove */
160 { &vop_link_desc, kernfs_link }, /* link */
161 { &vop_rename_desc, kernfs_rename }, /* rename */
162 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
163 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
164 { &vop_symlink_desc, kernfs_symlink }, /* symlink */
165 { &vop_readdir_desc, kernfs_readdir }, /* readdir */
166 { &vop_readlink_desc, kernfs_readlink }, /* readlink */
167 { &vop_abortop_desc, kernfs_abortop }, /* abortop */
168 { &vop_inactive_desc, kernfs_inactive }, /* inactive */
169 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
170 { &vop_lock_desc, kernfs_lock }, /* lock */
171 { &vop_unlock_desc, kernfs_unlock }, /* unlock */
172 { &vop_bmap_desc, kernfs_bmap }, /* bmap */
173 { &vop_strategy_desc, kernfs_strategy }, /* strategy */
174 { &vop_print_desc, kernfs_print }, /* print */
175 { &vop_islocked_desc, kernfs_islocked }, /* islocked */
176 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */
177 { &vop_advlock_desc, kernfs_advlock }, /* advlock */
178 { &vop_blkatoff_desc, kernfs_blkatoff }, /* blkatoff */
179 { &vop_valloc_desc, kernfs_valloc }, /* valloc */
180 { &vop_vfree_desc, kernfs_vfree }, /* vfree */
181 { &vop_truncate_desc, kernfs_truncate }, /* truncate */
182 { &vop_update_desc, kernfs_update }, /* update */
183 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
184 { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL }
185 };
186 struct vnodeopv_desc kernfs_vnodeop_opv_desc =
187 { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
188
189 int
190 kernfs_xread(kt, off, bufp, len)
191 struct kern_target *kt;
192 int off;
193 char **bufp;
194 int len;
195 {
196
197 switch (kt->kt_tag) {
198 case KTT_TIME: {
199 struct timeval tv;
200
201 microtime(&tv);
202 sprintf(*bufp, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
203 break;
204 }
205
206 case KTT_INT: {
207 int *ip = kt->kt_data;
208
209 sprintf(*bufp, "%d\n", *ip);
210 break;
211 }
212
213 case KTT_STRING: {
214 char *cp = kt->kt_data;
215
216 *bufp = cp;
217 break;
218 }
219
220 case KTT_MSGBUF: {
221 long n;
222
223 /*
224 * deal with cases where the message buffer has
225 * become corrupted.
226 */
227 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
228 msgbufenabled = 0;
229 return (ENXIO);
230 }
231
232 /*
233 * Note that reads of /kern/msgbuf won't necessarily yield
234 * consistent results, if the message buffer is modified
235 * while the read is in progress. The worst that can happen
236 * is that incorrect data will be read. There's no way
237 * that this can crash the system unless the values in the
238 * message buffer header are corrupted, but that'll cause
239 * the system to die anyway.
240 */
241 if (off >= msgbufp->msg_bufs)
242 return (0);
243 n = msgbufp->msg_bufx + off;
244 if (n >= msgbufp->msg_bufs)
245 n -= msgbufp->msg_bufs;
246 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
247 *bufp = msgbufp->msg_bufc + n;
248 return (len);
249 }
250
251 case KTT_HOSTNAME: {
252 char *cp = hostname;
253 int xlen = hostnamelen;
254
255 if (xlen >= (len-2))
256 return (EINVAL);
257
258 bcopy(cp, *bufp, xlen);
259 (*bufp)[xlen] = '\n';
260 (*bufp)[xlen+1] = '\0';
261 break;
262 }
263
264 case KTT_AVENRUN:
265 averunnable.fscale = FSCALE;
266 sprintf(*bufp, "%d %d %d %ld\n",
267 averunnable.ldavg[0], averunnable.ldavg[1],
268 averunnable.ldavg[2], averunnable.fscale);
269 break;
270
271 default:
272 return (0);
273 }
274
275 len = strlen(*bufp);
276 if (len <= off)
277 return (0);
278 *bufp += off;
279 return (len - off);
280 }
281
282 int
283 kernfs_xwrite(kt, buf, len)
284 struct kern_target *kt;
285 char *buf;
286 int len;
287 {
288
289 switch (kt->kt_tag) {
290 case KTT_HOSTNAME:
291 if (buf[len-1] == '\n')
292 --len;
293 bcopy(buf, hostname, len);
294 hostname[len] = '\0';
295 hostnamelen = len;
296 return (0);
297
298 default:
299 return (EIO);
300 }
301 }
302
303
304 /*
305 * vp is the current namei directory
306 * ndp is the name to locate in that directory...
307 */
308 int
309 kernfs_lookup(v)
310 void *v;
311 {
312 struct vop_lookup_args /* {
313 struct vnode * a_dvp;
314 struct vnode ** a_vpp;
315 struct componentname * a_cnp;
316 } */ *ap = v;
317 struct componentname *cnp = ap->a_cnp;
318 struct vnode **vpp = ap->a_vpp;
319 struct vnode *dvp = ap->a_dvp;
320 const char *pname = cnp->cn_nameptr;
321 struct kern_target *kt;
322 struct vnode *fvp;
323 int error, i;
324
325 #ifdef KERNFS_DIAGNOSTIC
326 printf("kernfs_lookup(%p)\n", ap);
327 printf("kernfs_lookup(dp = %p, vpp = %p, cnp = %p)\n", dvp, vpp, ap->a_cnp);
328 printf("kernfs_lookup(%s)\n", pname);
329 #endif
330
331 *vpp = NULLVP;
332
333 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
334 return (EROFS);
335
336 if (cnp->cn_namelen == 1 && *pname == '.') {
337 *vpp = dvp;
338 VREF(dvp);
339 /*VOP_LOCK(dvp);*/
340 return (0);
341 }
342
343 #if 0
344 if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {
345 *vpp = rootdir;
346 VREF(rootdir);
347 VOP_LOCK(rootdir);
348 return (0);
349 }
350 #endif
351
352 for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) {
353 if (cnp->cn_namelen == kt->kt_namlen &&
354 bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
355 goto found;
356 }
357
358 #ifdef KERNFS_DIAGNOSTIC
359 printf("kernfs_lookup: i = %d, failed", i);
360 #endif
361
362 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
363
364 found:
365 if (kt->kt_tag == KTT_DEVICE) {
366 dev_t *dp = kt->kt_data;
367 loop:
368 if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
369 return (ENOENT);
370 *vpp = fvp;
371 if (vget(fvp, 1))
372 goto loop;
373 return (0);
374 }
375
376 #ifdef KERNFS_DIAGNOSTIC
377 printf("kernfs_lookup: allocate new vnode\n");
378 #endif
379 error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);
380 if (error)
381 return (error);
382
383 MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP,
384 M_WAITOK);
385 VTOKERN(fvp)->kf_kt = kt;
386 fvp->v_type = kt->kt_vtype;
387 *vpp = fvp;
388
389 #ifdef KERNFS_DIAGNOSTIC
390 printf("kernfs_lookup: newvp = %p\n", fvp);
391 #endif
392 return (0);
393 }
394
395 int
396 kernfs_access(v)
397 void *v;
398 {
399 struct vop_access_args /* {
400 struct vnode *a_vp;
401 int a_mode;
402 struct ucred *a_cred;
403 struct proc *a_p;
404 } */ *ap = v;
405 struct vnode *vp = ap->a_vp;
406 mode_t mode;
407
408 if (vp->v_flag & VROOT) {
409 mode = DIR_MODE;
410 } else {
411 struct kern_target *kt = VTOKERN(vp)->kf_kt;
412 mode = kt->kt_mode;
413 }
414
415 return (vaccess(vp->v_type, mode, (uid_t)0, (gid_t)0, ap->a_mode,
416 ap->a_cred));
417 }
418
419 int
420 kernfs_getattr(v)
421 void *v;
422 {
423 struct vop_getattr_args /* {
424 struct vnode *a_vp;
425 struct vattr *a_vap;
426 struct ucred *a_cred;
427 struct proc *a_p;
428 } */ *ap = v;
429 struct vnode *vp = ap->a_vp;
430 struct vattr *vap = ap->a_vap;
431 struct timeval tv;
432 int error = 0;
433 char strbuf[KSTRING], *buf;
434
435 bzero((caddr_t) vap, sizeof(*vap));
436 vattr_null(vap);
437 vap->va_uid = 0;
438 vap->va_gid = 0;
439 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
440 vap->va_size = 0;
441 vap->va_blocksize = DEV_BSIZE;
442 microtime(&tv);
443 TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
444 vap->va_mtime = vap->va_atime;
445 vap->va_ctime = vap->va_ctime;
446 vap->va_gen = 0;
447 vap->va_flags = 0;
448 vap->va_rdev = 0;
449 vap->va_bytes = 0;
450
451 if (vp->v_flag & VROOT) {
452 #ifdef KERNFS_DIAGNOSTIC
453 printf("kernfs_getattr: stat rootdir\n");
454 #endif
455 vap->va_type = VDIR;
456 vap->va_mode = DIR_MODE;
457 vap->va_nlink = 2;
458 vap->va_fileid = 2;
459 vap->va_size = DEV_BSIZE;
460 } else {
461 struct kern_target *kt = VTOKERN(vp)->kf_kt;
462 int nbytes, total;
463 #ifdef KERNFS_DIAGNOSTIC
464 printf("kernfs_getattr: stat target %s\n", kt->kt_name);
465 #endif
466 vap->va_type = kt->kt_vtype;
467 vap->va_mode = kt->kt_mode;
468 vap->va_nlink = 1;
469 vap->va_fileid = 3 + (kt - kern_targets);
470 total = 0;
471 while (buf = strbuf,
472 nbytes = kernfs_xread(kt, total, &buf, sizeof(strbuf)))
473 total += nbytes;
474 vap->va_size = total;
475 }
476
477 #ifdef KERNFS_DIAGNOSTIC
478 printf("kernfs_getattr: return error %d\n", error);
479 #endif
480 return (error);
481 }
482
483 /*ARGSUSED*/
484 int
485 kernfs_setattr(v)
486 void *v;
487 {
488 /*
489 * Silently ignore attribute changes.
490 * This allows for open with truncate to have no
491 * effect until some data is written. I want to
492 * do it this way because all writes are atomic.
493 */
494 return (0);
495 }
496
497 int
498 kernfs_read(v)
499 void *v;
500 {
501 struct vop_read_args /* {
502 struct vnode *a_vp;
503 struct uio *a_uio;
504 int a_ioflag;
505 struct ucred *a_cred;
506 } */ *ap = v;
507 struct vnode *vp = ap->a_vp;
508 struct uio *uio = ap->a_uio;
509 struct kern_target *kt;
510 char strbuf[KSTRING], *buf;
511 int off, len;
512 int error;
513
514 if (vp->v_type == VDIR)
515 return (EOPNOTSUPP);
516
517 kt = VTOKERN(vp)->kf_kt;
518
519 #ifdef KERNFS_DIAGNOSTIC
520 printf("kern_read %s\n", kt->kt_name);
521 #endif
522
523 off = uio->uio_offset;
524 #if 0
525 while (buf = strbuf,
526 #else
527 if (buf = strbuf,
528 #endif
529 len = kernfs_xread(kt, off, &buf, sizeof(strbuf))) {
530 if ((error = uiomove(buf, len, uio)) != 0)
531 return (error);
532 off += len;
533 }
534 return (0);
535 }
536
537 int
538 kernfs_write(v)
539 void *v;
540 {
541 struct vop_write_args /* {
542 struct vnode *a_vp;
543 struct uio *a_uio;
544 int a_ioflag;
545 struct ucred *a_cred;
546 } */ *ap = v;
547 struct vnode *vp = ap->a_vp;
548 struct uio *uio = ap->a_uio;
549 struct kern_target *kt;
550 int error, xlen;
551 char strbuf[KSTRING];
552
553 if (vp->v_type == VDIR)
554 return (EOPNOTSUPP);
555
556 kt = VTOKERN(vp)->kf_kt;
557
558 if (uio->uio_offset != 0)
559 return (EINVAL);
560
561 xlen = min(uio->uio_resid, KSTRING-1);
562 if ((error = uiomove(strbuf, xlen, uio)) != 0)
563 return (error);
564
565 if (uio->uio_resid != 0)
566 return (EIO);
567
568 strbuf[xlen] = '\0';
569 xlen = strlen(strbuf);
570 return (kernfs_xwrite(kt, strbuf, xlen));
571 }
572
573 int
574 kernfs_readdir(v)
575 void *v;
576 {
577 struct vop_readdir_args /* {
578 struct vnode *a_vp;
579 struct uio *a_uio;
580 struct ucred *a_cred;
581 int *a_eofflag;
582 u_long *a_cookies;
583 int a_ncookies;
584 } */ *ap = v;
585 struct uio *uio = ap->a_uio;
586 struct dirent d;
587 struct kern_target *kt;
588 int i;
589 int error;
590 u_long *cookies = ap->a_cookies;
591 int ncookies = ap->a_ncookies;
592
593 if (ap->a_vp->v_type != VDIR)
594 return (ENOTDIR);
595
596 if (uio->uio_resid < UIO_MX)
597 return (EINVAL);
598 if (uio->uio_offset < 0)
599 return (EINVAL);
600
601 error = 0;
602 i = uio->uio_offset;
603 bzero((caddr_t)&d, UIO_MX);
604 d.d_reclen = UIO_MX;
605
606 for (kt = &kern_targets[i];
607 uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) {
608 #ifdef KERNFS_DIAGNOSTIC
609 printf("kernfs_readdir: i = %d\n", i);
610 #endif
611
612 if (kt->kt_tag == KTT_DEVICE) {
613 dev_t *dp = kt->kt_data;
614 struct vnode *fvp;
615
616 if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
617 continue;
618 }
619
620 d.d_fileno = i + 3;
621 d.d_namlen = kt->kt_namlen;
622 bcopy(kt->kt_name, d.d_name, kt->kt_namlen + 1);
623 d.d_type = kt->kt_type;
624
625 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
626 break;
627 if (ncookies-- > 0)
628 *cookies++ = i + 1;
629 }
630
631 uio->uio_offset = i;
632 return (error);
633 }
634
635 int
636 kernfs_inactive(v)
637 void *v;
638 {
639 struct vop_inactive_args /* {
640 struct vnode *a_vp;
641 } */ *ap = v;
642 struct vnode *vp = ap->a_vp;
643
644 #ifdef KERNFS_DIAGNOSTIC
645 printf("kernfs_inactive(%p)\n", vp);
646 #endif
647 /*
648 * Clear out the v_type field to avoid
649 * nasty things happening in vgone().
650 */
651 vp->v_type = VNON;
652 return (0);
653 }
654
655 int
656 kernfs_reclaim(v)
657 void *v;
658 {
659 struct vop_reclaim_args /* {
660 struct vnode *a_vp;
661 } */ *ap = v;
662 struct vnode *vp = ap->a_vp;
663
664 #ifdef KERNFS_DIAGNOSTIC
665 printf("kernfs_reclaim(%p)\n", vp);
666 #endif
667 if (vp->v_data) {
668 FREE(vp->v_data, M_TEMP);
669 vp->v_data = 0;
670 }
671 return (0);
672 }
673
674 /*
675 * Return POSIX pathconf information applicable to special devices.
676 */
677 int
678 kernfs_pathconf(v)
679 void *v;
680 {
681 struct vop_pathconf_args /* {
682 struct vnode *a_vp;
683 int a_name;
684 register_t *a_retval;
685 } */ *ap = v;
686
687 switch (ap->a_name) {
688 case _PC_LINK_MAX:
689 *ap->a_retval = LINK_MAX;
690 return (0);
691 case _PC_MAX_CANON:
692 *ap->a_retval = MAX_CANON;
693 return (0);
694 case _PC_MAX_INPUT:
695 *ap->a_retval = MAX_INPUT;
696 return (0);
697 case _PC_PIPE_BUF:
698 *ap->a_retval = PIPE_BUF;
699 return (0);
700 case _PC_CHOWN_RESTRICTED:
701 *ap->a_retval = 1;
702 return (0);
703 case _PC_VDISABLE:
704 *ap->a_retval = _POSIX_VDISABLE;
705 return (0);
706 default:
707 return (EINVAL);
708 }
709 /* NOTREACHED */
710 }
711
712 /*
713 * Print out the contents of a /dev/fd vnode.
714 */
715 /* ARGSUSED */
716 int
717 kernfs_print(v)
718 void *v;
719 {
720
721 printf("tag VT_KERNFS, kernfs vnode\n");
722 return (0);
723 }
724
725 int
726 kernfs_link(v)
727 void *v;
728 {
729 struct vop_link_args /* {
730 struct vnode *a_dvp;
731 struct vnode *a_vp;
732 struct componentname *a_cnp;
733 } */ *ap = v;
734
735 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
736 vput(ap->a_dvp);
737 return (EROFS);
738 }
739
740 int
741 kernfs_symlink(v)
742 void *v;
743 {
744 struct vop_symlink_args /* {
745 struct vnode *a_dvp;
746 struct vnode **a_vpp;
747 struct componentname *a_cnp;
748 struct vattr *a_vap;
749 char *a_target;
750 } */ *ap = v;
751
752 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
753 vput(ap->a_dvp);
754 return (EROFS);
755 }
756