[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.162

1.162   ! thorpej     1: /*     $NetBSD: kernfs_vnops.c,v 1.161 2019/08/29 06:43:13 hannken 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.
1.89      agc        18:  * 3. Neither the name of the University nor the names of its contributors
1.2       cgd        19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
1.1       cgd        21:  *
1.2       cgd        22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
1.1       cgd        33:  *
1.57      fvdl       34:  *     @(#)kernfs_vnops.c      8.15 (Berkeley) 5/21/95
1.1       cgd        35:  */
                     36:
                     37: /*
1.23      mycroft    38:  * Kernel parameter filesystem (/kern)
1.1       cgd        39:  */
1.77      lukem      40:
                     41: #include <sys/cdefs.h>
1.162   ! thorpej    42: __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.161 2019/08/29 06:43:13 hannken Exp $");
1.55      mrg        43:
1.14      mycroft    44: #include <sys/param.h>
                     45: #include <sys/systm.h>
                     46: #include <sys/kernel.h>
1.23      mycroft    47: #include <sys/vmmeter.h>
1.14      mycroft    48: #include <sys/time.h>
                     49: #include <sys/proc.h>
1.23      mycroft    50: #include <sys/vnode.h>
                     51: #include <sys/malloc.h>
1.14      mycroft    52: #include <sys/file.h>
                     53: #include <sys/stat.h>
                     54: #include <sys/mount.h>
                     55: #include <sys/namei.h>
                     56: #include <sys/buf.h>
1.23      mycroft    57: #include <sys/dirent.h>
1.28      mycroft    58: #include <sys/msgbuf.h>
1.44      mycroft    59:
                     60: #include <miscfs/genfs/genfs.h>
1.17      cgd        61: #include <miscfs/kernfs/kernfs.h>
1.151     christos   62: #include <miscfs/specfs/specdev.h>
1.63      mrg        63:
1.54      mrg        64: #include <uvm/uvm_extern.h>
                     65:
1.17      cgd        66: #define KSTRING        256             /* Largest I/O available via this filesystem */
                     67: #define        UIO_MX 32
1.1       cgd        68:
1.23      mycroft    69: #define        READ_MODE       (S_IRUSR|S_IRGRP|S_IROTH)
                     70: #define        WRITE_MODE      (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
1.101     cl         71: #define        UREAD_MODE      (S_IRUSR)
1.102     cl         72: #define        DIR_MODE        (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
                     73: #define        UDIR_MODE       (S_IRUSR|S_IXUSR)
1.23      mycroft    74:
1.90      itojun     75: #define N(s) sizeof(s)-1, s
1.75      jdolecek   76: const struct kern_target kern_targets[] = {
1.1       cgd        77: /* NOTE: The name must be less than UIO_MX-16 chars in length */
1.23      mycroft    78:      /*        name            data          tag           type  ro/rw */
1.98      darcy      79:      { DT_DIR, N("."),         0,            KFSkern,        VDIR, DIR_MODE   },
                     80:      { DT_DIR, N(".."),        0,            KFSroot,        VDIR, DIR_MODE   },
1.162   ! thorpej    81:      { DT_REG, N("boottime"),  0,            KFSboottime,    VREG, READ_MODE  },
1.109     christos   82:                        /* XXXUNCONST */
                     83:      { DT_REG, N("copyright"), __UNCONST(copyright),
1.98      darcy      84:                                             KFSstring,      VREG, READ_MODE  },
                     85:      { DT_REG, N("hostname"),  0,            KFShostname,    VREG, WRITE_MODE },
                     86:      { DT_REG, N("hz"),        &hz,          KFSint,         VREG, READ_MODE  },
                     87:      { DT_REG, N("loadavg"),   0,            KFSavenrun,     VREG, READ_MODE  },
                     88:      { DT_REG, N("msgbuf"),    0,           KFSmsgbuf,      VREG, READ_MODE  },
                     89:      { DT_REG, N("pagesize"),  &uvmexp.pagesize, KFSint,     VREG, READ_MODE  },
                     90:      { DT_REG, N("physmem"),   &physmem,     KFSint,         VREG, READ_MODE  },
1.17      cgd        91: #if 0
1.98      darcy      92:      { DT_DIR, N("root"),      0,            KFSnull,        VDIR, DIR_MODE   },
1.17      cgd        93: #endif
1.98      darcy      94:      { DT_BLK, N("rootdev"),   &rootdev,     KFSdevice,      VBLK, READ_MODE  },
                     95:      { DT_CHR, N("rrootdev"),  &rrootdev,    KFSdevice,      VCHR, READ_MODE  },
                     96:      { DT_REG, N("time"),      0,            KFStime,        VREG, READ_MODE  },
1.109     christos   97:                        /* XXXUNCONST */
                     98:      { DT_REG, N("version"),   __UNCONST(version),
1.98      darcy      99:                                             KFSstring,      VREG, READ_MODE  },
1.90      itojun    100: };
1.102     cl        101: const struct kern_target subdir_targets[] = {
                    102: /* NOTE: The name must be less than UIO_MX-16 chars in length */
                    103:      /*        name            data          tag           type  ro/rw */
                    104:      { DT_DIR, N("."),         0,            KFSsubdir,      VDIR, DIR_MODE   },
                    105:      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
                    106: };
1.23      mycroft   107: #undef N
1.102     cl        108: SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
                    109:        SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
1.90      itojun    110: int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.102     cl        111: const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
                    112: int nkern_dirs = 2;
1.90      itojun    113:
1.102     cl        114: int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
1.124     bouyer    115: int kernfs_try_xread(kfstype, const struct kernfs_node *, char **,
1.123     bouyer    116:     size_t, int);
1.102     cl        117: int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
                    118:     size_t, int);
                    119:
1.123     bouyer    120: static int kernfs_default_xread(void *v);
1.102     cl        121: static int kernfs_default_xwrite(void *v);
                    122: static int kernfs_default_fileop_getattr(void *);
                    123:
                    124: /* must include all fileop's */
                    125: const struct kernfs_fileop kernfs_default_fileops[] = {
1.123     bouyer    126:   { .kf_fileop = KERNFS_XREAD },
1.102     cl        127:   { .kf_fileop = KERNFS_XWRITE },
                    128:   { .kf_fileop = KERNFS_FILEOP_OPEN },
                    129:   { .kf_fileop = KERNFS_FILEOP_GETATTR,
1.125     christos  130:     .kf_vop = kernfs_default_fileop_getattr },
1.102     cl        131:   { .kf_fileop = KERNFS_FILEOP_IOCTL },
                    132:   { .kf_fileop = KERNFS_FILEOP_CLOSE },
1.125     christos  133:   { .kf_fileop = KERNFS_FILEOP_READ,
                    134:     .kf_vop = kernfs_default_xread },
                    135:   { .kf_fileop = KERNFS_FILEOP_WRITE,
                    136:     .kf_vop = kernfs_default_xwrite },
1.102     cl        137: };
1.1       cgd       138:
1.110     xtraeme   139: int    kernfs_lookup(void *);
1.85      jdolecek  140: #define        kernfs_create   genfs_eopnotsupp
                    141: #define        kernfs_mknod    genfs_eopnotsupp
