[BACK]Return to kernfs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / miscfs / kernfs

Annotation of src/sys/miscfs/kernfs/kernfs_vnops.c, Revision 1.59

1.59    ! kleink      1: /*     $NetBSD: kernfs_vnops.c,v 1.58 1998/03/08 14:04:14 mrg Exp $    */
1.27      cgd         2:
1.1       cgd         3: /*
1.23      mycroft     4:  * Copyright (c) 1992, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
1.17      cgd         7:  * This code is derived from software donated to Berkeley by
1.1       cgd         8:  * Jan-Simon Pendry.
                      9:  *
1.2       cgd        10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
1.17      cgd        20:  *     This product includes software developed by the University of
                     21:  *     California, Berkeley and its contributors.
1.2       cgd        22:  * 4. Neither the name of the University nor the names of its contributors
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
1.1       cgd        25:  *
1.2       cgd        26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
1.1       cgd        37:  *
1.57      fvdl       38:  *     @(#)kernfs_vnops.c      8.15 (Berkeley) 5/21/95
1.1       cgd        39:  */
                     40:
                     41: /*
1.23      mycroft    42:  * Kernel parameter filesystem (/kern)
1.1       cgd        43:  */
1.55      mrg        44:
1.58      mrg        45: #if defined(_KERNEL) && !defined(_LKM)
1.55      mrg        46: #include "opt_uvm.h"
1.56      thorpej    47: #endif
1.1       cgd        48:
1.14      mycroft    49: #include <sys/param.h>
                     50: #include <sys/systm.h>
                     51: #include <sys/kernel.h>
1.23      mycroft    52: #include <sys/vmmeter.h>
1.14      mycroft    53: #include <sys/types.h>
                     54: #include <sys/time.h>
                     55: #include <sys/proc.h>
1.23      mycroft    56: #include <sys/vnode.h>
                     57: #include <sys/malloc.h>
1.14      mycroft    58: #include <sys/file.h>
                     59: #include <sys/stat.h>
                     60: #include <sys/mount.h>
                     61: #include <sys/namei.h>
                     62: #include <sys/buf.h>
1.23      mycroft    63: #include <sys/dirent.h>
1.28      mycroft    64: #include <sys/msgbuf.h>
1.44      mycroft    65:
                     66: #include <miscfs/genfs/genfs.h>
1.17      cgd        67: #include <miscfs/kernfs/kernfs.h>
1.1       cgd        68:
1.54      mrg        69: #if defined(UVM)
                     70: #include <vm/vm.h>
                     71: #include <uvm/uvm_extern.h>
                     72: #endif
                     73:
1.17      cgd        74: #define KSTRING        256             /* Largest I/O available via this filesystem */
                     75: #define        UIO_MX 32
1.1       cgd        76:
1.23      mycroft    77: #define        READ_MODE       (S_IRUSR|S_IRGRP|S_IROTH)
                     78: #define        WRITE_MODE      (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
                     79: #define DIR_MODE       (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
                     80:
1.50      pk         81: struct kern_target kern_targets[] = {
1.1       cgd        82: /* NOTE: The name must be less than UIO_MX-16 chars in length */
1.23      mycroft    83: #define N(s) sizeof(s)-1, s
                     84:      /*        name            data          tag           type  ro/rw */
                     85:      { DT_DIR, N("."),         0,            KTT_NULL,     VDIR, DIR_MODE   },
                     86:      { DT_DIR, N(".."),        0,            KTT_NULL,     VDIR, DIR_MODE   },
                     87:      { DT_REG, N("boottime"),  &boottime.tv_sec, KTT_INT,  VREG, READ_MODE  },
                     88:      { DT_REG, N("copyright"), copyright,    KTT_STRING,   VREG, READ_MODE  },
                     89:      { DT_REG, N("hostname"),  0,            KTT_HOSTNAME, VREG, WRITE_MODE },
                     90:      { DT_REG, N("hz"),        &hz,          KTT_INT,      VREG, READ_MODE  },
                     91:      { DT_REG, N("loadavg"),   0,            KTT_AVENRUN,  VREG, READ_MODE  },
1.28      mycroft    92:      { DT_REG, N("msgbuf"),    0,           KTT_MSGBUF,   VREG, READ_MODE  },
1.54      mrg        93: #if defined(UVM)
                     94:      { DT_REG, N("pagesize"),  &uvmexp.pagesize, KTT_INT,  VREG, READ_MODE  },
                     95: #else
1.23      mycroft    96:      { DT_REG, N("pagesize"),  &cnt.v_page_size, KTT_INT,  VREG, READ_MODE  },
1.54      mrg        97: #endif
1.23      mycroft    98:      { DT_REG, N("physmem"),   &physmem,     KTT_INT,      VREG, READ_MODE  },
1.17      cgd        99: #if 0
1.23      mycroft   100:      { DT_DIR, N("root"),      0,            KTT_NULL,     VDIR, DIR_MODE   },
1.17      cgd       101: #endif
1.23      mycroft   102:      { DT_BLK, N("rootdev"),   &rootdev,     KTT_DEVICE,   VBLK, READ_MODE  },
                    103:      { DT_CHR, N("rrootdev"),  &rrootdev,    KTT_DEVICE,   VCHR, READ_MODE  },
                    104:      { DT_REG, N("time"),      0,            KTT_TIME,     VREG, READ_MODE  },
                    105:      { DT_REG, N("version"),   version,      KTT_STRING,   VREG, READ_MODE  },
                    106: #undef N
1.1       cgd       107: };
1.17      cgd       108: static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.1       cgd       109:
1.41      christos  110: int    kernfs_lookup   __P((void *));
1.44      mycroft   111: #define        kernfs_create   genfs_eopnotsupp
                    112: #define        kernfs_mknod    genfs_eopnotsupp
                    113: #define        kernfs_open     genfs_nullop
                    114: #define        kernfs_close    genfs_nullop
