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

1.145   ! elad        1: /*     $NetBSD: kernfs_vnops.c,v 1.144 2011/12/12 19:11:22 njoly 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.145   ! elad       42: __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.144 2011/12/12 19:11:22 njoly Exp $");
1.90      itojun     43:
                     44: #ifdef _KERNEL_OPT
                     45: #include "opt_ipsec.h"
                     46: #endif
1.55      mrg        47:
1.14      mycroft    48: #include <sys/param.h>
                     49: #include <sys/systm.h>
                     50: #include <sys/kernel.h>
1.23      mycroft    51: #include <sys/vmmeter.h>
1.14      mycroft    52: #include <sys/time.h>
                     53: #include <sys/proc.h>
1.23      mycroft    54: #include <sys/vnode.h>
                     55: #include <sys/malloc.h>
1.14      mycroft    56: #include <sys/file.h>
                     57: #include <sys/stat.h>
                     58: #include <sys/mount.h>
                     59: #include <sys/namei.h>
                     60: #include <sys/buf.h>
1.23      mycroft    61: #include <sys/dirent.h>
1.28      mycroft    62: #include <sys/msgbuf.h>
1.44      mycroft    63:
                     64: #include <miscfs/genfs/genfs.h>
1.17      cgd        65: #include <miscfs/kernfs/kernfs.h>
1.63      mrg        66:
1.90      itojun     67: #ifdef IPSEC
                     68: #include <sys/mbuf.h>
                     69: #include <net/route.h>
                     70: #include <netinet/in.h>
                     71: #include <netinet6/ipsec.h>
                     72: #include <netkey/key.h>
                     73: #endif
                     74:
1.54      mrg        75: #include <uvm/uvm_extern.h>
                     76:
1.17      cgd        77: #define KSTRING        256             /* Largest I/O available via this filesystem */
                     78: #define        UIO_MX 32
1.1       cgd        79:
1.23      mycroft    80: #define        READ_MODE       (S_IRUSR|S_IRGRP|S_IROTH)
                     81: #define        WRITE_MODE      (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
1.101     cl         82: #define        UREAD_MODE      (S_IRUSR)
1.102     cl         83: #define        DIR_MODE        (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
                     84: #define        UDIR_MODE       (S_IRUSR|S_IXUSR)
1.23      mycroft    85:
1.90      itojun     86: #define N(s) sizeof(s)-1, s
1.75      jdolecek   87: const struct kern_target kern_targets[] = {
1.1       cgd        88: /* NOTE: The name must be less than UIO_MX-16 chars in length */
1.23      mycroft    89:      /*        name            data          tag           type  ro/rw */
1.98      darcy      90:      { DT_DIR, N("."),         0,            KFSkern,        VDIR, DIR_MODE   },
                     91:      { DT_DIR, N(".."),        0,            KFSroot,        VDIR, DIR_MODE   },
                     92:      { DT_REG, N("boottime"),  &boottime.tv_sec, KFSint,     VREG, READ_MODE  },
1.109     christos   93:                        /* XXXUNCONST */
                     94:      { DT_REG, N("copyright"), __UNCONST(copyright),
1.98      darcy      95:                                             KFSstring,      VREG, READ_MODE  },
                     96:      { DT_REG, N("hostname"),  0,            KFShostname,    VREG, WRITE_MODE },
                     97:      { DT_REG, N("hz"),        &hz,          KFSint,         VREG, READ_MODE  },
1.90      itojun     98: #ifdef IPSEC
1.98      darcy      99:      { DT_DIR, N("ipsecsa"),   0,           KFSipsecsadir,  VDIR, UDIR_MODE  },
                    100:      { DT_DIR, N("ipsecsp"),   0,           KFSipsecspdir,  VDIR, UDIR_MODE  },
1.90      itojun    101: #endif
1.98      darcy     102:      { DT_REG, N("loadavg"),   0,            KFSavenrun,     VREG, READ_MODE  },
                    103:      { DT_REG, N("msgbuf"),    0,           KFSmsgbuf,      VREG, READ_MODE  },
                    104:      { DT_REG, N("pagesize"),  &uvmexp.pagesize, KFSint,     VREG, READ_MODE  },
                    105:      { DT_REG, N("physmem"),   &physmem,     KFSint,         VREG, READ_MODE  },
1.17      cgd       106: #if 0
1.98      darcy     107:      { DT_DIR, N("root"),      0,            KFSnull,        VDIR, DIR_MODE   },
1.17      cgd       108: #endif
1.98      darcy     109:      { DT_BLK, N("rootdev"),   &rootdev,     KFSdevice,      VBLK, READ_MODE  },
                    110:      { DT_CHR, N("rrootdev"),  &rrootdev,    KFSdevice,      VCHR, READ_MODE  },
                    111:      { DT_REG, N("time"),      0,            KFStime,        VREG, READ_MODE  },
1.109     christos  112:                        /* XXXUNCONST */
                    113:      { DT_REG, N("version"),   __UNCONST(version),
1.98      darcy     114:                                             KFSstring,      VREG, READ_MODE  },
1.90      itojun    115: };
1.102     cl        116: const struct kern_target subdir_targets[] = {
                    117: /* NOTE: The name must be less than UIO_MX-16 chars in length */
                    118:      /*        name            data          tag           type  ro/rw */
                    119:      { DT_DIR, N("."),         0,            KFSsubdir,      VDIR, DIR_MODE   },
                    120:      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
                    121: };
1.90      itojun    122: #ifdef IPSEC
                    123: const struct kern_target ipsecsa_targets[] = {
                    124: /* NOTE: The name must be less than UIO_MX-16 chars in length */
                    125:      /*        name            data          tag           type  ro/rw */
1.98      darcy     126:      { DT_DIR, N("."),         0,            KFSipsecsadir,  VDIR, DIR_MODE   },
                    127:      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
1.90      itojun    128: };
                    129: const struct kern_target ipsecsp_targets[] = {
                    130: /* NOTE: The name must be less than UIO_MX-16 chars in length */
                    131:      /*        name            data          tag           type  ro/rw */
1.98      darcy     132:      { DT_DIR, N("."),         0,            KFSipsecspdir,  VDIR, DIR_MODE   },
                    133:      { DT_DIR, N(".."),        0,            KFSkern,        VDIR, DIR_MODE   },
1.90      itojun    134: };
1.101     cl        135: const struct kern_target ipsecsa_kt =
                    136:      { DT_DIR, N(""),          0,            KFSipsecsa,     VREG, UREAD_MODE };
                    137: const struct kern_target ipsecsp_kt =
                    138:      { DT_DIR, N(""),          0,            KFSipsecsp,     VREG, UREAD_MODE };
1.90      itojun    139: #endif
1.23      mycroft   140: #undef N
1.102     cl        141: SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
                    142:        SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
1.90      itojun    143: int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.102     cl        144: const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.90      itojun    145: #ifdef IPSEC
                    146: int nipsecsa_targets = sizeof(ipsecsa_targets) / sizeof(ipsecsa_targets[0]);
                    147: int nipsecsp_targets = sizeof(ipsecsp_targets) / sizeof(ipsecsp_targets[0]);
1.102     cl        148: int nkern_dirs = 4; /* 2 extra subdirs */
                    149: #else
                    150: int nkern_dirs = 2;
1.90      itojun    151: #endif
                    152:
1.102     cl        153: int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
1.124     bouyer    154: int kernfs_try_xread(kfstype, const struct kernfs_node *, char **,
1.123     bouyer    155:     size_t, int);
1.102     cl        156: int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
                    157:     size_t, int);
                    158:
1.123     bouyer    159: static int kernfs_default_xread(void *v);
1.102     cl        160: static int kernfs_default_xwrite(void *v);
                    161: static int kernfs_default_fileop_getattr(void *);
                    162:
                    163: /* must include all fileop's */
                    164: const struct kernfs_fileop kernfs_default_fileops[] = {
1.123     bouyer    165:   { .kf_fileop = KERNFS_XREAD },
1.102     cl        166:   { .kf_fileop = KERNFS_XWRITE },
                    167:   { .kf_fileop = KERNFS_FILEOP_OPEN },
                    168:   { .kf_fileop = KERNFS_FILEOP_GETATTR,
1.125     christos  169:     .kf_vop = kernfs_default_fileop_getattr },
1.102     cl        170:   { .kf_fileop = KERNFS_FILEOP_IOCTL },
                    171:   { .kf_fileop = KERNFS_FILEOP_CLOSE },
1.125     christos  172:   { .kf_fileop = KERNFS_FILEOP_READ,
                    173:     .kf_vop = kernfs_default_xread },
                    174:   { .kf_fileop = KERNFS_FILEOP_WRITE,
                    175:     .kf_vop = kernfs_default_xwrite },
1.102     cl        176: };
1.1       cgd       177:
1.110     xtraeme   178: int    kernfs_lookup(void *);
1.85      jdolecek  179: #define        kernfs_create   genfs_eopnotsupp
                    180: #define        kernfs_mknod    genfs_eopnotsupp
