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