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