1.41      christos  115: int    kernfs_access   __P((void *));
                    116: int    kernfs_getattr  __P((void *));
                    117: int    kernfs_setattr  __P((void *));
                    118: int    kernfs_read     __P((void *));
                    119: int    kernfs_write    __P((void *));
1.44      mycroft   120: #define        kernfs_ioctl    genfs_eopnotsupp
1.45      mycroft   121: #define        kernfs_poll     genfs_poll
1.57      fvdl      122: #define kernfs_revoke  genfs_revoke
1.44      mycroft   123: #define        kernfs_mmap     genfs_eopnotsupp
                    124: #define        kernfs_fsync    genfs_nullop
                    125: #define        kernfs_seek     genfs_nullop
                    126: #define        kernfs_remove   genfs_eopnotsupp
1.41      christos  127: int    kernfs_link     __P((void *));
1.44      mycroft   128: #define        kernfs_rename   genfs_eopnotsupp
                    129: #define        kernfs_mkdir    genfs_eopnotsupp
                    130: #define        kernfs_rmdir    genfs_eopnotsupp
1.41      christos  131: int    kernfs_symlink  __P((void *));
                    132: int    kernfs_readdir  __P((void *));
1.44      mycroft   133: #define        kernfs_readlink genfs_eopnotsupp
                    134: #define        kernfs_abortop  genfs_abortop
1.41      christos  135: int    kernfs_inactive __P((void *));
                    136: int    kernfs_reclaim  __P((void *));
1.57      fvdl      137: #define        kernfs_lock     genfs_nolock
                    138: #define        kernfs_unlock   genfs_nounlock
1.44      mycroft   139: #define        kernfs_bmap     genfs_badop
                    140: #define        kernfs_strategy genfs_badop
1.41      christos  141: int    kernfs_print    __P((void *));
1.57      fvdl      142: #define        kernfs_islocked genfs_noislocked
1.41      christos  143: int    kernfs_pathconf __P((void *));
1.44      mycroft   144: #define        kernfs_advlock  genfs_eopnotsupp
                    145: #define        kernfs_blkatoff genfs_eopnotsupp
                    146: #define        kernfs_valloc   genfs_eopnotsupp
                    147: #define        kernfs_vfree    genfs_nullop
                    148: #define        kernfs_truncate genfs_eopnotsupp
                    149: #define        kernfs_update   genfs_nullop
                    150: #define        kernfs_bwrite   genfs_eopnotsupp
1.41      christos  151:
                    152: int    kernfs_xread __P((struct kern_target *, int, char **, int));
                    153: int    kernfs_xwrite __P((struct kern_target *, char *, int));
                    154:
                    155: int (**kernfs_vnodeop_p) __P((void *));
                    156: struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
                    157:        { &vop_default_desc, vn_default_error },
1.44      mycroft   158:        { &vop_lookup_desc, kernfs_lookup },            /* lookup */
                    159:        { &vop_create_desc, kernfs_create },            /* create */
                    160:        { &vop_mknod_desc, kernfs_mknod },              /* mknod */
                    161:        { &vop_open_desc, kernfs_open },                /* open */
                    162:        { &vop_close_desc, kernfs_close },              /* close */
                    163:        { &vop_access_desc, kernfs_access },            /* access */
                    164:        { &vop_getattr_desc, kernfs_getattr },          /* getattr */
                    165:        { &vop_setattr_desc, kernfs_setattr },          /* setattr */
                    166:        { &vop_read_desc, kernfs_read },                /* read */
                    167:        { &vop_write_desc, kernfs_write },              /* write */
                    168:        { &vop_ioctl_desc, kernfs_ioctl },              /* ioctl */