1.110     xtraeme   142: int    kernfs_open(void *);
                    143: int    kernfs_close(void *);
                    144: int    kernfs_access(void *);
                    145: int    kernfs_getattr(void *);
                    146: int    kernfs_setattr(void *);
                    147: int    kernfs_read(void *);
                    148: int    kernfs_write(void *);
1.65      wrstuden  149: #define        kernfs_fcntl    genfs_fcntl
1.110     xtraeme   150: int    kernfs_ioctl(void *);
1.45      mycroft   151: #define        kernfs_poll     genfs_poll
1.57      fvdl      152: #define kernfs_revoke  genfs_revoke
1.44      mycroft   153: #define        kernfs_fsync    genfs_nullop
                    154: #define        kernfs_seek     genfs_nullop
1.85      jdolecek  155: #define        kernfs_remove   genfs_eopnotsupp
1.110     xtraeme   156: int    kernfs_link(void *);
1.85      jdolecek  157: #define        kernfs_rename   genfs_eopnotsupp
                    158: #define        kernfs_mkdir    genfs_eopnotsupp
                    159: #define        kernfs_rmdir    genfs_eopnotsupp
1.110     xtraeme   160: int    kernfs_symlink(void *);
                    161: int    kernfs_readdir(void *);
1.44      mycroft   162: #define        kernfs_readlink genfs_eopnotsupp
                    163: #define        kernfs_abortop  genfs_abortop
1.110     xtraeme   164: int    kernfs_inactive(void *);
                    165: int    kernfs_reclaim(void *);
1.64      wrstuden  166: #define        kernfs_lock     genfs_lock
                    167: #define        kernfs_unlock   genfs_unlock
1.44      mycroft   168: #define        kernfs_bmap     genfs_badop
                    169: #define        kernfs_strategy genfs_badop
1.110     xtraeme   170: int    kernfs_print(void *);
1.64      wrstuden  171: #define        kernfs_islocked genfs_islocked
1.110     xtraeme   172: int    kernfs_pathconf(void *);
1.62      kleink    173: #define        kernfs_advlock  genfs_einval
1.44      mycroft   174: #define        kernfs_bwrite   genfs_eopnotsupp
1.161     hannken   175: int    kernfs_getpages(void *);
1.79      chs       176: #define        kernfs_putpages genfs_putpages
1.41      christos  177:
1.110     xtraeme   178: static int     kernfs_xread(struct kernfs_node *, int, char **,
                    179:                                size_t, size_t *);
                    180: static int     kernfs_xwrite(const struct kernfs_node *, char *, size_t);
1.41      christos  181:
1.110     xtraeme   182: int (**kernfs_vnodeop_p)(void *);
1.71      jdolecek  183: const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
1.41      christos  184:        { &vop_default_desc, vn_default_error },
1.44      mycroft   185:        { &vop_lookup_desc, kernfs_lookup },            /* lookup */
                    186:        { &vop_create_desc, kernfs_create },            /* create */
                    187:        { &vop_mknod_desc, kernfs_mknod },              /* mknod */
                    188:        { &vop_open_desc, kernfs_open },                /* open */
                    189:        { &vop_close_desc, kernfs_close },              /* close */
                    190:        { &vop_access_desc, kernfs_access },            /* access */
                    191:        { &vop_getattr_desc, kernfs_getattr },          /* getattr */
                    192:        { &vop_setattr_desc, kernfs_setattr },          /* setattr */
                    193:        { &vop_read_desc, kernfs_read },                /* read */
                    194:        { &vop_write_desc, kernfs_write },              /* write */
1.154     dholland  195:        { &vop_fallocate_desc, genfs_eopnotsupp },      /* fallocate */
                    196:        { &vop_fdiscard_desc, genfs_eopnotsupp },       /* fdiscard */
1.65      wrstuden  197:        { &vop_fcntl_desc, kernfs_fcntl },              /* fcntl */
1.44      mycroft   198:        { &vop_ioctl_desc, kernfs_ioctl },              /* ioctl */
1.45      mycroft   199:        { &vop_poll_desc, kernfs_poll },                /* poll */
1.57      fvdl      200:        { &vop_revoke_desc, kernfs_revoke },            /* revoke */
1.44      mycroft   201:        { &vop_fsync_desc, kernfs_fsync },              /* fsync */
                    202:        { &vop_seek_desc, kernfs_seek },                /* seek */
                    203:        { &vop_remove_desc, kernfs_remove },            /* remove */
                    204:        { &vop_link_desc, kernfs_link },                /* link */
                    205:        { &vop_rename_desc, kernfs_rename },            /* rename */
                    206:        { &vop_mkdir_desc, kernfs_mkdir },              /* mkdir */
                    207:        { &vop_rmdir_desc, kernfs_rmdir },              /* rmdir */
                    208:        { &vop_symlink_desc, kernfs_symlink },          /* symlink */
                    209:        { &vop_readdir_desc, kernfs_readdir },          /* readdir */
                    210:        { &vop_readlink_desc, kernfs_readlink },        /* readlink */
                    211:        { &vop_abortop_desc, kernfs_abortop },          /* abortop */
                    212:        { &vop_inactive_desc, kernfs_inactive },        /* inactive */
                    213:        { &vop_reclaim_desc, kernfs_reclaim },          /* reclaim */
                    214:        { &vop_lock_desc, kernfs_lock },                /* lock */
                    215:        { &vop_unlock_desc, kernfs_unlock },            /* unlock */
                    216:        { &vop_bmap_desc, kernfs_bmap },                /* bmap */
                    217:        { &vop_strategy_desc, kernfs_strategy },        /* strategy */
                    218:        { &vop_print_desc, kernfs_print },              /* print */
                    219:        { &vop_islocked_desc, kernfs_islocked },        /* islocked */
                    220:        { &vop_pathconf_desc, kernfs_pathconf },        /* pathconf */
                    221:        { &vop_advlock_desc, kernfs_advlock },          /* advlock */
                    222:        { &vop_bwrite_desc, kernfs_bwrite },            /* bwrite */
