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