1.45      mycroft   169:        { &vop_poll_desc, kernfs_poll },                /* poll */
1.57      fvdl      170:        { &vop_revoke_desc, kernfs_revoke },            /* revoke */
1.44      mycroft   171:        { &vop_mmap_desc, kernfs_mmap },                /* mmap */
                    172:        { &vop_fsync_desc, kernfs_fsync },              /* fsync */
                    173:        { &vop_seek_desc, kernfs_seek },                /* seek */
                    174:        { &vop_remove_desc, kernfs_remove },            /* remove */
                    175:        { &vop_link_desc, kernfs_link },                /* link */
                    176:        { &vop_rename_desc, kernfs_rename },            /* rename */
                    177:        { &vop_mkdir_desc, kernfs_mkdir },              /* mkdir */
                    178:        { &vop_rmdir_desc, kernfs_rmdir },              /* rmdir */
                    179:        { &vop_symlink_desc, kernfs_symlink },          /* symlink */
                    180:        { &vop_readdir_desc, kernfs_readdir },          /* readdir */
                    181:        { &vop_readlink_desc, kernfs_readlink },        /* readlink */
                    182:        { &vop_abortop_desc, kernfs_abortop },          /* abortop */
                    183:        { &vop_inactive_desc, kernfs_inactive },        /* inactive */
                    184:        { &vop_reclaim_desc, kernfs_reclaim },          /* reclaim */
                    185:        { &vop_lock_desc, kernfs_lock },                /* lock */
                    186:        { &vop_unlock_desc, kernfs_unlock },            /* unlock */
                    187:        { &vop_bmap_desc, kernfs_bmap },                /* bmap */
                    188:        { &vop_strategy_desc, kernfs_strategy },        /* strategy */
                    189:        { &vop_print_desc, kernfs_print },              /* print */
                    190:        { &vop_islocked_desc, kernfs_islocked },        /* islocked */
                    191:        { &vop_pathconf_desc, kernfs_pathconf },        /* pathconf */
                    192:        { &vop_advlock_desc, kernfs_advlock },          /* advlock */
                    193:        { &vop_blkatoff_desc, kernfs_blkatoff },        /* blkatoff */
                    194:        { &vop_valloc_desc, kernfs_valloc },            /* valloc */
                    195:        { &vop_vfree_desc, kernfs_vfree },              /* vfree */
                    196:        { &vop_truncate_desc, kernfs_truncate },        /* truncate */
                    197:        { &vop_update_desc, kernfs_update },            /* update */
                    198:        { &vop_bwrite_desc, kernfs_bwrite },            /* bwrite */