1.161     hannken   223:        { &vop_getpages_desc, kernfs_getpages },        /* getpages */
1.79      chs       224:        { &vop_putpages_desc, kernfs_putpages },        /* putpages */
1.76      chs       225:        { NULL, NULL }
1.41      christos  226: };
1.71      jdolecek  227: const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
1.41      christos  228:        { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
                    229:
1.116     perry     230: static inline int
1.102     cl        231: kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
                    232: {
                    233:        if (a->kf_type < b->kf_type)
                    234:                return -1;
                    235:        if (a->kf_type > b->kf_type)
                    236:                return 1;
                    237:        if (a->kf_fileop < b->kf_fileop)
                    238:                return -1;
                    239:        if (a->kf_fileop > b->kf_fileop)
                    240:                return 1;
                    241:        return (0);
                    242: }
                    243:
                    244: SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
                    245:        SPLAY_INITIALIZER(kfsfileoptree);
                    246: SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
                    247: SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
                    248:
                    249: kfstype
                    250: kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
                    251: {
                    252:        static u_char nextfreetype = KFSlasttype;
                    253:        struct kernfs_fileop *dkf, *fkf, skf;
                    254:        int i;
                    255:
                    256:        /* XXX need to keep track of dkf's memory if we support
                    257:            deallocating types */
                    258:        dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
                    259:        memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
                    260:
                    261:        for (i = 0; i < sizeof(kernfs_default_fileops) /
                    262:                     sizeof(kernfs_default_fileops[0]); i++) {
                    263:                dkf[i].kf_type = nextfreetype;
                    264:                SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
                    265:        }
                    266:
                    267:        for (i = 0; i < nkf; i++) {
                    268:                skf.kf_type = nextfreetype;
                    269:                skf.kf_fileop = kf[i].kf_fileop;
                    270:                if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
1.125     christos  271:                        fkf->kf_vop = kf[i].kf_vop;
1.102     cl        272:        }
                    273:
                    274:        return nextfreetype++;
                    275: }
                    276:
                    277: int
                    278: kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
                    279: {
                    280:        struct kernfs_fileop *kf, skf;
                    281:
                    282:        skf.kf_type = type;
                    283:        skf.kf_fileop = fileop;
                    284:        if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
                    285:                if (kf->kf_vop)
                    286:                        return kf->kf_vop(v);
                    287:        return error;
                    288: }
                    289:
                    290: int
1.124     bouyer    291: kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp,
                    292:     size_t len, int error)
                    293: {
                    294:        struct kernfs_fileop *kf, skf;
                    295:
                    296:        skf.kf_type = type;
                    297:        skf.kf_fileop = KERNFS_XREAD;
                    298:        if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
                    299:                if (kf->kf_xread)
                    300:                        return kf->kf_xread(kfs, bfp, len);
                    301:        return error;
                    302: }
                    303:
                    304: int
1.109     christos  305: kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,
1.102     cl        306:     size_t len, int error)
                    307: {
                    308:        struct kernfs_fileop *kf, skf;
                    309:
                    310:        skf.kf_type = type;
                    311:        skf.kf_fileop = KERNFS_XWRITE;
                    312:        if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
                    313:                if (kf->kf_xwrite)
1.109     christos  314:                        return kf->kf_xwrite(kfs, bf, len);
1.102     cl        315:        return error;
                    316: }
                    317:
                    318: int
                    319: kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
                    320: {
                    321:        struct kernfs_subdir *ks, *parent;
                    322:
                    323:        if (pkt == NULL) {
                    324:                SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
                    325:                nkern_targets++;
                    326:                if (dkt->dkt_kt.kt_vtype == VDIR)
                    327:                        nkern_dirs++;
                    328:        } else {
                    329:                parent = (struct kernfs_subdir *)pkt->kt_data;
                    330:                SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
                    331:                parent->ks_nentries++;
                    332:                if (dkt->dkt_kt.kt_vtype == VDIR)
                    333:                        parent->ks_dirs++;
                    334:        }
                    335:        if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
                    336:                ks = malloc(sizeof(struct kernfs_subdir),
                    337:                    M_TEMP, M_WAITOK);
                    338:                SIMPLEQ_INIT(&ks->ks_entries);
                    339:                ks->ks_nentries = 2; /* . and .. */
                    340:                ks->ks_dirs = 2;
                    341:                ks->ks_parent = pkt ? pkt : &kern_targets[0];
                    342:                dkt->dkt_kt.kt_data = ks;
                    343:        }
                    344:        return 0;
                    345: }
                    346:
1.82      jdolecek  347: static int
1.136     dsl       348: kernfs_xread(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen)
1.1       cgd       349: {
1.90      itojun    350:        const struct kern_target *kt;
1.124     bouyer    351:        int err;
1.90      itojun    352:
                    353:        kt = kfs->kfs_kt;
1.1       cgd       354:
1.90      itojun    355:        switch (kfs->kfs_type) {
1.98      darcy     356:        case KFStime: {
1.1       cgd       357:                struct timeval tv;
1.28      mycroft   358:
1.1       cgd       359:                microtime(&tv);
1.135     christos  360:                snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec,
                    361:                    (long)tv.tv_usec);
1.1       cgd       362:                break;
                    363:        }
                    364:
1.162   ! thorpej   365:        case KFSboottime: {
        !           366:                struct timeval tv;
        !           367:
        !           368:                /*
        !           369:                 * Historically, /kern/boottime only contained seconds.
        !           370:                 */
        !           371:                getmicroboottime(&tv);
        !           372:                snprintf(*bufp, len, "%lld\n", (long long)tv.tv_sec);
        !           373:                break;
        !           374:        }
        !           375:
1.98      darcy     376:        case KFSint: {
1.1       cgd       377:                int *ip = kt->kt_data;
1.28      mycroft   378:
1.90      itojun    379:                snprintf(*bufp, len, "%d\n", *ip);
1.1       cgd       380:                break;
                    381:        }
                    382:
1.98      darcy     383:        case KFSstring: {
1.1       cgd       384:                char *cp = kt->kt_data;
                    385:
1.28      mycroft   386:                *bufp = cp;
                    387:                break;
                    388:        }
1.1       cgd       389:
1.98      darcy     390:        case KFSmsgbuf: {
1.28      mycroft   391:                long n;
                    392:
1.52      leo       393:                /*
                    394:                 * deal with cases where the message buffer has
                    395:                 * become corrupted.
                    396:                 */
1.159     christos  397:                if (!logenabled(msgbufp)) {
1.52      leo       398:                        msgbufenabled = 0;
                    399:                        return (ENXIO);
                    400:                }
                    401:
                    402:                /*
                    403:                 * Note that reads of /kern/msgbuf won't necessarily yield
                    404:                 * consistent results, if the message buffer is modified
                    405:                 * while the read is in progress.  The worst that can happen
                    406:                 * is that incorrect data will be read.  There's no way
                    407:                 * that this can crash the system unless the values in the
                    408:                 * message buffer header are corrupted, but that'll cause
                    409:                 * the system to die anyway.
                    410:                 */
1.82      jdolecek  411:                if (off >= msgbufp->msg_bufs) {
                    412:                        *wrlen = 0;
1.28      mycroft   413:                        return (0);
1.82      jdolecek  414:                }
1.28      mycroft   415:                n = msgbufp->msg_bufx + off;
1.52      leo       416:                if (n >= msgbufp->msg_bufs)
                    417:                        n -= msgbufp->msg_bufs;
1.160     riastrad  418:                len = uimin(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
1.28      mycroft   419:                *bufp = msgbufp->msg_bufc + n;
1.82      jdolecek  420:                *wrlen = len;
                    421:                return (0);
1.1       cgd       422:        }
                    423:
1.98      darcy     424:        case KFShostname: {
1.1       cgd       425:                char *cp = hostname;
1.127     jmmv      426:                size_t xlen = hostnamelen;
1.1       cgd       427:
1.90      itojun    428:                if (xlen >= (len - 2))
1.1       cgd       429:                        return (EINVAL);
                    430:
1.60      perry     431:                memcpy(*bufp, cp, xlen);
1.28      mycroft   432:                (*bufp)[xlen] = '\n';
                    433:                (*bufp)[xlen+1] = '\0';
1.1       cgd       434:                break;
                    435:        }
                    436:
1.98      darcy     437:        case KFSavenrun:
1.31      mycroft   438:                averunnable.fscale = FSCALE;
1.90      itojun    439:                snprintf(*bufp, len, "%d %d %d %ld\n",
1.23      mycroft   440:                    averunnable.ldavg[0], averunnable.ldavg[1],
                    441:                    averunnable.ldavg[2], averunnable.fscale);
1.1       cgd       442:                break;
                    443:
                    444:        default:
1.124     bouyer    445:                err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len,
                    446:                    EOPNOTSUPP);
                    447:                if (err)
                    448:                        return err;
1.1       cgd       449:        }
                    450:
1.28      mycroft   451:        len = strlen(*bufp);
                    452:        if (len <= off)
1.82      jdolecek  453:                *wrlen = 0;
                    454:        else {
                    455:                *bufp += off;
                    456:                *wrlen = len - off;
                    457:        }
                    458:        return (0);
1.1       cgd       459: }
                    460:
1.82      jdolecek  461: static int
1.136     dsl       462: kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len)
1.1       cgd       463: {
1.23      mycroft   464:
1.90      itojun    465:        switch (kfs->kfs_type) {
1.98      darcy     466:        case KFShostname:
1.109     christos  467:                if (bf[len-1] == '\n')
1.1       cgd       468:                        --len;
1.109     christos  469:                memcpy(hostname, bf, len);
1.17      cgd       470:                hostname[len] = '\0';
1.82      jdolecek  471:                hostnamelen = (size_t) len;
1.1       cgd       472:                return (0);
                    473:
                    474:        default:
1.109     christos  475:                return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO);
1.1       cgd       476:        }
                    477: }
                    478:
1.17      cgd       479:
                    480: /*
1.1       cgd       481:  * vp is the current namei directory
                    482:  * ndp is the name to locate in that directory...
                    483:  */
1.41      christos  484: int
1.136     dsl       485: kernfs_lookup(void *v)
1.41      christos  486: {
1.150     hannken   487:        struct vop_lookup_v2_args /* {
1.23      mycroft   488:                struct vnode * a_dvp;
                    489:                struct vnode ** a_vpp;
                    490:                struct componentname * a_cnp;
1.41      christos  491:        } */ *ap = v;
1.23      mycroft   492:        struct componentname *cnp = ap->a_cnp;
                    493:        struct vnode **vpp = ap->a_vpp;
                    494:        struct vnode *dvp = ap->a_dvp;
1.48      cgd       495:        const char *pname = cnp->cn_nameptr;
1.90      itojun    496:        const struct kernfs_node *kfs;
1.75      jdolecek  497:        const struct kern_target *kt;
1.102     cl        498:        const struct dyn_kern_target *dkt;
                    499:        const struct kernfs_subdir *ks;
1.129     chs       500:        int error, i;
1.23      mycroft   501:
1.35      mycroft   502:        *vpp = NULLVP;
                    503:
                    504:        if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
                    505:                return (EROFS);
                    506:
1.23      mycroft   507:        if (cnp->cn_namelen == 1 && *pname == '.') {
                    508:                *vpp = dvp;
1.139     pooka     509:                vref(dvp);
1.1       cgd       510:                return (0);
                    511:        }
1.13      cgd       512:
1.90      itojun    513:        kfs = VTOKERN(dvp);
                    514:        switch (kfs->kfs_type) {
1.98      darcy     515:        case KFSkern:
1.90      itojun    516:                /*
                    517:                 * Shouldn't get here with .. in the root node.
                    518:                 */
                    519:                if (cnp->cn_flags & ISDOTDOT)
                    520:                        return (EIO);
1.64      wrstuden  521:
1.102     cl        522:                for (i = 0; i < static_nkern_targets; i++) {
1.90      itojun    523:                        kt = &kern_targets[i];
                    524:                        if (cnp->cn_namelen == kt->kt_namlen &&
                    525:                            memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
                    526:                                goto found;
                    527:                }
1.102     cl        528:                SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
                    529:                        if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
                    530:                            memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
                    531:                                kt = &dkt->dkt_kt;
                    532:                                goto found;
                    533:                        }
                    534:                }
1.90      itojun    535:                break;
1.25      mycroft   536:
1.90      itojun    537:        found:
1.153     hannken   538:                error = vcache_get(dvp->v_mount, &kt, sizeof(kt), vpp);
                    539:                return error;
1.64      wrstuden  540:
1.102     cl        541:        case KFSsubdir:
                    542:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
                    543:                if (cnp->cn_flags & ISDOTDOT) {
                    544:                        kt = ks->ks_parent;
                    545:                        goto found;
                    546:                }
                    547:
                    548:                SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
                    549:                        if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
                    550:                            memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
                    551:                                kt = &dkt->dkt_kt;
                    552:                                goto found;
                    553:                        }
                    554:                }
                    555:                break;
                    556:
1.90      itojun    557:        default:
                    558:                return (ENOTDIR);
                    559:        }
                    560:
                    561:        return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
                    562: }
                    563:
                    564: int