1.110     xtraeme   181: int    kernfs_open(void *);
                    182: int    kernfs_close(void *);
                    183: int    kernfs_access(void *);
                    184: int    kernfs_getattr(void *);
                    185: int    kernfs_setattr(void *);
                    186: int    kernfs_read(void *);
                    187: int    kernfs_write(void *);
1.65      wrstuden  188: #define        kernfs_fcntl    genfs_fcntl
1.110     xtraeme   189: int    kernfs_ioctl(void *);
1.45      mycroft   190: #define        kernfs_poll     genfs_poll
1.57      fvdl      191: #define kernfs_revoke  genfs_revoke
1.44      mycroft   192: #define        kernfs_fsync    genfs_nullop
                    193: #define        kernfs_seek     genfs_nullop
1.85      jdolecek  194: #define        kernfs_remove   genfs_eopnotsupp
1.110     xtraeme   195: int    kernfs_link(void *);
1.85      jdolecek  196: #define        kernfs_rename   genfs_eopnotsupp
                    197: #define        kernfs_mkdir    genfs_eopnotsupp
                    198: #define        kernfs_rmdir    genfs_eopnotsupp
1.110     xtraeme   199: int    kernfs_symlink(void *);
                    200: int    kernfs_readdir(void *);
1.44      mycroft   201: #define        kernfs_readlink genfs_eopnotsupp
                    202: #define        kernfs_abortop  genfs_abortop
1.110     xtraeme   203: int    kernfs_inactive(void *);
                    204: int    kernfs_reclaim(void *);
1.64      wrstuden  205: #define        kernfs_lock     genfs_lock
                    206: #define        kernfs_unlock   genfs_unlock
1.44      mycroft   207: #define        kernfs_bmap     genfs_badop
                    208: #define        kernfs_strategy genfs_badop
1.110     xtraeme   209: int    kernfs_print(void *);
1.64      wrstuden  210: #define        kernfs_islocked genfs_islocked
1.110     xtraeme   211: int    kernfs_pathconf(void *);
1.62      kleink    212: #define        kernfs_advlock  genfs_einval
1.44      mycroft   213: #define        kernfs_bwrite   genfs_eopnotsupp
1.79      chs       214: #define        kernfs_putpages genfs_putpages
1.41      christos  215:
1.110     xtraeme   216: static int     kernfs_xread(struct kernfs_node *, int, char **,
                    217:                                size_t, size_t *);
                    218: static int     kernfs_xwrite(const struct kernfs_node *, char *, size_t);
1.41      christos  219:
1.110     xtraeme   220: int (**kernfs_vnodeop_p)(void *);
1.71      jdolecek  221: const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
1.41      christos  222:        { &vop_default_desc, vn_default_error },
1.44      mycroft   223:        { &vop_lookup_desc, kernfs_lookup },            /* lookup */
                    224:        { &vop_create_desc, kernfs_create },            /* create */
                    225:        { &vop_mknod_desc, kernfs_mknod },              /* mknod */
                    226:        { &vop_open_desc, kernfs_open },                /* open */
                    227:        { &vop_close_desc, kernfs_close },              /* close */
                    228:        { &vop_access_desc, kernfs_access },            /* access */
                    229:        { &vop_getattr_desc, kernfs_getattr },          /* getattr */
                    230:        { &vop_setattr_desc, kernfs_setattr },          /* setattr */
                    231:        { &vop_read_desc, kernfs_read },                /* read */
                    232:        { &vop_write_desc, kernfs_write },              /* write */
1.65      wrstuden  233:        { &vop_fcntl_desc, kernfs_fcntl },              /* fcntl */
1.44      mycroft   234:        { &vop_ioctl_desc, kernfs_ioctl },              /* ioctl */
1.45      mycroft   235:        { &vop_poll_desc, kernfs_poll },                /* poll */
1.57      fvdl      236:        { &vop_revoke_desc, kernfs_revoke },            /* revoke */
1.44      mycroft   237:        { &vop_fsync_desc, kernfs_fsync },              /* fsync */
                    238:        { &vop_seek_desc, kernfs_seek },                /* seek */
                    239:        { &vop_remove_desc, kernfs_remove },            /* remove */
                    240:        { &vop_link_desc, kernfs_link },                /* link */
                    241:        { &vop_rename_desc, kernfs_rename },            /* rename */
                    242:        { &vop_mkdir_desc, kernfs_mkdir },              /* mkdir */
                    243:        { &vop_rmdir_desc, kernfs_rmdir },              /* rmdir */
                    244:        { &vop_symlink_desc, kernfs_symlink },          /* symlink */
                    245:        { &vop_readdir_desc, kernfs_readdir },          /* readdir */
                    246:        { &vop_readlink_desc, kernfs_readlink },        /* readlink */
                    247:        { &vop_abortop_desc, kernfs_abortop },          /* abortop */
                    248:        { &vop_inactive_desc, kernfs_inactive },        /* inactive */
                    249:        { &vop_reclaim_desc, kernfs_reclaim },          /* reclaim */
                    250:        { &vop_lock_desc, kernfs_lock },                /* lock */
                    251:        { &vop_unlock_desc, kernfs_unlock },            /* unlock */
                    252:        { &vop_bmap_desc, kernfs_bmap },                /* bmap */
                    253:        { &vop_strategy_desc, kernfs_strategy },        /* strategy */
                    254:        { &vop_print_desc, kernfs_print },              /* print */
                    255:        { &vop_islocked_desc, kernfs_islocked },        /* islocked */
                    256:        { &vop_pathconf_desc, kernfs_pathconf },        /* pathconf */
                    257:        { &vop_advlock_desc, kernfs_advlock },          /* advlock */
                    258:        { &vop_bwrite_desc, kernfs_bwrite },            /* bwrite */
1.79      chs       259:        { &vop_putpages_desc, kernfs_putpages },        /* putpages */
1.76      chs       260:        { NULL, NULL }
1.41      christos  261: };
1.71      jdolecek  262: const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
1.41      christos  263:        { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
                    264:
1.116     perry     265: static inline int
1.102     cl        266: kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
                    267: {
                    268:        if (a->kf_type < b->kf_type)
                    269:                return -1;
                    270:        if (a->kf_type > b->kf_type)
                    271:                return 1;
                    272:        if (a->kf_fileop < b->kf_fileop)
                    273:                return -1;
                    274:        if (a->kf_fileop > b->kf_fileop)
                    275:                return 1;
                    276:        return (0);
                    277: }
                    278:
                    279: SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
                    280:        SPLAY_INITIALIZER(kfsfileoptree);
                    281: SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
                    282: SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
                    283:
                    284: kfstype
                    285: kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
                    286: {
                    287:        static u_char nextfreetype = KFSlasttype;
                    288:        struct kernfs_fileop *dkf, *fkf, skf;
                    289:        int i;
                    290:
                    291:        /* XXX need to keep track of dkf's memory if we support
                    292:            deallocating types */
                    293:        dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
                    294:        memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
                    295:
                    296:        for (i = 0; i < sizeof(kernfs_default_fileops) /
                    297:                     sizeof(kernfs_default_fileops[0]); i++) {
                    298:                dkf[i].kf_type = nextfreetype;
                    299:                SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
                    300:        }
                    301:
                    302:        for (i = 0; i < nkf; i++) {
                    303:                skf.kf_type = nextfreetype;
                    304:                skf.kf_fileop = kf[i].kf_fileop;
                    305:                if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
1.125     christos  306:                        fkf->kf_vop = kf[i].kf_vop;
1.102     cl        307:        }
                    308:
                    309:        return nextfreetype++;
                    310: }
                    311:
                    312: int
                    313: kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
                    314: {
                    315:        struct kernfs_fileop *kf, skf;
                    316:
                    317:        skf.kf_type = type;
                    318:        skf.kf_fileop = fileop;
                    319:        if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
                    320:                if (kf->kf_vop)
                    321:                        return kf->kf_vop(v);
                    322:        return error;
                    323: }
                    324:
                    325: int
1.124     bouyer    326: kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp,
                    327:     size_t len, int error)
                    328: {
                    329:        struct kernfs_fileop *kf, skf;
                    330:
                    331:        skf.kf_type = type;
                    332:        skf.kf_fileop = KERNFS_XREAD;
                    333:        if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
                    334:                if (kf->kf_xread)
                    335:                        return kf->kf_xread(kfs, bfp, len);
                    336:        return error;
                    337: }
                    338:
                    339: int