1.41      christos  199:        { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL }
                    200: };
                    201: struct vnodeopv_desc kernfs_vnodeop_opv_desc =
                    202:        { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
                    203:
1.28      mycroft   204: int
                    205: kernfs_xread(kt, off, bufp, len)
1.17      cgd       206:        struct kern_target *kt;
1.28      mycroft   207:        int off;
                    208:        char **bufp;
1.1       cgd       209:        int len;
                    210: {
                    211:
                    212:        switch (kt->kt_tag) {
                    213:        case KTT_TIME: {
                    214:                struct timeval tv;
1.28      mycroft   215:
1.1       cgd       216:                microtime(&tv);
1.47      christos  217:                sprintf(*bufp, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
1.1       cgd       218:                break;
                    219:        }
                    220:
                    221:        case KTT_INT: {
                    222:                int *ip = kt->kt_data;
1.28      mycroft   223:
1.47      christos  224:                sprintf(*bufp, "%d\n", *ip);
1.1       cgd       225:                break;
                    226:        }
                    227:
                    228:        case KTT_STRING: {
                    229:                char *cp = kt->kt_data;
                    230:
1.28      mycroft   231:                *bufp = cp;
                    232:                break;
                    233:        }
1.1       cgd       234:
1.28      mycroft   235:        case KTT_MSGBUF: {
                    236:                long n;
                    237:
1.52      leo       238:                /*
                    239:                 * deal with cases where the message buffer has
                    240:                 * become corrupted.
                    241:                 */
                    242:                if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
                    243:                        msgbufenabled = 0;
                    244:                        return (ENXIO);
                    245:                }
                    246:
                    247:                /*
                    248:                 * Note that reads of /kern/msgbuf won't necessarily yield
                    249:                 * consistent results, if the message buffer is modified
                    250:                 * while the read is in progress.  The worst that can happen
                    251:                 * is that incorrect data will be read.  There's no way
                    252:                 * that this can crash the system unless the values in the
                    253:                 * message buffer header are corrupted, but that'll cause
                    254:                 * the system to die anyway.
                    255:                 */
                    256:                if (off >= msgbufp->msg_bufs)
1.28      mycroft   257:                        return (0);
                    258:                n = msgbufp->msg_bufx + off;
1.52      leo       259:                if (n >= msgbufp->msg_bufs)
                    260:                        n -= msgbufp->msg_bufs;
                    261:                len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
1.28      mycroft   262:                *bufp = msgbufp->msg_bufc + n;
                    263:                return (len);
1.1       cgd       264:        }
                    265:
                    266:        case KTT_HOSTNAME: {
                    267:                char *cp = hostname;
                    268:                int xlen = hostnamelen;
                    269:
1.17      cgd       270:                if (xlen >= (len-2))
1.1       cgd       271:                        return (EINVAL);
                    272:
1.28      mycroft   273:                bcopy(cp, *bufp, xlen);
                    274:                (*bufp)[xlen] = '\n';
                    275:                (*bufp)[xlen+1] = '\0';
1.1       cgd       276:                break;
                    277:        }
                    278:
                    279:        case KTT_AVENRUN:
1.31      mycroft   280:                averunnable.fscale = FSCALE;
1.47      christos  281:                sprintf(*bufp, "%d %d %d %ld\n",
1.23      mycroft   282:                    averunnable.ldavg[0], averunnable.ldavg[1],
                    283:                    averunnable.ldavg[2], averunnable.fscale);
1.1       cgd       284:                break;
                    285:
                    286:        default:
1.28      mycroft   287:                return (0);
1.1       cgd       288:        }
                    289:
1.28      mycroft   290:        len = strlen(*bufp);
                    291:        if (len <= off)
                    292:                return (0);
                    293:        *bufp += off;
                    294:        return (len - off);
1.1       cgd       295: }
                    296:
1.28      mycroft   297: int
1.1       cgd       298: kernfs_xwrite(kt, buf, len)
1.17      cgd       299:        struct kern_target *kt;
1.1       cgd       300:        char *buf;
                    301:        int len;
                    302: {
1.23      mycroft   303:
1.1       cgd       304:        switch (kt->kt_tag) {
1.23      mycroft   305:        case KTT_HOSTNAME:
1.1       cgd       306:                if (buf[len-1] == '\n')
                    307:                        --len;
                    308:                bcopy(buf, hostname, len);
1.17      cgd       309:                hostname[len] = '\0';
1.6       cgd       310:                hostnamelen = len;
1.1       cgd       311:                return (0);
                    312:
                    313:        default:
                    314:                return (EIO);
                    315:        }
                    316: }
                    317:
1.17      cgd       318:
                    319: /*
1.1       cgd       320:  * vp is the current namei directory
                    321:  * ndp is the name to locate in that directory...
                    322:  */
1.41      christos  323: int
                    324: kernfs_lookup(v)
                    325:        void *v;
                    326: {
1.23      mycroft   327:        struct vop_lookup_args /* {
                    328:                struct vnode * a_dvp;
                    329:                struct vnode ** a_vpp;
                    330:                struct componentname * a_cnp;
1.41      christos  331:        } */ *ap = v;
1.23      mycroft   332:        struct componentname *cnp = ap->a_cnp;
                    333:        struct vnode **vpp = ap->a_vpp;
                    334:        struct vnode *dvp = ap->a_dvp;
1.48      cgd       335:        const char *pname = cnp->cn_nameptr;
1.23      mycroft   336:        struct kern_target *kt;
1.1       cgd       337:        struct vnode *fvp;
1.23      mycroft   338:        int error, i;
1.1       cgd       339:
                    340: #ifdef KERNFS_DIAGNOSTIC
1.51      christos  341:        printf("kernfs_lookup(%p)\n", ap);
                    342:        printf("kernfs_lookup(dp = %p, vpp = %p, cnp = %p)\n", dvp, vpp, ap->a_cnp);
1.47      christos  343:        printf("kernfs_lookup(%s)\n", pname);
1.1       cgd       344: #endif
1.23      mycroft   345:
1.35      mycroft   346:        *vpp = NULLVP;
                    347:
                    348:        if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
                    349:                return (EROFS);
                    350:
1.57      fvdl      351:        VOP_UNLOCK(dvp, 0);
1.23      mycroft   352:        if (cnp->cn_namelen == 1 && *pname == '.') {
                    353:                *vpp = dvp;
1.1       cgd       354:                VREF(dvp);
1.57      fvdl      355:                vn_lock(dvp, LK_SHARED | LK_RETRY);
1.1       cgd       356:                return (0);
                    357:        }
1.13      cgd       358:
1.17      cgd       359: #if 0
1.23      mycroft   360:        if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {
                    361:                *vpp = rootdir;
1.17      cgd       362:                VREF(rootdir);
1.57      fvdl      363:                vn_lock(rootdir, LK_SHARED | LK_RETRY);
1.1       cgd       364:                return (0);
                    365:        }
1.13      cgd       366: #endif
1.25      mycroft   367:
1.35      mycroft   368:        for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) {
1.26      mycroft   369:                if (cnp->cn_namelen == kt->kt_namlen &&
1.35      mycroft   370:                    bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
                    371:                        goto found;
1.1       cgd       372:        }
                    373:
                    374: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  375:        printf("kernfs_lookup: i = %d, failed", i);
1.1       cgd       376: #endif
                    377:
1.57      fvdl      378:        vn_lock(dvp, LK_SHARED | LK_RETRY);
1.35      mycroft   379:        return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
1.23      mycroft   380:
1.35      mycroft   381: found:
1.23      mycroft   382:        if (kt->kt_tag == KTT_DEVICE) {
                    383:                dev_t *dp = kt->kt_data;
1.24      mycroft   384:        loop:
1.57      fvdl      385:                if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) {
                    386:                        vn_lock(dvp, LK_SHARED | LK_RETRY);
1.24      mycroft   387:                        return (ENOENT);
1.57      fvdl      388:                }
1.23      mycroft   389:                *vpp = fvp;
1.57      fvdl      390:                if (vget(fvp, LK_EXCLUSIVE))
1.24      mycroft   391:                        goto loop;
1.23      mycroft   392:                return (0);
                    393:        }
1.1       cgd       394:
                    395: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  396:        printf("kernfs_lookup: allocate new vnode\n");
1.1       cgd       397: #endif
1.41      christos  398:        error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);
1.57      fvdl      399:        if (error) {
                    400:                vn_lock(dvp, LK_SHARED | LK_RETRY);
1.23      mycroft   401:                return (error);
1.57      fvdl      402:        }
1.23      mycroft   403:
                    404:        MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP,
                    405:            M_WAITOK);
                    406:        VTOKERN(fvp)->kf_kt = kt;
                    407:        fvp->v_type = kt->kt_vtype;
