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