1.109     christos  340: kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,
1.102     cl        341:     size_t len, int error)
                    342: {
                    343:        struct kernfs_fileop *kf, skf;
                    344:
                    345:        skf.kf_type = type;
                    346:        skf.kf_fileop = KERNFS_XWRITE;
                    347:        if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
                    348:                if (kf->kf_xwrite)
1.109     christos  349:                        return kf->kf_xwrite(kfs, bf, len);
1.102     cl        350:        return error;
                    351: }
                    352:
                    353: int
                    354: kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
                    355: {
                    356:        struct kernfs_subdir *ks, *parent;
                    357:
                    358:        if (pkt == NULL) {
                    359:                SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
                    360:                nkern_targets++;
                    361:                if (dkt->dkt_kt.kt_vtype == VDIR)
                    362:                        nkern_dirs++;
                    363:        } else {
                    364:                parent = (struct kernfs_subdir *)pkt->kt_data;
                    365:                SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
                    366:                parent->ks_nentries++;
                    367:                if (dkt->dkt_kt.kt_vtype == VDIR)
                    368:                        parent->ks_dirs++;
                    369:        }
                    370:        if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
                    371:                ks = malloc(sizeof(struct kernfs_subdir),
                    372:                    M_TEMP, M_WAITOK);
                    373:                SIMPLEQ_INIT(&ks->ks_entries);
                    374:                ks->ks_nentries = 2; /* . and .. */
                    375:                ks->ks_dirs = 2;
                    376:                ks->ks_parent = pkt ? pkt : &kern_targets[0];
                    377:                dkt->dkt_kt.kt_data = ks;
                    378:        }
                    379:        return 0;
                    380: }
                    381:
1.82      jdolecek  382: static int
1.136     dsl       383: kernfs_xread(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen)
1.1       cgd       384: {
1.90      itojun    385:        const struct kern_target *kt;
                    386: #ifdef IPSEC
                    387:        struct mbuf *m;
                    388: #endif
1.124     bouyer    389:        int err;
1.90      itojun    390:
                    391:        kt = kfs->kfs_kt;
1.1       cgd       392:
1.90      itojun    393:        switch (kfs->kfs_type) {
1.98      darcy     394:        case KFStime: {
1.1       cgd       395:                struct timeval tv;
1.28      mycroft   396:
1.1       cgd       397:                microtime(&tv);
1.135     christos  398:                snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec,
                    399:                    (long)tv.tv_usec);
1.1       cgd       400:                break;
                    401:        }
                    402:
1.98      darcy     403:        case KFSint: {
1.1       cgd       404:                int *ip = kt->kt_data;
1.28      mycroft   405:
1.90      itojun    406:                snprintf(*bufp, len, "%d\n", *ip);
1.1       cgd       407:                break;
                    408:        }
                    409:
1.98      darcy     410:        case KFSstring: {
1.1       cgd       411:                char *cp = kt->kt_data;
                    412:
1.28      mycroft   413:                *bufp = cp;
                    414:                break;
                    415:        }
1.1       cgd       416:
1.98      darcy     417:        case KFSmsgbuf: {
1.28      mycroft   418:                long n;
                    419:
1.52      leo       420:                /*
                    421:                 * deal with cases where the message buffer has
                    422:                 * become corrupted.
                    423:                 */
                    424:                if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
                    425:                        msgbufenabled = 0;
                    426:                        return (ENXIO);
                    427:                }
                    428:
                    429:                /*
                    430:                 * Note that reads of /kern/msgbuf won't necessarily yield
                    431:                 * consistent results, if the message buffer is modified
                    432:                 * while the read is in progress.  The worst that can happen
                    433:                 * is that incorrect data will be read.  There's no way
                    434:                 * that this can crash the system unless the values in the
                    435:                 * message buffer header are corrupted, but that'll cause
                    436:                 * the system to die anyway.
                    437:                 */
1.82      jdolecek  438:                if (off >= msgbufp->msg_bufs) {
                    439:                        *wrlen = 0;
1.28      mycroft   440:                        return (0);
1.82      jdolecek  441:                }
1.28      mycroft   442:                n = msgbufp->msg_bufx + off;
1.52      leo       443:                if (n >= msgbufp->msg_bufs)
                    444:                        n -= msgbufp->msg_bufs;
                    445:                len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
1.28      mycroft   446:                *bufp = msgbufp->msg_bufc + n;
1.82      jdolecek  447:                *wrlen = len;
                    448:                return (0);
1.1       cgd       449:        }
                    450:
1.98      darcy     451:        case KFShostname: {
1.1       cgd       452:                char *cp = hostname;
1.127     jmmv      453:                size_t xlen = hostnamelen;
1.1       cgd       454:
1.90      itojun    455:                if (xlen >= (len - 2))
1.1       cgd       456:                        return (EINVAL);
                    457:
1.60      perry     458:                memcpy(*bufp, cp, xlen);
1.28      mycroft   459:                (*bufp)[xlen] = '\n';
                    460:                (*bufp)[xlen+1] = '\0';
1.1       cgd       461:                break;
                    462:        }
                    463:
1.98      darcy     464:        case KFSavenrun:
1.31      mycroft   465:                averunnable.fscale = FSCALE;
1.90      itojun    466:                snprintf(*bufp, len, "%d %d %d %ld\n",
1.23      mycroft   467:                    averunnable.ldavg[0], averunnable.ldavg[1],
                    468:                    averunnable.ldavg[2], averunnable.fscale);
1.1       cgd       469:                break;
                    470:
1.90      itojun    471: #ifdef IPSEC
1.98      darcy     472:        case KFSipsecsa:
1.135     christos  473:                if (key_setdumpsa_spi == NULL)
                    474:                        return 0;
1.90      itojun    475:                /*
                    476:                 * Note that SA configuration could be changed during the
                    477:                 * read operation, resulting in garbled output.
                    478:                 */
                    479:                m = key_setdumpsa_spi(htonl(kfs->kfs_value));
                    480:                if (!m)
                    481:                        return (ENOBUFS);
                    482:                if (off >= m->m_pkthdr.len) {
                    483:                        *wrlen = 0;
                    484:                        m_freem(m);
                    485:                        return (0);
                    486:                }
                    487:                if (len > m->m_pkthdr.len - off)
                    488:                        len = m->m_pkthdr.len - off;
                    489:                m_copydata(m, off, len, *bufp);
                    490:                *wrlen = len;
                    491:                m_freem(m);
                    492:                return (0);
                    493:
1.98      darcy     494:        case KFSipsecsp:
1.90      itojun    495:                /*
                    496:                 * Note that SP configuration could be changed during the
                    497:                 * read operation, resulting in garbled output.
                    498:                 */
1.135     christos  499:                if (key_getspbyid == NULL)
                    500:                        return 0;
1.90      itojun    501:                if (!kfs->kfs_v) {
                    502:                        struct secpolicy *sp;
                    503:
                    504:                        sp = key_getspbyid(kfs->kfs_value);
                    505:                        if (sp)
                    506:                                kfs->kfs_v = sp;
                    507:                        else
                    508:                                return (ENOENT);
                    509:                }
                    510:                m = key_setdumpsp((struct secpolicy *)kfs->kfs_v,
                    511:                    SADB_X_SPDGET, 0, 0);
                    512:                if (!m)
                    513:                        return (ENOBUFS);
                    514:                if (off >= m->m_pkthdr.len) {
                    515:                        *wrlen = 0;
                    516:                        m_freem(m);
                    517:                        return (0);
                    518:                }
                    519:                if (len > m->m_pkthdr.len - off)
                    520:                        len = m->m_pkthdr.len - off;
                    521:                m_copydata(m, off, len, *bufp);
                    522:                *wrlen = len;
                    523:                m_freem(m);
                    524:                return (0);
                    525: #endif
                    526:
1.1       cgd       527:        default:
1.124     bouyer    528:                err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len,
                    529:                    EOPNOTSUPP);
                    530:                if (err)
                    531:                        return err;
1.1       cgd       532:        }
                    533:
1.28      mycroft   534:        len = strlen(*bufp);
                    535:        if (len <= off)
1.82      jdolecek  536:                *wrlen = 0;
                    537:        else {
                    538:                *bufp += off;
                    539:                *wrlen = len - off;
                    540:        }
                    541:        return (0);
1.1       cgd       542: }
                    543:
1.82      jdolecek  544: static int
1.136     dsl       545: kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len)
1.1       cgd       546: {
1.23      mycroft   547:
1.90      itojun    548:        switch (kfs->kfs_type) {
1.98      darcy     549:        case KFShostname:
1.109     christos  550:                if (bf[len-1] == '\n')
1.1       cgd       551:                        --len;
1.109     christos  552:                memcpy(hostname, bf, len);
1.17      cgd       553:                hostname[len] = '\0';
1.82      jdolecek  554:                hostnamelen = (size_t) len;
1.1       cgd       555:                return (0);
                    556:
                    557:        default:
1.109     christos  558:                return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO);
1.1       cgd       559:        }
                    560: }
                    561:
1.17      cgd       562:
                    563: /*
1.1       cgd       564:  * vp is the current namei directory
                    565:  * ndp is the name to locate in that directory...
                    566:  */
1.41      christos  567: int
1.136     dsl       568: kernfs_lookup(void *v)
1.41      christos  569: {
1.23      mycroft   570:        struct vop_lookup_args /* {
                    571:                struct vnode * a_dvp;
                    572:                struct vnode ** a_vpp;
                    573:                struct componentname * a_cnp;
1.41      christos  574:        } */ *ap = v;
1.23      mycroft   575:        struct componentname *cnp = ap->a_cnp;
                    576:        struct vnode **vpp = ap->a_vpp;
                    577:        struct vnode *dvp = ap->a_dvp;
1.48      cgd       578:        const char *pname = cnp->cn_nameptr;
1.90      itojun    579:        const struct kernfs_node *kfs;
1.75      jdolecek  580:        const struct kern_target *kt;
1.102     cl        581:        const struct dyn_kern_target *dkt;
                    582:        const struct kernfs_subdir *ks;
1.129     chs       583:        int error, i;
1.90      itojun    584: #ifdef IPSEC
                    585:        char *ep;
                    586:        u_int32_t id;
1.1       cgd       587: #endif
1.23      mycroft   588:
1.35      mycroft   589:        *vpp = NULLVP;
                    590:
                    591:        if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
                    592:                return (EROFS);
                    593:
1.23      mycroft   594:        if (cnp->cn_namelen == 1 && *pname == '.') {
                    595:                *vpp = dvp;
1.139     pooka     596:                vref(dvp);
1.1       cgd       597:                return (0);
                    598:        }
1.13      cgd       599:
1.90      itojun    600:        kfs = VTOKERN(dvp);
                    601:        switch (kfs->kfs_type) {
1.98      darcy     602:        case KFSkern:
1.90      itojun    603:                /*
                    604:                 * Shouldn't get here with .. in the root node.
                    605:                 */
                    606:                if (cnp->cn_flags & ISDOTDOT)
                    607:                        return (EIO);
1.64      wrstuden  608:
1.102     cl        609:                for (i = 0; i < static_nkern_targets; i++) {
1.90      itojun    610:                        kt = &kern_targets[i];
                    611:                        if (cnp->cn_namelen == kt->kt_namlen &&
                    612:                            memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
                    613:                                goto found;
                    614:                }
1.102     cl        615:                SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
                    616:                        if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
                    617:                            memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
                    618:                                kt = &dkt->dkt_kt;
                    619:                                goto found;
                    620:                        }
                    621:                }
1.90      itojun    622:                break;
1.25      mycroft   623:
1.90      itojun    624:        found:
                    625:                error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0);
                    626:                return (error);
1.64      wrstuden  627:
1.102     cl        628:        case KFSsubdir:
                    629:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
                    630:                if (cnp->cn_flags & ISDOTDOT) {
                    631:                        kt = ks->ks_parent;
                    632:                        goto found;
                    633:                }
                    634:
                    635:                SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
                    636:                        if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
                    637:                            memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
                    638:                                kt = &dkt->dkt_kt;
                    639:                                goto found;
                    640:                        }
                    641:                }
                    642:                break;
                    643:
1.90      itojun    644: #ifdef IPSEC
1.98      darcy     645:        case KFSipsecsadir:
1.100     cl        646:                if (cnp->cn_flags & ISDOTDOT) {
                    647:                        kt = &kern_targets[0];
                    648:                        goto found;
                    649:                }
                    650:
                    651:                for (i = 2; i < nipsecsa_targets; i++) {
1.90      itojun    652:                        kt = &ipsecsa_targets[i];
                    653:                        if (cnp->cn_namelen == kt->kt_namlen &&
1.100     cl        654:                            memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
                    655:                                goto found;
1.90      itojun    656:                }
1.1       cgd       657:
1.90      itojun    658:                ep = NULL;
                    659:                id = strtoul(pname, &ep, 10);
                    660:                if (!ep || *ep || ep == pname)
                    661:                        break;
1.1       cgd       662:
1.101     cl        663:                error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsa, &ipsecsa_kt, id);
1.90      itojun    664:                return (error);
1.23      mycroft   665:
1.98      darcy     666:        case KFSipsecspdir:
1.100     cl        667:                if (cnp->cn_flags & ISDOTDOT) {
                    668:                        kt = &kern_targets[0];
                    669:                        goto found;
                    670:                }
                    671:
                    672:                for (i = 2; i < nipsecsp_targets; i++) {
1.90      itojun    673:                        kt = &ipsecsp_targets[i];
                    674:                        if (cnp->cn_namelen == kt->kt_namlen &&
1.100     cl        675:                            memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
                    676:                                goto found;
1.57      fvdl      677:                }
1.90      itojun    678:
                    679:                ep = NULL;
                    680:                id = strtoul(pname, &ep, 10);
                    681:                if (!ep || *ep || ep == pname)
                    682:                        break;
                    683:
1.101     cl        684:                error = kernfs_allocvp(dvp->v_mount, vpp, KFSipsecsp, &ipsecsp_kt, id);
1.90      itojun    685:                return (error);
                    686: #endif
                    687:
                    688:        default:
                    689:                return (ENOTDIR);
                    690:        }
                    691:
                    692:        return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
                    693: }
                    694:
                    695: int
1.136     dsl       696: kernfs_open(void *v)
1.90      itojun    697: {
                    698:        struct vop_open_args /* {
                    699:                struct vnode *a_vp;
                    700:                int a_mode;
1.120     elad      701:                kauth_cred_t a_cred;
1.90      itojun    702:        } */ *ap = v;
                    703:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    704: #ifdef IPSEC
                    705:        struct mbuf *m;
                    706:        struct secpolicy *sp;
                    707: #endif
                    708:
                    709:        switch (kfs->kfs_type) {
                    710: #ifdef IPSEC
1.98      darcy     711:        case KFSipsecsa:
1.135     christos  712:                if (key_setdumpsa_spi == NULL)
                    713:                        return 0;
1.90      itojun    714:                m = key_setdumpsa_spi(htonl(kfs->kfs_value));
                    715:                if (m) {
                    716:                        m_freem(m);
                    717:                        return (0);
                    718:                } else
                    719:                        return (ENOENT);
                    720:
1.98      darcy     721:        case KFSipsecsp:
1.135     christos  722:                if (key_getspbyid == NULL)
                    723:                        return 0;
1.90      itojun    724:                sp = key_getspbyid(kfs->kfs_value);
                    725:                if (sp) {
                    726:                        kfs->kfs_v = sp;
                    727:                        return (0);
                    728:                } else
                    729:                        return (ENOENT);
                    730: #endif
                    731:
                    732:        default:
1.102     cl        733:                return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN,
                    734:                    v, 0);
1.23      mycroft   735:        }
1.90      itojun    736: }
1.1       cgd       737:
1.90      itojun    738: int
1.136     dsl       739: kernfs_close(void *v)
1.90      itojun    740: {
                    741:        struct vop_close_args /* {
                    742:                struct vnode *a_vp;
                    743:                int a_fflag;
1.120     elad      744:                kauth_cred_t a_cred;
1.90      itojun    745:        } */ *ap = v;
                    746:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    747:
                    748:        switch (kfs->kfs_type) {
                    749: #ifdef IPSEC
1.98      darcy     750:        case KFSipsecsp:
1.135     christos  751:                if (key_freesp == NULL)
                    752:                        return 0;
1.90      itojun    753:                key_freesp((struct secpolicy *)kfs->kfs_v);
                    754:                break;
1.1       cgd       755: #endif
1.90      itojun    756:
                    757:        default:
1.102     cl        758:                return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE,
                    759:                    v, 0);
1.57      fvdl      760:        }
1.23      mycroft   761:
1.1       cgd       762:        return (0);
                    763: }
                    764:
1.28      mycroft   765: int
1.136     dsl       766: kernfs_access(void *v)
1.41      christos  767: {
1.23      mycroft   768:        struct vop_access_args /* {
                    769:                struct vnode *a_vp;
1.34      mycroft   770:                int a_mode;
1.120     elad      771:                kauth_cred_t a_cred;
1.41      christos  772:        } */ *ap = v;
1.90      itojun    773:        struct vattr va;
                    774:        int error;
1.17      cgd       775:
1.133     pooka     776:        if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0)
1.90      itojun    777:                return (error);
1.49      mycroft   778:
1.145   ! elad      779:        return kauth_authorize_vnode(ap->a_cred,
        !           780:            kauth_access_action(ap->a_mode, ap->a_vp->v_type, va.va_mode),
        !           781:            ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode,
        !           782:            va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
1.23      mycroft   783: }
                    784:
1.102     cl        785: static int
1.136     dsl       786: kernfs_default_fileop_getattr(void *v)
1.102     cl        787: {
                    788:        struct vop_getattr_args /* {
                    789:                struct vnode *a_vp;
                    790:                struct vattr *a_vap;
1.120     elad      791:                kauth_cred_t a_cred;
1.102     cl        792:        } */ *ap = v;
                    793:        struct vattr *vap = ap->a_vap;
                    794:
                    795:        vap->va_nlink = 1;
                    796:        vap->va_bytes = vap->va_size = 0;
                    797:
                    798:        return 0;
                    799: }
                    800:
1.41      christos  801: int
1.136     dsl       802: kernfs_getattr(void *v)
1.41      christos  803: {
1.23      mycroft   804:        struct vop_getattr_args /* {
                    805:                struct vnode *a_vp;
                    806:                struct vattr *a_vap;
1.120     elad      807:                kauth_cred_t a_cred;
1.41      christos  808:        } */ *ap = v;
1.90      itojun    809:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.102     cl        810:        struct kernfs_subdir *ks;
1.23      mycroft   811:        struct vattr *vap = ap->a_vap;
1.1       cgd       812:        int error = 0;
1.109     christos  813:        char strbuf[KSTRING], *bf;
1.90      itojun    814:        size_t nread, total;
1.1       cgd       815:
1.139     pooka     816:        vattr_null(vap);
1.90      itojun    817:        vap->va_type = ap->a_vp->v_type;
1.17      cgd       818:        vap->va_uid = 0;
                    819:        vap->va_gid = 0;
1.90      itojun    820:        vap->va_mode = kfs->kfs_mode;
                    821:        vap->va_fileid = kfs->kfs_fileno;
                    822:        vap->va_flags = 0;
1.23      mycroft   823:        vap->va_size = 0;
1.1       cgd       824:        vap->va_blocksize = DEV_BSIZE;
1.121     kardel    825:        /* Make all times be current TOD, except for the "boottime" node. */
1.132     elad      826:        if (kfs->kfs_kt->kt_namlen == 8 &&
1.92      dan       827:            !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
1.135     christos  828:                vap->va_ctime = boottime;
1.92      dan       829:        } else {
1.121     kardel    830:                getnanotime(&vap->va_ctime);
1.92      dan       831:        }
1.81      lukem     832:        vap->va_atime = vap->va_mtime = vap->va_ctime;
1.1       cgd       833:        vap->va_gen = 0;
                    834:        vap->va_flags = 0;
                    835:        vap->va_rdev = 0;
                    836:        vap->va_bytes = 0;
                    837:
1.90      itojun    838:        switch (kfs->kfs_type) {
1.98      darcy     839:        case KFSkern:
1.102     cl        840:                vap->va_nlink = nkern_dirs;
1.90      itojun    841:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    842:                break;
                    843:
1.98      darcy     844:        case KFSroot:
1.90      itojun    845:                vap->va_nlink = 1;
                    846:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    847:                break;
                    848:
1.102     cl        849:        case KFSsubdir:
                    850:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
                    851:                vap->va_nlink = ks->ks_dirs;
                    852:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    853:                break;
                    854:
1.98      darcy     855:        case KFSnull:
                    856:        case KFStime:
                    857:        case KFSint:
                    858:        case KFSstring:
                    859:        case KFShostname:
                    860:        case KFSavenrun:
                    861:        case KFSdevice:
                    862:        case KFSmsgbuf:
1.90      itojun    863: #ifdef IPSEC
1.98      darcy     864:        case KFSipsecsa:
                    865:        case KFSipsecsp:
1.1       cgd       866: #endif
                    867:                vap->va_nlink = 1;
1.84      jdolecek  868:                total = 0;
                    869:                do {
1.109     christos  870:                        bf = strbuf;
                    871:                        error = kernfs_xread(kfs, total, &bf,
1.90      itojun    872:                            sizeof(strbuf), &nread);
1.84      jdolecek  873:                        total += nread;
                    874:                } while (error == 0 && nread != 0);
1.90      itojun    875:                vap->va_bytes = vap->va_size = total;
                    876:                break;
                    877:
                    878: #ifdef IPSEC
1.98      darcy     879:        case KFSipsecsadir:
                    880:        case KFSipsecspdir:
1.90      itojun    881:                vap->va_nlink = 2;
                    882:                vap->va_bytes = vap->va_size = DEV_BSIZE;
                    883:                break;
                    884: #endif
                    885:
                    886:        default:
1.102     cl        887:                error = kernfs_try_fileop(kfs->kfs_type,
                    888:                    KERNFS_FILEOP_GETATTR, v, EINVAL);
1.90      itojun    889:                break;
1.1       cgd       890:        }
                    891:
                    892:        return (error);
                    893: }
                    894:
1.41      christos  895: /*ARGSUSED*/
                    896: int
1.128     christos  897: kernfs_setattr(void *v)
1.1       cgd       898: {
1.90      itojun    899:
1.1       cgd       900:        /*
1.17      cgd       901:         * Silently ignore attribute changes.
                    902:         * This allows for open with truncate to have no
                    903:         * effect until some data is written.  I want to
                    904:         * do it this way because all writes are atomic.
1.1       cgd       905:         */
1.17      cgd       906:        return (0);
1.1       cgd       907: }
                    908:
1.28      mycroft   909: int
1.136     dsl       910: kernfs_default_xread(void *v)
1.41      christos  911: {
1.23      mycroft   912:        struct vop_read_args /* {
                    913:                struct vnode *a_vp;
                    914:                struct uio *a_uio;
                    915:                int  a_ioflag;
1.120     elad      916:                kauth_cred_t a_cred;
1.41      christos  917:        } */ *ap = v;
1.23      mycroft   918:        struct uio *uio = ap->a_uio;
1.90      itojun    919:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.109     christos  920:        char strbuf[KSTRING], *bf;
1.114     christos  921:        int off;
1.82      jdolecek  922:        size_t len;
1.28      mycroft   923:        int error;
1.23      mycroft   924:
1.90      itojun    925:        if (ap->a_vp->v_type == VDIR)
1.144     njoly     926:                return EISDIR;
1.23      mycroft   927:
1.114     christos  928:        off = (int)uio->uio_offset;
1.112     christos  929:        /* Don't allow negative offsets */
1.114     christos  930:        if (off < 0)
1.112     christos  931:                return EINVAL;
                    932:
1.109     christos  933:        bf = strbuf;
                    934:        if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
                    935:                error = uiomove(bf, len, uio);
1.82      jdolecek  936:        return (error);
1.1       cgd       937: }
                    938:
1.123     bouyer    939: int
1.136     dsl       940: kernfs_read(void *v)
1.123     bouyer    941: {
                    942:        struct vop_read_args /* {
                    943:                struct vnode *a_vp;
                    944:                struct uio *a_uio;
                    945:                int  a_ioflag;
                    946:                struct ucred *a_cred;
                    947:        } */ *ap = v;
                    948:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    949:
1.124     bouyer    950:        if (kfs->kfs_type < KFSlasttype) {
                    951:                /* use default function */
                    952:                return kernfs_default_xread(v);
                    953:        }
                    954:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v,
                    955:           EOPNOTSUPP);
1.123     bouyer    956: }
                    957:
1.102     cl        958: static int
1.136     dsl       959: kernfs_default_xwrite(void *v)
1.41      christos  960: {
1.23      mycroft   961:        struct vop_write_args /* {
                    962:                struct vnode *a_vp;
                    963:                struct uio *a_uio;
                    964:                int  a_ioflag;
1.120     elad      965:                kauth_cred_t a_cred;
1.41      christos  966:        } */ *ap = v;
1.90      itojun    967:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.23      mycroft   968:        struct uio *uio = ap->a_uio;
1.127     jmmv      969:        int error;
                    970:        size_t xlen;
1.1       cgd       971:        char strbuf[KSTRING];
1.23      mycroft   972:
1.1       cgd       973:        if (uio->uio_offset != 0)
                    974:                return (EINVAL);
                    975:
                    976:        xlen = min(uio->uio_resid, KSTRING-1);
1.41      christos  977:        if ((error = uiomove(strbuf, xlen, uio)) != 0)
1.1       cgd       978:                return (error);
                    979:
                    980:        if (uio->uio_resid != 0)
                    981:                return (EIO);
                    982:
                    983:        strbuf[xlen] = '\0';
1.17      cgd       984:        xlen = strlen(strbuf);
1.90      itojun    985:        return (kernfs_xwrite(kfs, strbuf, xlen));
1.1       cgd       986: }
                    987:
1.102     cl        988: int
1.136     dsl       989: kernfs_write(void *v)
1.102     cl        990: {
                    991:        struct vop_write_args /* {
                    992:                struct vnode *a_vp;
                    993:                struct uio *a_uio;
                    994:                int  a_ioflag;
1.120     elad      995:                kauth_cred_t a_cred;
1.102     cl        996:        } */ *ap = v;
                    997:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                    998:
1.124     bouyer    999:        if (kfs->kfs_type < KFSlasttype) {
                   1000:                /* use default function */
                   1001:                return kernfs_default_xwrite(v);
                   1002:        }
                   1003:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v,
                   1004:            EOPNOTSUPP);
1.102     cl       1005: }
                   1006:
                   1007: int
1.136     dsl      1008: kernfs_ioctl(void *v)
1.102     cl       1009: {
                   1010:        struct vop_ioctl_args /* {
                   1011:                const struct vnodeop_desc *a_desc;
                   1012:                struct vnode *a_vp;
                   1013:                u_long a_command;
                   1014:                void *a_data;
                   1015:                int a_fflag;
1.120     elad     1016:                kauth_cred_t a_cred;
1.102     cl       1017:        } */ *ap = v;
                   1018:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                   1019:
                   1020:        return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
                   1021:            EPASSTHROUGH);
                   1022: }
                   1023:
1.101     cl       1024: static int
                   1025: kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
                   1026:     u_int32_t value, struct vop_readdir_args *ap)
                   1027: {
                   1028:        struct kernfs_node *kfs;
                   1029:        struct vnode *vp;
                   1030:        int error;
                   1031:
                   1032:        if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt,
                   1033:            value)) != 0)
                   1034:                return error;
                   1035:        if (kt->kt_tag == KFSdevice) {
                   1036:                struct vattr va;
1.117     yamt     1037:
1.133     pooka    1038:                error = VOP_GETATTR(vp, &va, ap->a_cred);
1.117     yamt     1039:                if (error != 0) {
                   1040:                        return error;
                   1041:                }
1.101     cl       1042:                d->d_fileno = va.va_fileid;
                   1043:        } else {
                   1044:                kfs = VTOKERN(vp);
                   1045:                d->d_fileno = kfs->kfs_fileno;
                   1046:        }
                   1047:        vput(vp);
                   1048:        return 0;
                   1049: }
                   1050:
                   1051: static int
                   1052: kernfs_setdirentfileno(struct dirent *d, off_t entry,
                   1053:     struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
                   1054:     const struct kern_target *kt, struct vop_readdir_args *ap)
                   1055: {
                   1056:        const struct kern_target *ikt;
                   1057:        int error;
                   1058:
                   1059:        switch (entry) {
                   1060:        case 0:
                   1061:                d->d_fileno = thisdir_kfs->kfs_fileno;
                   1062:                return 0;
                   1063:        case 1:
                   1064:                ikt = parent_kt;
                   1065:                break;
                   1066:        default:
                   1067:                ikt = kt;
                   1068:                break;
                   1069:        }
                   1070:        if (ikt != thisdir_kfs->kfs_kt) {
                   1071:                if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0)
                   1072:                        return error;
                   1073:        } else
                   1074:                d->d_fileno = thisdir_kfs->kfs_fileno;
                   1075:        return 0;
                   1076: }
                   1077:
1.41      christos 1078: int
1.136     dsl      1079: kernfs_readdir(void *v)
1.41      christos 1080: {
1.23      mycroft  1081:        struct vop_readdir_args /* {
                   1082:                struct vnode *a_vp;
                   1083:                struct uio *a_uio;
1.120     elad     1084:                kauth_cred_t a_cred;
1.26      mycroft  1085:                int *a_eofflag;
1.57      fvdl     1086:                off_t **a_cookies;
                   1087:                int a_*ncookies;
1.41      christos 1088:        } */ *ap = v;
1.23      mycroft  1089:        struct uio *uio = ap->a_uio;
1.37      mycroft  1090:        struct dirent d;
1.90      itojun   1091:        struct kernfs_node *kfs = VTOKERN(ap->a_vp);
1.75      jdolecek 1092:        const struct kern_target *kt;
1.102     cl       1093:        const struct dyn_kern_target *dkt = NULL;
                   1094:        const struct kernfs_subdir *ks;
                   1095:        off_t i, j;
1.1       cgd      1096:        int error;
1.57      fvdl     1097:        off_t *cookies = NULL;
1.90      itojun   1098:        int ncookies = 0, n;
                   1099: #ifdef IPSEC
                   1100:        struct secasvar *sav, *sav2;
                   1101:        struct secpolicy *sp;
                   1102: #endif
1.23      mycroft  1103:
1.37      mycroft  1104:        if (uio->uio_resid < UIO_MX)
                   1105:                return (EINVAL);
1.38      mycroft  1106:        if (uio->uio_offset < 0)
1.37      mycroft  1107:                return (EINVAL);
1.26      mycroft  1108:
1.1       cgd      1109:        error = 0;
1.38      mycroft  1110:        i = uio->uio_offset;
1.90      itojun   1111:        memset(&d, 0, sizeof(d));
                   1112:        d.d_reclen = UIO_MX;
                   1113:        ncookies = uio->uio_resid / UIO_MX;
                   1114:
                   1115:        switch (kfs->kfs_type) {
1.98      darcy    1116:        case KFSkern:
1.90      itojun   1117:                if (i >= nkern_targets)
                   1118:                        return (0);
1.66      sommerfe 1119:
1.90      itojun   1120:                if (ap->a_ncookies) {
                   1121:                        ncookies = min(ncookies, (nkern_targets - i));
                   1122:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1123:                            M_WAITOK);
                   1124:                        *ap->a_cookies = cookies;
                   1125:                }
                   1126:
                   1127:                n = 0;
                   1128:                for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
1.102     cl       1129:                        if (i < static_nkern_targets)
                   1130:                                kt = &kern_targets[i];
                   1131:                        else {
                   1132:                                if (dkt == NULL) {
                   1133:                                        dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
                   1134:                                        for (j = static_nkern_targets; j < i &&
                   1135:                                                     dkt != NULL; j++)
                   1136:                                                dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                   1137:                                        if (j != i)
                   1138:                                                break;
                   1139:                                } else {
                   1140:                                        dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                   1141:                                }
1.119     christos 1142:                                if (dkt == NULL)
                   1143:                                        break;
1.102     cl       1144:                                kt = &dkt->dkt_kt;
                   1145:                        }
1.98      darcy    1146:                        if (kt->kt_tag == KFSdevice) {
1.94      itojun   1147:                                dev_t *dp = kt->kt_data;
                   1148:                                struct vnode *fvp;
                   1149:
                   1150:                                if (*dp == NODEV ||
                   1151:                                    !vfinddev(*dp, kt->kt_vtype, &fvp))
                   1152:                                        continue;
1.143     hannken  1153:                                vrele(fvp);
1.94      itojun   1154:                        }
1.141     pooka    1155:                        if (kt->kt_tag == KFSmsgbuf) {
                   1156:                                if (!msgbufenabled
                   1157:                                    || msgbufp->msg_magic != MSG_MAGIC) {
                   1158:                                        continue;
                   1159:                                }
                   1160:                        }
1.90      itojun   1161:                        d.d_namlen = kt->kt_namlen;
1.101     cl       1162:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                   1163:                            &kern_targets[0], kt, ap)) != 0)
                   1164:                                break;