1.57      fvdl      408:        vn_lock(fvp, LK_SHARED | LK_RETRY);
1.23      mycroft   409:        *vpp = fvp;
                    410:
1.1       cgd       411: #ifdef KERNFS_DIAGNOSTIC
1.51      christos  412:        printf("kernfs_lookup: newvp = %p\n", fvp);
1.1       cgd       413: #endif
                    414:        return (0);
                    415: }
                    416:
1.28      mycroft   417: int
1.41      christos  418: kernfs_access(v)
                    419:        void *v;
                    420: {
1.23      mycroft   421:        struct vop_access_args /* {
                    422:                struct vnode *a_vp;
1.34      mycroft   423:                int a_mode;
1.23      mycroft   424:                struct ucred *a_cred;
                    425:                struct proc *a_p;
1.41      christos  426:        } */ *ap = v;
1.26      mycroft   427:        struct vnode *vp = ap->a_vp;
1.49      mycroft   428:        mode_t mode;
1.17      cgd       429:
1.49      mycroft   430:        if (vp->v_flag & VROOT) {
                    431:                mode = DIR_MODE;
                    432:        } else {
                    433:                struct kern_target *kt = VTOKERN(vp)->kf_kt;
                    434:                mode = kt->kt_mode;
                    435:        }
                    436:
                    437:        return (vaccess(vp->v_type, mode, (uid_t)0, (gid_t)0, ap->a_mode,
                    438:            ap->a_cred));
1.23      mycroft   439: }
                    440:
1.41      christos  441: int
                    442: kernfs_getattr(v)
                    443:        void *v;
                    444: {
1.23      mycroft   445:        struct vop_getattr_args /* {
                    446:                struct vnode *a_vp;
                    447:                struct vattr *a_vap;
                    448:                struct ucred *a_cred;
                    449:                struct proc *a_p;
1.41      christos  450:        } */ *ap = v;
1.23      mycroft   451:        struct vnode *vp = ap->a_vp;
                    452:        struct vattr *vap = ap->a_vap;
1.36      cgd       453:        struct timeval tv;
1.1       cgd       454:        int error = 0;
1.28      mycroft   455:        char strbuf[KSTRING], *buf;
1.1       cgd       456:
                    457:        bzero((caddr_t) vap, sizeof(*vap));
                    458:        vattr_null(vap);
1.17      cgd       459:        vap->va_uid = 0;
                    460:        vap->va_gid = 0;
1.1       cgd       461:        vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1.23      mycroft   462:        vap->va_size = 0;
1.1       cgd       463:        vap->va_blocksize = DEV_BSIZE;
1.36      cgd       464:        microtime(&tv);
                    465:        TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
1.1       cgd       466:        vap->va_mtime = vap->va_atime;
                    467:        vap->va_ctime = vap->va_ctime;
                    468:        vap->va_gen = 0;
                    469:        vap->va_flags = 0;
                    470:        vap->va_rdev = 0;
                    471:        vap->va_bytes = 0;
                    472:
                    473:        if (vp->v_flag & VROOT) {
                    474: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  475:                printf("kernfs_getattr: stat rootdir\n");
1.1       cgd       476: #endif
1.17      cgd       477:                vap->va_type = VDIR;
1.23      mycroft   478:                vap->va_mode = DIR_MODE;
1.1       cgd       479:                vap->va_nlink = 2;
                    480:                vap->va_fileid = 2;
                    481:                vap->va_size = DEV_BSIZE;
                    482:        } else {
1.23      mycroft   483:                struct kern_target *kt = VTOKERN(vp)->kf_kt;
1.28      mycroft   484:                int nbytes, total;
1.1       cgd       485: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  486:                printf("kernfs_getattr: stat target %s\n", kt->kt_name);
1.1       cgd       487: #endif
1.17      cgd       488:                vap->va_type = kt->kt_vtype;
1.23      mycroft   489:                vap->va_mode = kt->kt_mode;
1.1       cgd       490:                vap->va_nlink = 1;
1.57      fvdl      491:                vap->va_fileid = 1 + (kt - kern_targets);
1.28      mycroft   492:                total = 0;
                    493:                while (buf = strbuf,
                    494:                       nbytes = kernfs_xread(kt, total, &buf, sizeof(strbuf)))
                    495:                        total += nbytes;
                    496:                vap->va_size = total;
1.1       cgd       497:        }
                    498:
                    499: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  500:        printf("kernfs_getattr: return error %d\n", error);
1.1       cgd       501: #endif
                    502:        return (error);
                    503: }
                    504:
1.41      christos  505: /*ARGSUSED*/
                    506: int
                    507: kernfs_setattr(v)
                    508:        void *v;
1.1       cgd       509: {
                    510:        /*
1.17      cgd       511:         * Silently ignore attribute changes.
                    512:         * This allows for open with truncate to have no
                    513:         * effect until some data is written.  I want to
                    514:         * do it this way because all writes are atomic.
1.1       cgd       515:         */
1.17      cgd       516:        return (0);
1.1       cgd       517: }
                    518:
