kernfs_vnops.c revision 1.9 1 /*
2 * Copyright (c) 1990, 1992 Jan-Simon Pendry
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Jan-Simon Pendry.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $Id: kernfs_vnops.c,v 1.9 1993/05/28 16:47:05 cgd Exp $
37 */
38
39 /*
40 * Kernel parameter filesystem
41 */
42
43 #include "param.h"
44 #include "systm.h"
45 #include "kernel.h"
46 #include "types.h"
47 #include "time.h"
48 #include "proc.h"
49 #include "file.h"
50 #include "vnode.h"
51 #include "stat.h"
52 #include "mount.h"
53 #include "namei.h"
54 #include "buf.h"
55 #include "miscfs/kernfs/kernfs.h"
56
57 #include "../ufs/dir.h" /* For readdir() XXX */
58
59 struct kernfs_target kernfs_targets[] = {
60 /* NOTE: The name must be less than UIO_MX-16 chars in length */
61 DIR_TARGET(".", 0, KTT_NULL, KTM_DIR_PERMS )
62 DIR_TARGET("..", 0, KTT_NULL, KTM_DIR_PERMS )
63 REG_TARGET("copyright", copyright, KTT_STRING, KTM_RO_PERMS )
64 REG_TARGET("hostname", 0, KTT_HOSTNAME, KTM_RW_PERMS )
65 REG_TARGET("hz", &hz, KTT_INT, KTM_RO_PERMS )
66 REG_TARGET("loadavg", 0, KTT_AVENRUN, KTM_RO_PERMS )
67 REG_TARGET("physmem", &physmem, KTT_INT, KTM_RO_PERMS )
68 DIR_TARGET("root", 0, KTT_NULL, KTM_DIR_PERMS )
69 BLK_TARGET("rootdev", 0, KTT_NULL, KTM_RO_PERMS )
70 CHR_TARGET("rrootdev", 0, KTT_NULL, KTM_RO_PERMS )
71 REG_TARGET("time", 0, KTT_TIME, KTM_RO_PERMS )
72 REG_TARGET("version", version, KTT_STRING, KTM_RO_PERMS )
73 };
74
75 static int nkernfs_targets = sizeof(kernfs_targets) / sizeof(kernfs_targets[0]);
76
77 static int
78 kernfs_xread(kt, buf, len, lenp)
79 struct kernfs_target *kt;
80 char *buf;
81 int len;
82 int *lenp;
83 {
84 int xlen;
85
86 switch (kt->kt_tag) {
87 case KTT_TIME: {
88 struct timeval tv;
89 microtime(&tv);
90 sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
91 break;
92 }
93
94 case KTT_INT: {
95 int *ip = kt->kt_data;
96 sprintf(buf, "%d\n", *ip);
97 break;
98 }
99
100 case KTT_STRING: {
101 char *cp = kt->kt_data;
102 int xlen = strlen(cp) + 1;
103
104 if (xlen >= len)
105 return (EINVAL);
106
107 bcopy(cp, buf, xlen);
108 break;
109 }
110
111 case KTT_HOSTNAME: {
112 char *cp = hostname;
113 int xlen = hostnamelen;
114
115 if (xlen + 2 > len) /* extra space for null and newline */
116 return (EINVAL);
117
118 bcopy(cp, buf, xlen); /* safer than sprintf */
119 buf[xlen] = '\n';
120 buf[xlen+1] = '\0';
121 break;
122 }
123
124 case KTT_AVENRUN:
125 sprintf(buf, "%d %d %d %d\n",
126 averunnable[0],
127 averunnable[1],
128 averunnable[2],
129 FSCALE);
130 break;
131
132 default:
133 return (EINVAL);
134 }
135
136 *lenp = strlen(buf);
137 return (0);
138 }
139
140 static int
141 kernfs_xwrite(kt, buf, len)
142 struct kernfs_target *kt;
143 char *buf;
144 int len;
145 {
146 switch (kt->kt_tag) {
147 case KTT_HOSTNAME: {
148 if (buf[len-1] == '\n')
149 --len;
150 bcopy(buf, hostname, len);
151 /* kernfs_write set buf[value_passed_as_len] = \0.
152 * therefore, buf len (hostnamelen) = len.
153 */
154 hostnamelen = len;
155 hostname[hostnamelen] = '\0'; /* null end of string. */
156 return (0);
157 }
158
159 default:
160 return (EIO);
161 }
162 }
163
164 /*
165 * vp is the current namei directory
166 * ndp is the name to locate in that directory...
167 */
168 kernfs_lookup(dvp, ndp, p)
169 struct vnode *dvp;
170 struct nameidata *ndp;
171 struct proc *p;
172 {
173 char *pname = ndp->ni_ptr;
174 int error = ENOENT;
175 int i;
176 struct vnode *fvp;
177
178 #ifdef KERNFS_DIAGNOSTIC
179 printf("kernfs_lookup(%s)\n", pname);
180 #endif
181 if (ndp->ni_namelen == 1 && *pname == '.') {
182 ndp->ni_dvp = dvp;
183 ndp->ni_vp = dvp;
184 VREF(dvp);
185 /*VOP_LOCK(dvp);*/
186 return (0);
187 }
188
189 if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) {
190 ndp->ni_dvp = dvp;
191 ndp->ni_vp = rootdir;
192 VREF(rootdir);
193 VOP_LOCK(rootdir);
194 return (0);
195 }
196
197 /*
198 * /kern/rootdev is the root device
199 */
200 if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
201 if (vfinddev(rootdev, VBLK, &fvp))
202 return (ENXIO);
203 ndp->ni_dvp = dvp;
204 ndp->ni_vp = fvp;
205 VREF(fvp);
206 VOP_LOCK(fvp);
207 return (0);
208 }
209
210 /*
211 * /kern/rrootdev is the root device
212 */
213 if (ndp->ni_namelen == 8 && bcmp(pname, "rrootdev", 7) == 0) {
214 ndp->ni_dvp = dvp;
215 ndp->ni_vp = rrootdevvp;
216 VREF(rrootdevvp);
217 VOP_LOCK(rrootdevvp);
218 return (0);
219 }
220
221 for (i = 0; i < nkernfs_targets; i++) {
222 struct kernfs_target *kt = &kernfs_targets[i];
223 if (ndp->ni_namelen == strlen(kt->kt_name) &&
224 bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) {
225 error = 0;
226 break;
227 }
228 }
229
230 #ifdef KERNFS_DIAGNOSTIC
231 printf("kernfs_lookup: i = %d, error = %d\n", i, error);
232 #endif
233
234 if (error)
235 goto bad;
236
237 #ifdef KERNFS_DIAGNOSTIC
238 printf("kernfs_lookup: allocate new vnode\n");
239 #endif
240 error = getnewvnode(VT_UFS, dvp->v_mount, &kernfs_vnodeops, &fvp);
241 if (error)
242 goto bad;
243 VTOKERN(fvp)->kf_kt = &kernfs_targets[i];
244 fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
245 ndp->ni_dvp = dvp;
246 ndp->ni_vp = fvp;
247 #ifdef KERNFS_DIAGNOSTIC
248 printf("kernfs_lookup: newvp = %x\n", fvp);
249 #endif
250 return (0);
251
252 bad:;
253 ndp->ni_dvp = dvp;
254 ndp->ni_vp = NULL;
255 #ifdef KERNFS_DIAGNOSTIC
256 printf("kernfs_lookup: error = %d\n", error);
257 #endif
258 return (error);
259 }
260
261 kernfs_open(vp, mode, cred, p)
262 struct vnode *vp;
263 int mode;
264 struct ucred *cred;
265 struct proc *p;
266 {
267 /* if access succeeded, this always does, too */
268
269 return (0);
270 }
271
272 /*
273 * Check mode permission on target pointer. Mode is READ, WRITE or EXEC.
274 * The mode is shifted to select the owner/group/other fields. The
275 * super user is granted all permissions.
276 */
277 kernfs_access(vp, mode, cred, p)
278 struct vnode *vp;
279 register int mode;
280 struct ucred *cred;
281 struct proc *p;
282 {
283 struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
284 register gid_t *gp;
285 int i, error;
286
287 #ifdef KERN_DIAGNOSTIC
288 if (!VOP_ISLOCKED(vp)) {
289 vprint("kernfs_access: not locked", vp);
290 panic("kernfs_access: not locked");
291 }
292 #endif
293 /*
294 * If you're the super-user, you always get access.
295 */
296 if (cred->cr_uid == 0)
297 return (0);
298 /*
299 * Access check is based on only one of owner, group, public.
300 * If not owner, then check group. If not a member of the
301 * group, then check public access.
302 */
303 if (cred->cr_uid != /* kt->kt_uid XXX */ 0) {
304 mode >>= 3;
305 gp = cred->cr_groups;
306 for (i = 0; i < cred->cr_ngroups; i++, gp++)
307 if (/* kt->kt_gid XXX */ 0 == *gp)
308 goto found;
309 mode >>= 3;
310 found:
311 ;
312 }
313 if ((kt->kt_perms & mode) == mode)
314 return (0);
315 return (EACCES);
316 }
317
318 kernfs_getattr(vp, vap, cred, p)
319 struct vnode *vp;
320 struct vattr *vap;
321 struct ucred *cred;
322 struct proc *p;
323 {
324 int error = 0;
325 char strbuf[KSTRING];
326 struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
327
328 bzero((caddr_t) vap, sizeof(*vap));
329 vattr_null(vap);
330 vap->va_uid = kt->kt_uid;
331 vap->va_gid = kt->kt_gid;
332 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
333 /* vap->va_qsize = 0; */
334 vap->va_blocksize = DEV_BSIZE;
335 microtime(&vap->va_atime);
336 vap->va_mtime = vap->va_atime;
337 vap->va_ctime = vap->va_ctime;
338 vap->va_gen = 0;
339 vap->va_flags = 0;
340 vap->va_rdev = 0;
341 /* vap->va_qbytes = 0; */
342 vap->va_bytes = 0;
343 vap->va_type = kt->kt_vtype;
344 vap->va_mode = kt->kt_perms;
345
346 if (vp->v_flag & VROOT) {
347 #ifdef KERNFS_DIAGNOSTIC
348 printf("kernfs_getattr: stat rootdir\n");
349 #endif
350 vap->va_nlink = 2;
351 vap->va_fileid = 2;
352 vap->va_size = DEV_BSIZE;
353 } else {
354 #ifdef KERNFS_DIAGNOSTIC
355 printf("kernfs_getattr: stat target %s\n", kt->kt_name);
356 #endif
357 vap->va_nlink = 1;
358 vap->va_fileid = 3 + (kt - kernfs_targets) / sizeof(*kt);
359 error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size);
360 }
361
362 vp->v_type = vap->va_type;
363 #ifdef KERNFS_DIAGNOSTIC
364 printf("kernfs_getattr: return error %d\n", error);
365 #endif
366 return (error);
367 }
368
369
370 /*
371 * Change the mode on a file.
372 */
373 kernfs_chmod1(vp, mode, p)
374 register struct vnode *vp;
375 register int mode;
376 struct proc *p;
377 {
378 register struct ucred *cred = p->p_ucred;
379 register struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
380 int error;
381
382 if ((mode & kt->kt_maxperms) != mode) /* can't set ro var to rw */
383 return (EPERM);
384
385 if (cred->cr_uid != kt->kt_uid &&
386 (error = suser(cred, &p->p_acflag)))
387 return (error);
388 if (cred->cr_uid) {
389 if (vp->v_type != VDIR && (mode & S_ISVTX))
390 return (EFTYPE);
391 if (!groupmember(kt->kt_gid, cred) && (mode & S_ISGID))
392 return (EPERM);
393 }
394 kt->kt_perms &= ~07777;
395 kt->kt_perms |= mode & 07777;
396 /* ip->i_flag |= ICHG;*/
397 return (0);
398 }
399
400 /*
401 * Perform chown operation on kernfs_target kt
402 */
403 kernfs_chown1(vp, uid, gid, p)
404 register struct vnode *vp;
405 uid_t uid;
406 gid_t gid;
407 struct proc *p;
408 {
409 register struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
410 register struct ucred *cred = p->p_ucred;
411 uid_t ouid;
412 gid_t ogid;
413 int error = 0;
414
415 if (uid == (u_short)VNOVAL)
416 uid = kt->kt_uid;
417 if (gid == (u_short)VNOVAL)
418 gid = kt->kt_gid;
419 /*
420 * If we don't own the file, are trying to change the owner
421 * of the file, or are not a member of the target group,
422 * the caller must be superuser or the call fails.
423 */
424 if ((cred->cr_uid != kt->kt_uid || uid != kt->kt_uid ||
425 !groupmember((gid_t)gid, cred)) &&
426 (error = suser(cred, &p->p_acflag)))
427 return (error);
428 ouid = kt->kt_uid;
429 ogid = kt->kt_gid;
430
431 kt->kt_uid = uid;
432 kt->kt_gid = gid;
433
434 /* if (ouid != uid || ogid != gid)
435 ip->i_flag |= ICHG;*/
436 if (ouid != uid && cred->cr_uid != 0)
437 kt->kt_perms &= ~S_ISUID;
438 if (ogid != gid && cred->cr_uid != 0)
439 kt->kt_perms &= ~S_ISGID;
440 return (0);
441 }
442
443 /*
444 * Set attribute vnode op. called from several syscalls
445 */
446 kernfs_setattr(vp, vap, cred, p)
447 struct vnode *vp;
448 struct vattr *vap;
449 struct ucred *cred;
450 struct proc *p;
451 {
452 int error = 0;
453
454 /*
455 * Check for unsetable attributes.
456 */
457 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
458 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
459 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
460 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
461 return (EINVAL);
462 }
463 /*
464 * Go through the fields and update iff not VNOVAL.
465 */
466 if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
467 if (error = kernfs_chown1(vp, vap->va_uid, vap->va_gid, p))
468 return (error);
469 if (vap->va_size != VNOVAL) {
470 if (vp->v_type == VDIR)
471 return (EISDIR);
472 /* else just nod and smile... */
473 }
474 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
475 /* if (cred->cr_uid != ip->i_uid &&
476 (error = suser(cred, &p->p_acflag)))
477 return (error);
478 if (vap->va_atime.tv_sec != VNOVAL)
479 ip->i_flag |= IACC;
480 if (vap->va_mtime.tv_sec != VNOVAL)
481 ip->i_flag |= IUPD;
482 ip->i_flag |= ICHG;
483 if (error = iupdat(ip, &vap->va_atime, &vap->va_mtime, 1))
484 return (error);
485 */
486 }
487 if (vap->va_mode != (u_short)VNOVAL)
488 error = kernfs_chmod1(vp, (int)vap->va_mode, p);
489 if (vap->va_flags != VNOVAL) {
490 /* if (cred->cr_uid != ip->i_uid &&
491 (error = suser(cred, &p->p_acflag)))
492 return (error);
493 if (cred->cr_uid == 0) {
494 ip->i_flags = vap->va_flags;
495 } else {
496 ip->i_flags &= 0xffff0000;
497 ip->i_flags |= (vap->va_flags & 0xffff);
498 }
499 ip->i_flag |= ICHG;
500 */
501 }
502 return (error);
503 }
504
505 static int
506 kernfs_read(vp, uio, ioflag, cred)
507 struct vnode *vp;
508 struct uio *uio;
509 int ioflag;
510 struct ucred *cred;
511 {
512 struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
513 char strbuf[KSTRING];
514 int off = uio->uio_offset;
515 int len = 0;
516 char *cp = strbuf;
517 int error;
518 #ifdef KERNFS_DIAGNOSTIC
519 printf("kern_read %s\n", kt->kt_name);
520 #endif
521
522 error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
523 if (error)
524 return (error);
525 cp = strbuf + off;
526 len -= off;
527 return (uiomove(cp, len, uio));
528 }
529
530 static int
531 kernfs_write(vp, uio, ioflag, cred)
532 struct vnode *vp;
533 struct uio *uio;
534 int ioflag;
535 struct ucred *cred;
536 {
537 struct kernfs_target *kt = VTOKERN(vp)->kf_kt;
538 char strbuf[KSTRING];
539 int len = uio->uio_resid;
540 char *cp = strbuf;
541 int xlen;
542 int error;
543
544 if (uio->uio_offset != 0)
545 return (EINVAL);
546
547 xlen = min(uio->uio_resid, KSTRING-1);
548 error = uiomove(strbuf, xlen, uio);
549 if (error)
550 return (error);
551
552 if (uio->uio_resid != 0)
553 return (EIO);
554
555 strbuf[xlen] = '\0';
556 return (kernfs_xwrite(kt, strbuf, xlen));
557 }
558
559 kernfs_readdir(vp, uio, cred, eofflagp)
560 struct vnode *vp;
561 struct uio *uio;
562 struct ucred *cred;
563 int *eofflagp;
564 {
565 struct filedesc *fdp;
566 int i;
567 int error;
568
569 i = uio->uio_offset / UIO_MX;
570 error = 0;
571 while (uio->uio_resid > 0) {
572 #ifdef KERNFS_DIAGNOSTIC
573 printf("kernfs_readdir: i = %d\n", i);
574 #endif
575 if (i >= nkernfs_targets) {
576 *eofflagp = 1;
577 break;
578 }
579 {
580 struct direct d;
581 struct direct *dp = &d;
582 struct kernfs_target *kt = &kernfs_targets[i];
583
584 bzero((caddr_t) dp, UIO_MX);
585
586 dp->d_namlen = strlen(kt->kt_name);
587 bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
588
589 #ifdef KERNFS_DIAGNOSTIC
590 printf("kernfs_readdir: name = %s, len = %d\n",
591 dp->d_name, dp->d_namlen);
592 #endif
593 /*
594 * Fill in the remaining fields
595 */
596 dp->d_reclen = UIO_MX;
597 dp->d_ino = i + 3;
598 /*
599 * And ship to userland
600 */
601 error = uiomove((caddr_t) dp, UIO_MX, uio);
602 if (error)
603 break;
604 }
605 i++;
606 }
607
608 uio->uio_offset = i * UIO_MX;
609
610 return (error);
611 }
612
613 kernfs_inactive(vp, p)
614 struct vnode *vp;
615 struct proc *p;
616 {
617 /*
618 * Clear out the v_type field to avoid
619 * nasty things happening in vgone().
620 */
621 vp->v_type = VNON;
622 #ifdef KERNFS_DIAGNOSTIC
623 printf("kernfs_inactive(%x)\n", vp);
624 #endif
625 return (0);
626 }
627
628 /*
629 * Print out the contents of a kernfs vnode.
630 */
631 /* ARGSUSED */
632 kernfs_print(vp)
633 struct vnode *vp;
634 {
635 printf("tag VT_NON, kernfs vnode\n");
636 }
637
638 /*
639 * kernfs vnode unsupported operation
640 */
641 kernfs_enotsupp()
642 {
643 return (EOPNOTSUPP);
644 }
645
646 /*
647 * kernfs "should never get here" operation
648 */
649 kernfs_badop()
650 {
651 panic("kernfs: bad op");
652 /* NOTREACHED */
653 }
654
655 /*
656 * kernfs vnode null operation
657 */
658 kernfs_nullop()
659 {
660 return (0);
661 }
662
663 #define kernfs_create ((int (*) __P(( \
664 struct nameidata *ndp, \
665 struct vattr *vap, \
666 struct proc *p))) kernfs_enotsupp)
667 #define kernfs_mknod ((int (*) __P(( \
668 struct nameidata *ndp, \
669 struct vattr *vap, \
670 struct ucred *cred, \
671 struct proc *p))) kernfs_enotsupp)
672 #define kernfs_close ((int (*) __P(( \
673 struct vnode *vp, \
674 int fflag, \
675 struct ucred *cred, \
676 struct proc *p))) nullop)
677 #define kernfs_ioctl ((int (*) __P(( \
678 struct vnode *vp, \
679 int command, \
680 caddr_t data, \
681 int fflag, \
682 struct ucred *cred, \
683 struct proc *p))) kernfs_enotsupp)
684 #define kernfs_select ((int (*) __P(( \
685 struct vnode *vp, \
686 int which, \
687 int fflags, \
688 struct ucred *cred, \
689 struct proc *p))) kernfs_enotsupp)
690 #define kernfs_mmap ((int (*) __P(( \
691 struct vnode *vp, \
692 int fflags, \
693 struct ucred *cred, \
694 struct proc *p))) kernfs_enotsupp)
695 #define kernfs_fsync ((int (*) __P(( \
696 struct vnode *vp, \
697 int fflags, \
698 struct ucred *cred, \
699 int waitfor, \
700 struct proc *p))) nullop)
701 #define kernfs_seek ((int (*) __P(( \
702 struct vnode *vp, \
703 off_t oldoff, \
704 off_t newoff, \
705 struct ucred *cred))) nullop)
706 #define kernfs_remove ((int (*) __P(( \
707 struct nameidata *ndp, \
708 struct proc *p))) kernfs_enotsupp)
709 #define kernfs_link ((int (*) __P(( \
710 struct vnode *vp, \
711 struct nameidata *ndp, \
712 struct proc *p))) kernfs_enotsupp)
713 #define kernfs_rename ((int (*) __P(( \
714 struct nameidata *fndp, \
715 struct nameidata *tdnp, \
716 struct proc *p))) kernfs_enotsupp)
717 #define kernfs_mkdir ((int (*) __P(( \
718 struct nameidata *ndp, \
719 struct vattr *vap, \
720 struct proc *p))) kernfs_enotsupp)
721 #define kernfs_rmdir ((int (*) __P(( \
722 struct nameidata *ndp, \
723 struct proc *p))) kernfs_enotsupp)
724 #define kernfs_symlink ((int (*) __P(( \
725 struct nameidata *ndp, \
726 struct vattr *vap, \
727 char *target, \
728 struct proc *p))) kernfs_enotsupp)
729 #define kernfs_readlink ((int (*) __P(( \
730 struct vnode *vp, \
731 struct uio *uio, \
732 struct ucred *cred))) kernfs_enotsupp)
733 #define kernfs_abortop ((int (*) __P(( \
734 struct nameidata *ndp))) nullop)
735 #ifdef KERNFS_DIAGNOSTIC
736 int kernfs_reclaim(vp)
737 struct vnode *vp;
738 {
739 printf("kernfs_reclaim(%x)\n", vp);
740 return (0);
741 }
742 #else
743 #define kernfs_reclaim ((int (*) __P(( \
744 struct vnode *vp))) nullop)
745 #endif
746 #define kernfs_lock ((int (*) __P(( \
747 struct vnode *vp))) nullop)
748 #define kernfs_unlock ((int (*) __P(( \
749 struct vnode *vp))) nullop)
750 #define kernfs_bmap ((int (*) __P(( \
751 struct vnode *vp, \
752 daddr_t bn, \
753 struct vnode **vpp, \
754 daddr_t *bnp))) kernfs_badop)
755 #define kernfs_strategy ((int (*) __P(( \
756 struct buf *bp))) kernfs_badop)
757 #define kernfs_islocked ((int (*) __P(( \
758 struct vnode *vp))) nullop)
759 #define kernfs_advlock ((int (*) __P(( \
760 struct vnode *vp, \
761 caddr_t id, \
762 int op, \
763 struct flock *fl, \
764 int flags))) kernfs_enotsupp)
765
766 struct vnodeops kernfs_vnodeops = {
767 kernfs_lookup, /* lookup */
768 kernfs_create, /* create */
769 kernfs_mknod, /* mknod */
770 kernfs_open, /* open */
771 kernfs_close, /* close */
772 kernfs_access, /* access */
773 kernfs_getattr, /* getattr */
774 kernfs_setattr, /* setattr */
775 kernfs_read, /* read */
776 kernfs_write, /* write */
777 kernfs_ioctl, /* ioctl */
778 kernfs_select, /* select */
779 kernfs_mmap, /* mmap */
780 kernfs_fsync, /* fsync */
781 kernfs_seek, /* seek */
782 kernfs_remove, /* remove */
783 kernfs_link, /* link */
784 kernfs_rename, /* rename */
785 kernfs_mkdir, /* mkdir */
786 kernfs_rmdir, /* rmdir */
787 kernfs_symlink, /* symlink */
788 kernfs_readdir, /* readdir */
789 kernfs_readlink, /* readlink */
790 kernfs_abortop, /* abortop */
791 kernfs_inactive, /* inactive */
792 kernfs_reclaim, /* reclaim */
793 kernfs_lock, /* lock */
794 kernfs_unlock, /* unlock */
795 kernfs_bmap, /* bmap */
796 kernfs_strategy, /* strategy */
797 kernfs_print, /* print */
798 kernfs_islocked, /* islocked */
799 kernfs_advlock, /* advlock */
800 };
801