1.90      itojun   1165:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1166:                        d.d_type = kt->kt_type;
1.99      jrf      1167:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1168:                                break;
                   1169:                        if (cookies)
                   1170:                                *cookies++ = i + 1;
                   1171:                        n++;
                   1172:                }
                   1173:                ncookies = n;
                   1174:                break;
                   1175:
1.98      darcy    1176:        case KFSroot:
1.90      itojun   1177:                if (i >= 2)
                   1178:                        return 0;
                   1179:
                   1180:                if (ap->a_ncookies) {
                   1181:                        ncookies = min(ncookies, (2 - i));
                   1182:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1183:                            M_WAITOK);
                   1184:                        *ap->a_cookies = cookies;
                   1185:                }
                   1186:
                   1187:                n = 0;
                   1188:                for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
                   1189:                        kt = &kern_targets[i];
                   1190:                        d.d_namlen = kt->kt_namlen;
                   1191:                        d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
                   1192:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1193:                        d.d_type = kt->kt_type;
1.99      jrf      1194:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1195:                                break;
                   1196:                        if (cookies)
                   1197:                                *cookies++ = i + 1;
                   1198:                        n++;
                   1199:                }
                   1200:                ncookies = n;
                   1201:                break;
                   1202:
1.102     cl       1203:        case KFSsubdir:
                   1204:                ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
                   1205:                if (i >= ks->ks_nentries)
                   1206:                        return (0);
                   1207:
                   1208:                if (ap->a_ncookies) {
                   1209:                        ncookies = min(ncookies, (ks->ks_nentries - i));
                   1210:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1211:                            M_WAITOK);
                   1212:                        *ap->a_cookies = cookies;
                   1213:                }
                   1214:
                   1215:                dkt = SIMPLEQ_FIRST(&ks->ks_entries);
                   1216:                for (j = 0; j < i && dkt != NULL; j++)
                   1217:                        dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                   1218:                n = 0;
                   1219:                for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
                   1220:                        if (i < 2)
                   1221:                                kt = &subdir_targets[i];
                   1222:                        else {
                   1223:                                /* check if ks_nentries lied to us */
                   1224:                                if (dkt == NULL)
                   1225:                                        break;
                   1226:                                kt = &dkt->dkt_kt;
                   1227:                                dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
                   1228:                        }
                   1229:                        if (kt->kt_tag == KFSdevice) {
                   1230:                                dev_t *dp = kt->kt_data;
                   1231:                                struct vnode *fvp;
                   1232:
                   1233:                                if (*dp == NODEV ||
                   1234:                                    !vfinddev(*dp, kt->kt_vtype, &fvp))
                   1235:                                        continue;
1.143     hannken  1236:                                vrele(fvp);
1.102     cl       1237:                        }
                   1238:                        d.d_namlen = kt->kt_namlen;
                   1239:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                   1240:                            ks->ks_parent, kt, ap)) != 0)
                   1241:                                break;
                   1242:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1243:                        d.d_type = kt->kt_type;
1.103     jrf      1244:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.102     cl       1245:                                break;
                   1246:                        if (cookies)
                   1247:                                *cookies++ = i + 1;
                   1248:                        n++;
                   1249:                }
                   1250:                ncookies = n;
                   1251:                break;
                   1252:
1.90      itojun   1253: #ifdef IPSEC
1.98      darcy    1254:        case KFSipsecsadir:
1.90      itojun   1255:                /* count SA in the system */
                   1256:                n = 0;
1.135     christos 1257:                if (&satailq == NULL)
                   1258:                        return 0;
1.90      itojun   1259:                TAILQ_FOREACH(sav, &satailq, tailq) {
                   1260:                        for (sav2 = TAILQ_FIRST(&satailq);
                   1261:                            sav2 != sav;
                   1262:                            sav2 = TAILQ_NEXT(sav2, tailq)) {
                   1263:                                if (sav->spi == sav2->spi) {
                   1264:                                        /* multiple SA with same SPI */
                   1265:                                        break;
                   1266:                                }
                   1267:                        }
                   1268:                        if (sav == sav2 || sav->spi != sav2->spi)
                   1269:                                n++;
                   1270:                }
1.37      mycroft  1271:
1.90      itojun   1272:                if (i >= nipsecsa_targets + n)
                   1273:                        return (0);
1.57      fvdl     1274:
1.90      itojun   1275:                if (ap->a_ncookies) {
                   1276:                        ncookies = min(ncookies, (n - i));
                   1277:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1278:                            M_WAITOK);
                   1279:                        *ap->a_cookies = cookies;
                   1280:                }
1.26      mycroft  1281:
1.90      itojun   1282:                n = 0;
                   1283:                for (; i < nipsecsa_targets && uio->uio_resid >= UIO_MX; i++) {
                   1284:                        kt = &ipsecsa_targets[i];
                   1285:                        d.d_namlen = kt->kt_namlen;
1.101     cl       1286:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                   1287:                            &kern_targets[0], kt, ap)) != 0)
                   1288:                                break;
1.90      itojun   1289:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1290:                        d.d_type = kt->kt_type;
1.99      jrf      1291:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1292:                                break;
                   1293:                        if (cookies)
                   1294:                                *cookies++ = i + 1;
                   1295:                        n++;
                   1296:                }
                   1297:                if (error) {
                   1298:                        ncookies = n;
                   1299:                        break;
                   1300:                }
1.26      mycroft  1301:
1.90      itojun   1302:                TAILQ_FOREACH(sav, &satailq, tailq) {
                   1303:                        for (sav2 = TAILQ_FIRST(&satailq);
                   1304:                            sav2 != sav;
                   1305:                            sav2 = TAILQ_NEXT(sav2, tailq)) {
                   1306:                                if (sav->spi == sav2->spi) {
                   1307:                                        /* multiple SA with same SPI */
                   1308:                                        break;
                   1309:                                }
                   1310:                        }
                   1311:                        if (sav != sav2 && sav->spi == sav2->spi)
1.23      mycroft  1312:                                continue;
1.90      itojun   1313:                        if (uio->uio_resid < UIO_MX)
                   1314:                                break;
1.101     cl       1315:                        if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsa_kt,
                   1316:                            sav->spi, ap)) != 0)
                   1317:                                break;
1.90      itojun   1318:                        d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
                   1319:                            "%u", ntohl(sav->spi));
                   1320:                        d.d_type = DT_REG;
1.99      jrf      1321:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1322:                                break;
                   1323:                        if (cookies)
                   1324:                                *cookies++ = i + 1;
                   1325:                        n++;
                   1326:                        i++;
1.23      mycroft  1327:                }
1.90      itojun   1328:                ncookies = n;
                   1329:                break;
                   1330:
1.98      darcy    1331:        case KFSipsecspdir:
1.90      itojun   1332:                /* count SP in the system */
1.135     christos 1333:                if (&sptailq == NULL)
                   1334:                        return 0;
                   1335:
1.90      itojun   1336:                n = 0;
                   1337:                TAILQ_FOREACH(sp, &sptailq, tailq)
                   1338:                        n++;
1.26      mycroft  1339:
1.102     cl       1340:                if (i >= nipsecsp_targets + n)
1.90      itojun   1341:                        return (0);
                   1342:
                   1343:                if (ap->a_ncookies) {
                   1344:                        ncookies = min(ncookies, (n - i));
                   1345:                        cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
                   1346:                            M_WAITOK);
                   1347:                        *ap->a_cookies = cookies;
                   1348:                }