1.28      mycroft   519: int
1.41      christos  520: kernfs_read(v)
                    521:        void *v;
                    522: {
1.23      mycroft   523:        struct vop_read_args /* {
                    524:                struct vnode *a_vp;
                    525:                struct uio *a_uio;
                    526:                int  a_ioflag;
                    527:                struct ucred *a_cred;
1.41      christos  528:        } */ *ap = v;
1.23      mycroft   529:        struct vnode *vp = ap->a_vp;
                    530:        struct uio *uio = ap->a_uio;
                    531:        struct kern_target *kt;
1.28      mycroft   532:        char strbuf[KSTRING], *buf;
                    533:        int off, len;
                    534:        int error;
1.23      mycroft   535:
                    536:        if (vp->v_type == VDIR)
                    537:                return (EOPNOTSUPP);
                    538:
                    539:        kt = VTOKERN(vp)->kf_kt;
                    540:
1.1       cgd       541: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  542:        printf("kern_read %s\n", kt->kt_name);
1.1       cgd       543: #endif
1.18      cgd       544:
1.28      mycroft   545:        off = uio->uio_offset;
                    546: #if 0
                    547:        while (buf = strbuf,
                    548: #else
                    549:        if (buf = strbuf,
                    550: #endif
                    551:            len = kernfs_xread(kt, off, &buf, sizeof(strbuf))) {
1.41      christos  552:                if ((error = uiomove(buf, len, uio)) != 0)
1.28      mycroft   553:                        return (error);
                    554:                off += len;
                    555:        }
                    556:        return (0);
1.1       cgd       557: }
                    558:
1.28      mycroft   559: int
1.41      christos  560: kernfs_write(v)
                    561:        void *v;
                    562: {
1.23      mycroft   563:        struct vop_write_args /* {
                    564:                struct vnode *a_vp;
                    565:                struct uio *a_uio;
                    566:                int  a_ioflag;
                    567:                struct ucred *a_cred;
1.41      christos  568:        } */ *ap = v;
1.23      mycroft   569:        struct vnode *vp = ap->a_vp;
                    570:        struct uio *uio = ap->a_uio;
                    571:        struct kern_target *kt;
                    572:        int error, xlen;
1.1       cgd       573:        char strbuf[KSTRING];
1.23      mycroft   574:
                    575:        if (vp->v_type == VDIR)
                    576:                return (EOPNOTSUPP);
                    577:
                    578:        kt = VTOKERN(vp)->kf_kt;
1.1       cgd       579:
                    580:        if (uio->uio_offset != 0)
                    581:                return (EINVAL);
                    582:
                    583:        xlen = min(uio->uio_resid, KSTRING-1);
1.41      christos  584:        if ((error = uiomove(strbuf, xlen, uio)) != 0)
1.1       cgd       585:                return (error);
                    586:
                    587:        if (uio->uio_resid != 0)
                    588:                return (EIO);
                    589:
                    590:        strbuf[xlen] = '\0';
1.17      cgd       591:        xlen = strlen(strbuf);
1.1       cgd       592:        return (kernfs_xwrite(kt, strbuf, xlen));
                    593: }
                    594:
1.41      christos  595: int
                    596: kernfs_readdir(v)
                    597:        void *v;
                    598: {
1.23      mycroft   599:        struct vop_readdir_args /* {
                    600:                struct vnode *a_vp;
                    601:                struct uio *a_uio;
                    602:                struct ucred *a_cred;
1.26      mycroft   603:                int *a_eofflag;
1.57      fvdl      604:                off_t **a_cookies;
                    605:                int a_*ncookies;
1.41      christos  606:        } */ *ap = v;
1.23      mycroft   607:        struct uio *uio = ap->a_uio;
1.37      mycroft   608:        struct dirent d;
1.26      mycroft   609:        struct kern_target *kt;
1.1       cgd       610:        int i;
                    611:        int error;
1.57      fvdl      612:        off_t *cookies = NULL;
                    613:        int ncookies = 0, nc = 0;
1.1       cgd       614:
1.23      mycroft   615:        if (ap->a_vp->v_type != VDIR)
                    616:                return (ENOTDIR);
                    617:
1.37      mycroft   618:        if (uio->uio_resid < UIO_MX)
                    619:                return (EINVAL);
1.38      mycroft   620:        if (uio->uio_offset < 0)
1.37      mycroft   621:                return (EINVAL);
1.26      mycroft   622:
1.1       cgd       623:        error = 0;
1.38      mycroft   624:        i = uio->uio_offset;
1.37      mycroft   625:        bzero((caddr_t)&d, UIO_MX);
                    626:        d.d_reclen = UIO_MX;
                    627:
1.57      fvdl      628:        if (ap->a_ncookies) {
                    629:                nc = uio->uio_resid / UIO_MX;
                    630:                nc = min(nc, (nkern_targets - i));
                    631:                MALLOC(cookies, off_t *, nc * sizeof(off_t), M_TEMP,
                    632:                    M_WAITOK);
                    633:                *ap->a_cookies = cookies;
                    634:        }
                    635:
1.23      mycroft   636:        for (kt = &kern_targets[i];
                    637:             uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) {
1.1       cgd       638: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  639:                printf("kernfs_readdir: i = %d\n", i);
1.1       cgd       640: #endif
1.26      mycroft   641:
1.23      mycroft   642:                if (kt->kt_tag == KTT_DEVICE) {
1.26      mycroft   643:                        dev_t *dp = kt->kt_data;
1.23      mycroft   644:                        struct vnode *fvp;
1.26      mycroft   645:
1.23      mycroft   646:                        if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
                    647:                                continue;
                    648:                }
1.26      mycroft   649:
1.37      mycroft   650:                d.d_fileno = i + 3;
                    651:                d.d_namlen = kt->kt_namlen;
                    652:                bcopy(kt->kt_name, d.d_name, kt->kt_namlen + 1);
                    653:                d.d_type = kt->kt_type;
1.26      mycroft   654:
1.41      christos  655:                if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1.1       cgd       656:                        break;
1.57      fvdl      657:                if (cookies) {
1.38      mycroft   658:                        *cookies++ = i + 1;
1.57      fvdl      659:                        ncookies++;
                    660:                }
                    661:        }
                    662:
                    663:        if (ap->a_ncookies) {
                    664:                if (error) {
                    665:                        FREE(*ap->a_cookies, M_TEMP);
                    666:                        *ap->a_ncookies = 0;
                    667:                        *ap->a_cookies = NULL;
                    668:                } else
                    669:                        *ap->a_ncookies = ncookies;
1.1       cgd       670:        }
                    671:
1.38      mycroft   672:        uio->uio_offset = i;
1.1       cgd       673:        return (error);
                    674: }
                    675:
1.41      christos  676: int
                    677: kernfs_inactive(v)
                    678:        void *v;
                    679: {
1.23      mycroft   680:        struct vop_inactive_args /* {
                    681:                struct vnode *a_vp;
1.57      fvdl      682:                struct proc *a_p;
1.41      christos  683:        } */ *ap = v;
1.23      mycroft   684:        struct vnode *vp = ap->a_vp;
                    685:
                    686: #ifdef KERNFS_DIAGNOSTIC
1.51      christos  687:        printf("kernfs_inactive(%p)\n", vp);
1.23      mycroft   688: #endif
1.1       cgd       689:        /*
                    690:         * Clear out the v_type field to avoid
                    691:         * nasty things happening in vgone().
                    692:         */
1.57      fvdl      693:        VOP_UNLOCK(vp, 0);
1.1       cgd       694:        vp->v_type = VNON;
1.23      mycroft   695:        return (0);
                    696: }
                    697:
1.41      christos  698: int
                    699: kernfs_reclaim(v)
                    700:        void *v;
                    701: {
1.23      mycroft   702:        struct vop_reclaim_args /* {
                    703:                struct vnode *a_vp;
1.41      christos  704:        } */ *ap = v;
1.23      mycroft   705:        struct vnode *vp = ap->a_vp;
                    706:
1.1       cgd       707: #ifdef KERNFS_DIAGNOSTIC
1.51      christos  708:        printf("kernfs_reclaim(%p)\n", vp);
1.1       cgd       709: #endif
1.23      mycroft   710:        if (vp->v_data) {
                    711:                FREE(vp->v_data, M_TEMP);
                    712:                vp->v_data = 0;
                    713:        }
1.1       cgd       714:        return (0);
                    715: }
                    716:
                    717: /*
1.23      mycroft   718:  * Return POSIX pathconf information applicable to special devices.
                    719:  */
1.41      christos  720: int
                    721: kernfs_pathconf(v)
                    722:        void *v;
                    723: {
1.23      mycroft   724:        struct vop_pathconf_args /* {
                    725:                struct vnode *a_vp;
                    726:                int a_name;
1.29      cgd       727:                register_t *a_retval;
1.41      christos  728:        } */ *ap = v;
1.23      mycroft   729:
                    730:        switch (ap->a_name) {
                    731:        case _PC_LINK_MAX:
                    732:                *ap->a_retval = LINK_MAX;
                    733:                return (0);
                    734:        case _PC_MAX_CANON:
                    735:                *ap->a_retval = MAX_CANON;
                    736:                return (0);
                    737:        case _PC_MAX_INPUT:
                    738:                *ap->a_retval = MAX_INPUT;
                    739:                return (0);
                    740:        case _PC_PIPE_BUF:
                    741:                *ap->a_retval = PIPE_BUF;
                    742:                return (0);
                    743:        case _PC_CHOWN_RESTRICTED:
                    744:                *ap->a_retval = 1;
                    745:                return (0);
                    746:        case _PC_VDISABLE:
                    747:                *ap->a_retval = _POSIX_VDISABLE;
1.59    ! kleink    748:                return (0);
        !           749:        case _PC_SYNC_IO:
        !           750:                *ap->a_retval = 1;
1.23      mycroft   751:                return (0);
                    752:        default:
                    753:                return (EINVAL);
                    754:        }
                    755:        /* NOTREACHED */
                    756: }
                    757:
                    758: /*
                    759:  * Print out the contents of a /dev/fd vnode.
1.1       cgd       760:  */
                    761: /* ARGSUSED */
1.41      christos  762: int
                    763: kernfs_print(v)
                    764:        void *v;
1.23      mycroft   765: {
                    766:
1.47      christos  767:        printf("tag VT_KERNFS, kernfs vnode\n");
1.23      mycroft   768:        return (0);
                    769: }
                    770:
1.40      mycroft   771: int
1.41      christos  772: kernfs_link(v)
                    773:        void *v;
                    774: {
1.40      mycroft   775:        struct vop_link_args /* {
                    776:                struct vnode *a_dvp;
                    777:                struct vnode *a_vp;
                    778:                struct componentname *a_cnp;
1.41      christos  779:        } */ *ap = v;
1.40      mycroft   780:
                    781:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                    782:        vput(ap->a_dvp);
                    783:        return (EROFS);
                    784: }
                    785:
                    786: int
1.41      christos  787: kernfs_symlink(v)
                    788:        void *v;
                    789: {
1.40      mycroft   790:        struct vop_symlink_args /* {
                    791:                struct vnode *a_dvp;
                    792:                struct vnode **a_vpp;
                    793:                struct componentname *a_cnp;
                    794:                struct vattr *a_vap;
                    795:                char *a_target;
1.41      christos  796:        } */ *ap = v;
1.40      mycroft   797:
                    798:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                    799:        vput(ap->a_dvp);
                    800:        return (EROFS);
1.1       cgd       801: }

CVSweb <webmaster@jp.NetBSD.org>