1.136     dsl       565: kernfs_open(void *v)
1.90      itojun    566: {
                    567:        struct vop_open_args /* {
                    568:                struct vnode *a_vp;
                    569:                int a_mode;
1.120     elad      570:                kauth_cred_t a_cred;
1.90      itojun    571:        } */ *ap = v;
                    572:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    573:
1.146     drochner  574:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN, v, 0);
1.90      itojun    575: }
1.1       cgd       576:
1.90      itojun    577: int
1.136     dsl       578: kernfs_close(void *v)
1.90      itojun    579: {
                    580:        struct vop_close_args /* {
                    581:                struct vnode *a_vp;
                    582:                int a_fflag;
1.120     elad      583:                kauth_cred_t a_cred;
1.90      itojun    584:        } */ *ap = v;
                    585:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    586:
1.146     drochner  587:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE, v, 0);
1.1       cgd       588: }
                    589:
1.28      mycroft   590: int
1.136     dsl       591: kernfs_access(void *v)
1.41      christos  592: {
1.23      mycroft   593:        struct vop_access_args /* {
                    594:                struct vnode *a_vp;
1.34      mycroft   595:                int a_mode;
1.120     elad      596:                kauth_cred_t a_cred;
1.41      christos  597:        } */ *ap = v;
1.90      itojun    598:        struct vattr va;
                    599:        int error;
1.17      cgd       600:
1.133     pooka     601:        if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0)
1.90      itojun    602:                return (error);
1.49      mycroft   603:
1.145     elad      604:        return kauth_authorize_vnode(ap->a_cred,
1.147     plunky    605:            KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode),
1.145     elad      606:            ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode,
                    607:            va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
1.23      mycroft   608: }
                    609:
1.102     cl        610: static int
1.136     dsl       611: kernfs_default_fileop_getattr(void *v)
1.102     cl        612: {
                    613:        struct vop_getattr_args /* {
                    614:                struct vnode *a_vp;
                    615:                struct vattr *a_vap;
1.120     elad      616:                kauth_cred_t a_cred;
1.102     cl        617:        } */ *ap = v;
                    618:        struct vattr *vap = ap->a_vap;
                    619:
                    620:        vap->va_nlink = 1;
                    621:        vap->va_bytes = vap->va_size = 0;
                    622:
                    623:        return 0;
                    624: }
                    625:
1.41      christos  626: int
1.136     dsl       627: kernfs_getattr(void *v)
1.41      christos  628: {
1.23      mycroft   629:        struct vop_getattr_args /* {
                    630:                struct vnode *a_vp;
                    631:                struct vattr *a_vap;
1.120     elad      632:                kauth_cred_t a_cred;
1.41      christos  633:        } */ *ap = v;
1.90      itojun    634:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.102     cl        635:        struct kernfs_subdir *ks;
1.23      mycroft   636:        struct vattr *vap = ap->a_vap;
1.1       cgd       637:        int error = 0;
1.109     christos  638:        char strbuf[KSTRING], *bf;
1.90      itojun    639:        size_t nread, total;
1.1       cgd       640:
1.139     pooka     641:        vattr_null(vap);
1.90      itojun    642:        vap->va_type = ap->a_vp->v_type;
1.17      cgd       643:        vap->va_uid = 0;
                    644:        vap->va_gid = 0;
1.90      itojun    645:        vap->va_mode = kfs->kfs_mode;
                    646:        vap->va_fileid = kfs->kfs_fileno;
                    647:        vap->va_flags = 0;
1.23      mycroft   648:        vap->va_size = 0;
1.1       cgd       649:        vap->va_blocksize = DEV_BSIZE;
1.121     kardel    650:        /* Make all times be current TOD, except for the "boottime" node. */
1.132     elad      651:        if (kfs->kfs_kt->kt_namlen == 8 &&
1.92      dan       652:            !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
1.162   ! thorpej   653:                getnanoboottime(&vap->va_ctime);
1.92      dan       654:        } else {
1.121     kardel    655:                getnanotime(&vap->va_ctime);
1.92      dan       656:        }
1.81      lukem     657:        vap->va_atime = vap->va_mtime = vap->va_ctime;
1.1       cgd       658:        vap->va_gen = 0;
                    659:        vap->va_flags = 0;
                    660:        vap->va_rdev = 0;
                    661:        vap->va_bytes = 0;
                    662:
1.90      itojun    663:        switch (kfs->kfs_type) {
1.98      darcy     664:        case KFSkern:
1.102     cl        665:                vap->va_nlink = nkern_dirs;
1.90      itojun    666:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    667:                break;
                    668:
1.151     christos  669:        case KFSdevice:
                    670:                vap->va_nlink = 1;
                    671:                vap->va_rdev = ap->a_vp->v_rdev;
                    672:                break;
                    673:
1.98      darcy     674:        case KFSroot:
1.90      itojun    675:                vap->va_nlink = 1;
                    676:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    677:                break;
                    678:
1.102     cl        679:        case KFSsubdir:
                    680:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
                    681:                vap->va_nlink = ks->ks_dirs;
                    682:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    683:                break;
                    684:
1.98      darcy     685:        case KFSnull:
                    686:        case KFStime:
1.162   ! thorpej   687:        case KFSboottime:
1.98      darcy     688:        case KFSint:
                    689:        case KFSstring:
                    690:        case KFShostname:
                    691:        case KFSavenrun:
                    692:        case KFSmsgbuf:
1.1       cgd       693:                vap->va_nlink = 1;
1.84      jdolecek  694:                total = 0;
                    695:                do {
1.109     christos  696:                        bf = strbuf;
                    697:                        error = kernfs_xread(kfs, total, &bf,
1.90      itojun    698:                            sizeof(strbuf), &nread);
1.84      jdolecek  699:                        total += nread;
                    700:                } while (error == 0 && nread != 0);
1.90      itojun    701:                vap->va_bytes = vap->va_size = total;
                    702:                break;
                    703:
                    704:        default:
1.102     cl        705:                error = kernfs_try_fileop(kfs->kfs_type,
                    706:                    KERNFS_FILEOP_GETATTR, v, EINVAL);
1.90      itojun    707:                break;
1.1       cgd       708:        }
                    709:
                    710:        return (error);
                    711: }
                    712:
1.41      christos  713: /*ARGSUSED*/
                    714: int
1.128     christos  715: kernfs_setattr(void *v)
1.1       cgd       716: {
1.90      itojun    717:
1.1       cgd       718:        /*
1.17      cgd       719:         * Silently ignore attribute changes.
                    720:         * This allows for open with truncate to have no
                    721:         * effect until some data is written.  I want to
                    722:         * do it this way because all writes are atomic.
1.1       cgd       723:         */
1.17      cgd       724:        return (0);
1.1       cgd       725: }
                    726:
1.28      mycroft   727: int
1.136     dsl       728: kernfs_default_xread(void *v)
1.41      christos  729: {
1.23      mycroft   730:        struct vop_read_args /* {
                    731:                struct vnode *a_vp;
                    732:                struct uio *a_uio;
                    733:                int  a_ioflag;
1.120     elad      734:                kauth_cred_t a_cred;
1.41      christos  735:        } */ *ap = v;
1.23      mycroft   736:        struct uio *uio = ap->a_uio;
1.90      itojun    737:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.109     christos  738:        char strbuf[KSTRING], *bf;
1.114     christos  739:        int off;
1.82      jdolecek  740:        size_t len;
1.28      mycroft   741:        int error;
1.23      mycroft   742:
1.90      itojun    743:        if (ap->a_vp->v_type == VDIR)
1.144     njoly     744:                return EISDIR;
1.23      mycroft   745:
1.114     christos  746:        off = (int)uio->uio_offset;
1.112     christos  747:        /* Don't allow negative offsets */
1.114     christos  748:        if (off < 0)
1.112     christos  749:                return EINVAL;
                    750:
1.109     christos  751:        bf = strbuf;
                    752:        if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
                    753:                error = uiomove(bf, len, uio);
1.82      jdolecek  754:        return (error);
1.1       cgd       755: }
                    756:
1.123     bouyer    757: int
1.136     dsl       758: kernfs_read(void *v)
1.123     bouyer    759: {
                    760:        struct vop_read_args /* {
                    761:                struct vnode *a_vp;
                    762:                struct uio *a_uio;
                    763:                int  a_ioflag;
                    764:                struct ucred *a_cred;
                    765:        } */ *ap = v;
                    766:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    767:
1.124     bouyer    768:        if (kfs->kfs_type < KFSlasttype) {
                    769:                /* use default function */
                    770:                return kernfs_default_xread(v);
                    771:        }
                    772:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v,
                    773:           EOPNOTSUPP);
1.123     bouyer    774: }
                    775:
1.102     cl        776: static int
1.136     dsl       777: kernfs_default_xwrite(void *v)
1.41      christos  778: {
1.23      mycroft   779:        struct vop_write_args /* {
                    780:                struct vnode *a_vp;
                    781:                struct uio *a_uio;
                    782:                int  a_ioflag;
1.120     elad      783:                kauth_cred_t a_cred;
1.41      christos  784:        } */ *ap = v;
1.90      itojun    785:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.23      mycroft   786:        struct uio *uio = ap->a_uio;
1.127     jmmv      787:        int error;
                    788:        size_t xlen;
1.1       cgd       789:        char strbuf[KSTRING];
1.23      mycroft   790:
1.1       cgd       791:        if (uio->uio_offset != 0)
                    792:                return (EINVAL);
                    793:
1.160     riastrad  794:        xlen = uimin(uio->uio_resid, KSTRING-1);
1.41      christos  795:        if ((error = uiomove(strbuf, xlen, uio)) != 0)
1.1       cgd       796:                return (error);
                    797:
                    798:        if (uio->uio_resid != 0)
                    799:                return (EIO);
                    800:
                    801:        strbuf[xlen] = '\0';
1.17      cgd       802:        xlen = strlen(strbuf);
1.90      itojun    803:        return (kernfs_xwrite(kfs, strbuf, xlen));
1.1       cgd       804: }
                    805:
1.102     cl        806: int
1.136     dsl       807: kernfs_write(void *v)
1.102     cl        808: {
                    809:        struct vop_write_args /* {
                    810:                struct vnode *a_vp;
                    811:                struct uio *a_uio;
                    812:                int  a_ioflag;
1.120     elad      813:                kauth_cred_t a_cred;
1.102     cl        814:        } */ *ap = v;
                    815:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    816:
1.124     bouyer    817:        if (kfs->kfs_type < KFSlasttype) {
                    818:                /* use default function */
                    819:                return kernfs_default_xwrite(v);
                    820:        }
                    821:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v,
                    822:            EOPNOTSUPP);
1.102     cl        823: }
                    824:
                    825: int
1.136     dsl       826: kernfs_ioctl(void *v)
1.102     cl        827: {
                    828:        struct vop_ioctl_args /* {
                    829:                const struct vnodeop_desc *a_desc;
                    830:                struct vnode *a_vp;
                    831:                u_long a_command;
                    832:                void *a_data;
                    833:                int a_fflag;
1.120     elad      834:                kauth_cred_t a_cred;
1.102     cl        835:        } */ *ap = v;
                    836:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    837:
                    838:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
                    839:            EPASSTHROUGH);
                    840: }
                    841:
1.101     cl        842: static int
                    843: kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
1.152     hannken   844:     struct vop_readdir_args *ap)
1.101     cl        845: {
                    846:        struct kernfs_node *kfs;
                    847:        struct vnode *vp;
                    848:        int error;
                    849:
1.153     hannken   850:        if ((error = vcache_get(ap->a_vp->v_mount, &kt, sizeof(kt), &vp)) != 0)
1.101     cl        851:                return error;
1.151     christos  852:        kfs = VTOKERN(vp);
                    853:        d->d_fileno = kfs->kfs_fileno;
1.153     hannken   854:        vrele(vp);
1.101     cl        855:        return 0;
                    856: }
                    857:
                    858: static int
                    859: kernfs_setdirentfileno(struct dirent *d, off_t entry,
                    860:     struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
                    861:     const struct kern_target *kt, struct vop_readdir_args *ap)
                    862: {
                    863:        const struct kern_target *ikt;
                    864:        int error;
                    865:
                    866:        switch (entry) {
                    867:        case 0:
                    868:                d->d_fileno = thisdir_kfs->kfs_fileno;
                    869:                return 0;
                    870:        case 1:
                    871:                ikt = parent_kt;
                    872:                break;
                    873:        default:
                    874:                ikt = kt;
                    875:                break;
                    876:        }
                    877:        if (ikt != thisdir_kfs->kfs_kt) {
1.152     hannken   878:                if ((error = kernfs_setdirentfileno_kt(d, ikt, ap)) != 0)
1.101     cl        879:                        return error;
                    880:        } else
                    881:                d->d_fileno = thisdir_kfs->kfs_fileno;
                    882:        return 0;
                    883: }
                    884:
1.41      christos  885: int
1.136     dsl       886: kernfs_readdir(void *v)
1.41      christos  887: {
1.23      mycroft   888:        struct vop_readdir_args /* {
                    889:                struct vnode *a_vp;
                    890:                struct uio *a_uio;
1.120     elad      891:                kauth_cred_t a_cred;
1.26      mycroft   892:                int *a_eofflag;
1.57      fvdl      893:                off_t **a_cookies;
                    894:                int a_*ncookies;
1.41      christos  895:        } */ *ap = v;
1.23      mycroft   896:        struct uio *uio = ap->a_uio;
1.37      mycroft   897:        struct dirent d;
1.90      itojun    898:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.75      jdolecek  899:        const struct kern_target *kt;
1.102     cl        900:        const struct dyn_kern_target *dkt = NULL;
                    901:        const struct kernfs_subdir *ks;
                    902:        off_t i, j;
1.1       cgd       903:        int error;
1.57      fvdl      904:        off_t *cookies = NULL;
1.90      itojun    905:        int ncookies = 0, n;
1.23      mycroft   906:
1.37      mycroft   907:        if (uio->uio_resid < UIO_MX)
                    908:                return (EINVAL);
1.38      mycroft   909:        if (uio->uio_offset < 0)
1.37      mycroft   910:                return (EINVAL);
1.26      mycroft   911:
1.1       cgd       912:        error = 0;
1.38      mycroft   913:        i = uio->uio_offset;
1.90      itojun    914:        memset(&d, 0, sizeof(d));
                    915:        d.d_reclen = UIO_MX;
                    916:        ncookies = uio->uio_resid / UIO_MX;
                    917:
                    918:        switch (kfs->kfs_type) {
1.98      darcy     919:        case KFSkern:
1.90      itojun    920:                if (i >= nkern_targets)
                    921:                        return (0);
1.66      sommerfe  922:
1.90      itojun    923:                if (ap->a_ncookies) {
1.160     riastrad  924:                        ncookies = uimin(ncookies, (nkern_targets - i));
1.90      itojun    925:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                    926:                            M_WAITOK);
                    927:                        *ap->a_cookies = cookies;
                    928:                }
                    929:
                    930:                n = 0;
                    931:                for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1.102     cl        932:                        if (i < static_nkern_targets)
                    933:                                kt = &kern_targets[i];
                    934:                        else {
                    935:                                if (dkt == NULL) {
                    936:                                        dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
                    937:                                        for (j = static_nkern_targets; j < i &&
                    938:                                                     dkt != NULL; j++)
                    939:                                                dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                    940:                                        if (j != i)
                    941:                                                break;
                    942:                                } else {
                    943:                                        dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                    944:                                }
1.119     christos  945:                                if (dkt == NULL)
                    946:                                        break;
1.102     cl        947:                                kt = &dkt->dkt_kt;
                    948:                        }
1.98      darcy     949:                        if (kt->kt_tag == KFSdevice) {
1.94      itojun    950:                                dev_t *dp = kt->kt_data;
                    951:                                struct vnode *fvp;
                    952:
                    953:                                if (*dp == NODEV ||
                    954:                                    !vfinddev(*dp, kt->kt_vtype, &fvp))
                    955:                                        continue;
1.143     hannken   956:                                vrele(fvp);
1.94      itojun    957:                        }
1.141     pooka     958:                        if (kt->kt_tag == KFSmsgbuf) {
1.159     christos  959:                                if (!logenabled(msgbufp)) {
1.141     pooka     960:                                        continue;
                    961:                                }
                    962:                        }
1.90      itojun    963:                        d.d_namlen = kt->kt_namlen;
1.101     cl        964:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                    965:                            &kern_targets[0], kt, ap)) != 0)
                    966:                                break;
1.90      itojun    967:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                    968:                        d.d_type = kt->kt_type;
1.99      jrf       969:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun    970:                                break;
                    971:                        if (cookies)
                    972:                                *cookies++ = i + 1;
                    973:                        n++;
                    974:                }
                    975:                ncookies = n;
                    976:                break;
                    977:
1.98      darcy     978:        case KFSroot:
1.90      itojun    979:                if (i >= 2)
                    980:                        return 0;
                    981:
                    982:                if (ap->a_ncookies) {
1.160     riastrad  983:                        ncookies = uimin(ncookies, (2 - i));
1.90      itojun    984:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                    985:                            M_WAITOK);
                    986:                        *ap->a_cookies = cookies;
                    987:                }
                    988:
                    989:                n = 0;
                    990:                for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
                    991:                        kt = &kern_targets[i];
                    992:                        d.d_namlen = kt->kt_namlen;
                    993:                        d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
                    994:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                    995:                        d.d_type = kt->kt_type;
1.99      jrf       996:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun    997:                                break;
                    998:                        if (cookies)
                    999:                                *cookies++ = i + 1;
                   1000:                        n++;
                   1001:                }
                   1002:                ncookies = n;
                   1003:                break;
                   1004:
1.102     cl       1005:        case KFSsubdir:
                   1006:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
                   1007:                if (i >= ks->ks_nentries)
                   1008:                        return (0);
                   1009:
                   1010:                if (ap->a_ncookies) {
1.160     riastrad 1011:                        ncookies = uimin(ncookies, (ks->ks_nentries - i));
1.102     cl       1012:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1013:                            M_WAITOK);
                   1014:                        *ap->a_cookies = cookies;
                   1015:                }
                   1016:
                   1017:                dkt = SIMPLEQ_FIRST(&ks->ks_entries);
                   1018:                for (j = 0; j < i && dkt != NULL; j++)
                   1019:                        dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                   1020:                n = 0;
                   1021:                for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
                   1022:                        if (i < 2)
                   1023:                                kt = &subdir_targets[i];
                   1024:                        else {
                   1025:                                /* check if ks_nentries lied to us */
                   1026:                                if (dkt == NULL)
                   1027:                                        break;
                   1028:                                kt = &dkt->dkt_kt;
                   1029:                                dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                   1030:                        }
                   1031:                        if (kt->kt_tag == KFSdevice) {
                   1032:                                dev_t *dp = kt->kt_data;
                   1033:                                struct vnode *fvp;
                   1034:
                   1035:                                if (*dp == NODEV ||
                   1036:                                    !vfinddev(*dp, kt->kt_vtype, &fvp))
                   1037:                                        continue;
1.143     hannken  1038:                                vrele(fvp);
1.102     cl       1039:                        }
                   1040:                        d.d_namlen = kt->kt_namlen;
                   1041:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                   1042:                            ks->ks_parent, kt, ap)) != 0)
                   1043:                                break;
                   1044:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1045:                        d.d_type = kt->kt_type;