1.26      mycroft  1349:
1.90      itojun   1350:                n = 0;
                   1351:                for (; i < nipsecsp_targets && uio->uio_resid >= UIO_MX; i++) {
                   1352:                        kt = &ipsecsp_targets[i];
                   1353:                        d.d_namlen = kt->kt_namlen;
1.101     cl       1354:                        if ((error = kernfs_setdirentfileno(&d, i, kfs,
                   1355:                            &kern_targets[0], kt, ap)) != 0)
                   1356:                                break;
1.90      itojun   1357:                        memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
                   1358:                        d.d_type = kt->kt_type;
1.99      jrf      1359:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1360:                                break;
                   1361:                        if (cookies)
                   1362:                                *cookies++ = i + 1;
                   1363:                        n++;
                   1364:                }
                   1365:                if (error) {
                   1366:                        ncookies = n;
1.1       cgd      1367:                        break;
1.57      fvdl     1368:                }
1.90      itojun   1369:
                   1370:                TAILQ_FOREACH(sp, &sptailq, tailq) {
                   1371:                        if (uio->uio_resid < UIO_MX)
                   1372:                                break;
1.101     cl       1373:                        if ((error = kernfs_setdirentfileno_kt(&d, &ipsecsp_kt,
                   1374:                            sp->id, ap)) != 0)
                   1375:                                break;
1.90      itojun   1376:                        d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
                   1377:                            "%u", sp->id);
                   1378:                        d.d_type = DT_REG;
1.99      jrf      1379:                        if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1.90      itojun   1380:                                break;
                   1381:                        if (cookies)
                   1382:                                *cookies++ = i + 1;
                   1383:                        n++;
                   1384:                        i++;
                   1385:                }
                   1386:                ncookies = n;
                   1387:                break;
                   1388: #endif
                   1389:
                   1390:        default:
                   1391:                error = ENOTDIR;
                   1392:                break;
1.57      fvdl     1393:        }
                   1394:
                   1395:        if (ap->a_ncookies) {
                   1396:                if (error) {
1.90      itojun   1397:                        if (cookies)
                   1398:                                free(*ap->a_cookies, M_TEMP);
1.57      fvdl     1399:                        *ap->a_ncookies = 0;
                   1400:                        *ap->a_cookies = NULL;
                   1401:                } else
                   1402:                        *ap->a_ncookies = ncookies;
1.1       cgd      1403:        }
                   1404:
1.38      mycroft  1405:        uio->uio_offset = i;
1.1       cgd      1406:        return (error);
                   1407: }
                   1408:
1.41      christos 1409: int
1.136     dsl      1410: kernfs_inactive(void *v)
1.41      christos 1411: {
1.23      mycroft  1412:        struct vop_inactive_args /* {
                   1413:                struct vnode *a_vp;
1.134     ad       1414:                bool *a_recycle;
1.41      christos 1415:        } */ *ap = v;
1.23      mycroft  1416:        struct vnode *vp = ap->a_vp;
1.90      itojun   1417:        const struct kernfs_node *kfs = VTOKERN(ap->a_vp);
                   1418: #ifdef IPSEC
                   1419:        struct mbuf *m;
                   1420:        struct secpolicy *sp;
                   1421: #endif
1.23      mycroft  1422:
1.134     ad       1423:        *ap->a_recycle = false;
1.90      itojun   1424:        switch (kfs->kfs_type) {
                   1425: #ifdef IPSEC
1.98      darcy    1426:        case KFSipsecsa:
1.135     christos 1427:                if (key_setdumpsa_spi == NULL)
                   1428:                        return 0;
1.90      itojun   1429:                m = key_setdumpsa_spi(htonl(kfs->kfs_value));
                   1430:                if (m)
                   1431:                        m_freem(m);
1.91      itojun   1432:                else
1.134     ad       1433:                        *ap->a_recycle = true;
1.90      itojun   1434:                break;
1.98      darcy    1435:        case KFSipsecsp:
1.135     christos 1436:                if (key_getspbyid == NULL)
                   1437:                        return 0;
1.90      itojun   1438:                sp = key_getspbyid(kfs->kfs_value);
                   1439:                if (sp)
                   1440:                        key_freesp(sp);
                   1441:                else {
1.134     ad       1442:                        *ap->a_recycle = true;
1.90      itojun   1443:                }
                   1444:                break;
1.23      mycroft  1445: #endif
1.90      itojun   1446:        default:
                   1447:                break;
                   1448:        }
1.142     hannken  1449:        VOP_UNLOCK(vp);
1.23      mycroft  1450:        return (0);
                   1451: }
                   1452:
1.41      christos 1453: int
1.136     dsl      1454: kernfs_reclaim(void *v)
1.41      christos 1455: {
1.23      mycroft  1456:        struct vop_reclaim_args /* {
                   1457:                struct vnode *a_vp;
1.41      christos 1458:        } */ *ap = v;
1.23      mycroft  1459:
1.90      itojun   1460:        return (kernfs_freevp(ap->a_vp));
1.1       cgd      1461: }
                   1462:
                   1463: /*
1.23      mycroft  1464:  * Return POSIX pathconf information applicable to special devices.
                   1465:  */
1.41      christos 1466: int
1.136     dsl      1467: kernfs_pathconf(void *v)
1.41      christos 1468: {
1.23      mycroft  1469:        struct vop_pathconf_args /* {
                   1470:                struct vnode *a_vp;
                   1471:                int a_name;
1.29      cgd      1472:                register_t *a_retval;
1.41      christos 1473:        } */ *ap = v;
1.23      mycroft  1474:
                   1475:        switch (ap->a_name) {
                   1476:        case _PC_LINK_MAX:
                   1477:                *ap->a_retval = LINK_MAX;
                   1478:                return (0);
                   1479:        case _PC_MAX_CANON:
                   1480:                *ap->a_retval = MAX_CANON;
                   1481:                return (0);
                   1482:        case _PC_MAX_INPUT:
                   1483:                *ap->a_retval = MAX_INPUT;
                   1484:                return (0);
                   1485:        case _PC_PIPE_BUF:
                   1486:                *ap->a_retval = PIPE_BUF;
                   1487:                return (0);
                   1488:        case _PC_CHOWN_RESTRICTED:
                   1489:                *ap->a_retval = 1;
                   1490:                return (0);
                   1491:        case _PC_VDISABLE:
                   1492:                *ap->a_retval = _POSIX_VDISABLE;
1.59      kleink   1493:                return (0);
                   1494:        case _PC_SYNC_IO:
                   1495:                *ap->a_retval = 1;
1.23      mycroft  1496:                return (0);
                   1497:        default:
                   1498:                return (EINVAL);
                   1499:        }
                   1500:        /* NOTREACHED */
                   1501: }
                   1502:
                   1503: /*
                   1504:  * Print out the contents of a /dev/fd vnode.
1.1       cgd      1505:  */
                   1506: /* ARGSUSED */
1.41      christos 1507: int
1.128     christos 1508: kernfs_print(void *v)
1.23      mycroft  1509: {
                   1510:
1.47      christos 1511:        printf("tag VT_KERNFS, kernfs vnode\n");
1.23      mycroft  1512:        return (0);
                   1513: }
                   1514:
1.40      mycroft  1515: int
1.136     dsl      1516: kernfs_link(void *v)
1.41      christos 1517: {
1.40      mycroft  1518:        struct vop_link_args /* {
                   1519:                struct vnode *a_dvp;
1.107     perry    1520:                struct vnode *a_vp;
1.40      mycroft  1521:                struct componentname *a_cnp;
1.41      christos 1522:        } */ *ap = v;
1.107     perry    1523:
1.40      mycroft  1524:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                   1525:        vput(ap->a_dvp);
                   1526:        return (EROFS);
                   1527: }
                   1528:
                   1529: int
1.136     dsl      1530: kernfs_symlink(void *v)
1.41      christos 1531: {
1.40      mycroft  1532:        struct vop_symlink_args /* {
                   1533:                struct vnode *a_dvp;
                   1534:                struct vnode **a_vpp;
                   1535:                struct componentname *a_cnp;
                   1536:                struct vattr *a_vap;
                   1537:                char *a_target;
1.41      christos 1538:        } */ *ap = v;
1.107     perry    1539:
1.40      mycroft  1540:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                   1541:        vput(ap->a_dvp);
                   1542:        return (EROFS);
1.1       cgd      1543: }

CVSweb <webmaster@jp.NetBSD.org>