1.103     jrf      1046:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.102     cl       1047:                                break;
                   1048:                        if (cookies)
                   1049:                                *cookies++ = i + 1;
                   1050:                        n++;
                   1051:                }
                   1052:                ncookies = n;
                   1053:                break;
                   1054:
1.90      itojun   1055:        default:
                   1056:                error = ENOTDIR;
                   1057:                break;
1.57      fvdl     1058:        }
                   1059:
                   1060:        if (ap->a_ncookies) {
                   1061:                if (error) {
1.90      itojun   1062:                        if (cookies)
                   1063:                                free(*ap->a_cookies, M_TEMP);
1.57      fvdl     1064:                        *ap->a_ncookies = 0;
                   1065:                        *ap->a_cookies = NULL;
                   1066:                } else
                   1067:                        *ap->a_ncookies = ncookies;
1.1       cgd      1068:        }
                   1069:
1.38      mycroft  1070:        uio->uio_offset = i;
1.1       cgd      1071:        return (error);
                   1072: }
                   1073:
1.41      christos 1074: int
1.136     dsl      1075: kernfs_inactive(void *v)
1.41      christos 1076: {
1.157     riastrad 1077:        struct vop_inactive_v2_args /* {
1.23      mycroft  1078:                struct vnode *a_vp;
1.134     ad       1079:                bool *a_recycle;
1.41      christos 1080:        } */ *ap = v;
1.23      mycroft  1081:
1.134     ad       1082:        *ap->a_recycle = false;
1.157     riastrad 1083:
1.23      mycroft  1084:        return (0);
                   1085: }
                   1086:
1.41      christos 1087: int
1.136     dsl      1088: kernfs_reclaim(void *v)
1.41      christos 1089: {
1.158     riastrad 1090:        struct vop_reclaim_v2_args /* {
1.23      mycroft  1091:                struct vnode *a_vp;
1.41      christos 1092:        } */ *ap = v;
1.153     hannken  1093:        struct vnode *vp = ap->a_vp;
                   1094:        struct kernfs_node *kfs = VTOKERN(vp);
                   1095:
1.158     riastrad 1096:        VOP_UNLOCK(vp);
                   1097:
1.153     hannken  1098:        vp->v_data = NULL;
                   1099:        mutex_enter(&kfs_lock);
                   1100:        TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list);
                   1101:        mutex_exit(&kfs_lock);
                   1102:        kmem_free(kfs, sizeof(struct kernfs_node));
1.23      mycroft  1103:
1.153     hannken  1104:        return 0;
1.1       cgd      1105: }
                   1106:
                   1107: /*
1.23      mycroft  1108:  * Return POSIX pathconf information applicable to special devices.
                   1109:  */
1.41      christos 1110: int
1.136     dsl      1111: kernfs_pathconf(void *v)
1.41      christos 1112: {
1.23      mycroft  1113:        struct vop_pathconf_args /* {
                   1114:                struct vnode *a_vp;
                   1115:                int a_name;
1.29      cgd      1116:                register_t *a_retval;
1.41      christos 1117:        } */ *ap = v;
1.23      mycroft  1118:
                   1119:        switch (ap->a_name) {
                   1120:        case _PC_LINK_MAX:
                   1121:                *ap->a_retval = LINK_MAX;
                   1122:                return (0);
                   1123:        case _PC_MAX_CANON:
                   1124:                *ap->a_retval = MAX_CANON;
                   1125:                return (0);
                   1126:        case _PC_MAX_INPUT:
                   1127:                *ap->a_retval = MAX_INPUT;
                   1128:                return (0);
                   1129:        case _PC_PIPE_BUF:
                   1130:                *ap->a_retval = PIPE_BUF;
                   1131:                return (0);
                   1132:        case _PC_CHOWN_RESTRICTED:
                   1133:                *ap->a_retval = 1;
                   1134:                return (0);
                   1135:        case _PC_VDISABLE:
                   1136:                *ap->a_retval = _POSIX_VDISABLE;
1.59      kleink   1137:                return (0);
                   1138:        case _PC_SYNC_IO:
                   1139:                *ap->a_retval = 1;
1.23      mycroft  1140:                return (0);
                   1141:        default:
                   1142:                return (EINVAL);
                   1143:        }
                   1144:        /* NOTREACHED */
                   1145: }
                   1146:
                   1147: /*
                   1148:  * Print out the contents of a /dev/fd vnode.
1.1       cgd      1149:  */
                   1150: /* ARGSUSED */
1.41      christos 1151: int
1.128     christos 1152: kernfs_print(void *v)
1.23      mycroft  1153: {
                   1154:
1.47      christos 1155:        printf("tag VT_KERNFS, kernfs vnode\n");
1.23      mycroft  1156:        return (0);
                   1157: }
                   1158:
1.40      mycroft  1159: int
1.136     dsl      1160: kernfs_link(void *v)
1.41      christos 1161: {
1.155     riastrad 1162:        struct vop_link_v2_args /* {
1.40      mycroft  1163:                struct vnode *a_dvp;
1.107     perry    1164:                struct vnode *a_vp;
1.40      mycroft  1165:                struct componentname *a_cnp;
1.41      christos 1166:        } */ *ap = v;
1.107     perry    1167:
1.40      mycroft  1168:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                   1169:        return (EROFS);
                   1170: }
                   1171:
                   1172: int
1.136     dsl      1173: kernfs_symlink(void *v)
1.41      christos 1174: {
1.149     hannken  1175:        struct vop_symlink_v3_args /* {
1.40      mycroft  1176:                struct vnode *a_dvp;
                   1177:                struct vnode **a_vpp;
                   1178:                struct componentname *a_cnp;
                   1179:                struct vattr *a_vap;
                   1180:                char *a_target;
1.41      christos 1181:        } */ *ap = v;
1.107     perry    1182:
1.40      mycroft  1183:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                   1184:        return (EROFS);
1.1       cgd      1185: }
1.161     hannken  1186:
                   1187: int
                   1188: kernfs_getpages(void *v)
                   1189: {
                   1190:        struct vop_getpages_args /* {
                   1191:                struct vnode *a_vp;
                   1192:                voff_t a_offset;
                   1193:                struct vm_page **a_m;
                   1194:                int *a_count;
                   1195:                int a_centeridx;
                   1196:                vm_prot_t a_access_type;
                   1197:                int a_advice;
                   1198:                int a_flags;
                   1199:        } */ *ap = v;
                   1200:
                   1201:        if ((ap->a_flags & PGO_LOCKED) == 0)
                   1202:                mutex_exit(ap->a_vp->v_interlock);
                   1203:
                   1204:        return (EFAULT);
                   1205: }

CVSweb <webmaster@jp.NetBSD.org>