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

1.89    ! agc         1: /*     $NetBSD: kernfs_vnops.c,v 1.88 2003/06/29 22:31:41 fvdl 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.89    ! agc        42: __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.88 2003/06/29 22:31:41 fvdl 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.63      mrg        62:
1.54      mrg        63: #include <uvm/uvm_extern.h>
                     64:
1.17      cgd        65: #define KSTRING        256             /* Largest I/O available via this filesystem */
                     66: #define        UIO_MX 32
1.1       cgd        67:
1.23      mycroft    68: #define        READ_MODE       (S_IRUSR|S_IRGRP|S_IROTH)
                     69: #define        WRITE_MODE      (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
                     70: #define DIR_MODE       (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
                     71:
1.75      jdolecek   72: const struct kern_target kern_targets[] = {
1.1       cgd        73: /* NOTE: The name must be less than UIO_MX-16 chars in length */
1.23      mycroft    74: #define N(s) sizeof(s)-1, s
                     75:      /*        name            data          tag           type  ro/rw */
                     76:      { DT_DIR, N("."),         0,            KTT_NULL,     VDIR, DIR_MODE   },
                     77:      { DT_DIR, N(".."),        0,            KTT_NULL,     VDIR, DIR_MODE   },
                     78:      { DT_REG, N("boottime"),  &boottime.tv_sec, KTT_INT,  VREG, READ_MODE  },
1.69      thorpej    79:                        /* XXX cast away const */
                     80:      { DT_REG, N("copyright"), (void *)copyright,
                     81:                                             KTT_STRING,   VREG, READ_MODE  },
1.23      mycroft    82:      { DT_REG, N("hostname"),  0,            KTT_HOSTNAME, VREG, WRITE_MODE },
                     83:      { DT_REG, N("hz"),        &hz,          KTT_INT,      VREG, READ_MODE  },
                     84:      { DT_REG, N("loadavg"),   0,            KTT_AVENRUN,  VREG, READ_MODE  },
1.28      mycroft    85:      { DT_REG, N("msgbuf"),    0,           KTT_MSGBUF,   VREG, READ_MODE  },
1.54      mrg        86:      { DT_REG, N("pagesize"),  &uvmexp.pagesize, KTT_INT,  VREG, READ_MODE  },
1.73      jdolecek   87:      { DT_REG, N("physmem"),   &physmem,     KTT_INT,      VREG, READ_MODE  },
1.17      cgd        88: #if 0
1.23      mycroft    89:      { DT_DIR, N("root"),      0,            KTT_NULL,     VDIR, DIR_MODE   },
1.17      cgd        90: #endif
1.23      mycroft    91:      { DT_BLK, N("rootdev"),   &rootdev,     KTT_DEVICE,   VBLK, READ_MODE  },
                     92:      { DT_CHR, N("rrootdev"),  &rrootdev,    KTT_DEVICE,   VCHR, READ_MODE  },
                     93:      { DT_REG, N("time"),      0,            KTT_TIME,     VREG, READ_MODE  },
1.69      thorpej    94:                        /* XXX cast away const */
                     95:      { DT_REG, N("version"),   (void *)version,
                     96:                                             KTT_STRING,   VREG, READ_MODE  },
1.23      mycroft    97: #undef N
1.1       cgd        98: };
1.17      cgd        99: static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
1.1       cgd       100:
1.41      christos  101: int    kernfs_lookup   __P((void *));
1.85      jdolecek  102: #define        kernfs_create   genfs_eopnotsupp
                    103: #define        kernfs_mknod    genfs_eopnotsupp
1.44      mycroft   104: #define        kernfs_open     genfs_nullop
                    105: #define        kernfs_close    genfs_nullop
1.41      christos  106: int    kernfs_access   __P((void *));
                    107: int    kernfs_getattr  __P((void *));
                    108: int    kernfs_setattr  __P((void *));
                    109: int    kernfs_read     __P((void *));
                    110: int    kernfs_write    __P((void *));
1.65      wrstuden  111: #define        kernfs_fcntl    genfs_fcntl
1.61      matthias  112: #define        kernfs_ioctl    genfs_enoioctl
1.45      mycroft   113: #define        kernfs_poll     genfs_poll
1.57      fvdl      114: #define kernfs_revoke  genfs_revoke
1.44      mycroft   115: #define        kernfs_fsync    genfs_nullop
                    116: #define        kernfs_seek     genfs_nullop
1.85      jdolecek  117: #define        kernfs_remove   genfs_eopnotsupp
1.41      christos  118: int    kernfs_link     __P((void *));
1.85      jdolecek  119: #define        kernfs_rename   genfs_eopnotsupp
                    120: #define        kernfs_mkdir    genfs_eopnotsupp
                    121: #define        kernfs_rmdir    genfs_eopnotsupp
1.41      christos  122: int    kernfs_symlink  __P((void *));
                    123: int    kernfs_readdir  __P((void *));
1.44      mycroft   124: #define        kernfs_readlink genfs_eopnotsupp
                    125: #define        kernfs_abortop  genfs_abortop
1.41      christos  126: int    kernfs_inactive __P((void *));
                    127: int    kernfs_reclaim  __P((void *));
1.64      wrstuden  128: #define        kernfs_lock     genfs_lock
                    129: #define        kernfs_unlock   genfs_unlock
1.44      mycroft   130: #define        kernfs_bmap     genfs_badop
                    131: #define        kernfs_strategy genfs_badop
1.41      christos  132: int    kernfs_print    __P((void *));
1.64      wrstuden  133: #define        kernfs_islocked genfs_islocked
1.41      christos  134: int    kernfs_pathconf __P((void *));
1.62      kleink    135: #define        kernfs_advlock  genfs_einval
1.44      mycroft   136: #define        kernfs_blkatoff genfs_eopnotsupp
                    137: #define        kernfs_valloc   genfs_eopnotsupp
                    138: #define        kernfs_vfree    genfs_nullop
                    139: #define        kernfs_truncate genfs_eopnotsupp
                    140: #define        kernfs_update   genfs_nullop
                    141: #define        kernfs_bwrite   genfs_eopnotsupp
1.79      chs       142: #define        kernfs_putpages genfs_putpages
1.41      christos  143:
1.82      jdolecek  144: static int     kernfs_xread __P((const struct kern_target *, int, char **, size_t, size_t *));
                    145: static int     kernfs_xwrite __P((const struct kern_target *, char *, size_t));
1.41      christos  146:
                    147: int (**kernfs_vnodeop_p) __P((void *));
1.71      jdolecek  148: const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
1.41      christos  149:        { &vop_default_desc, vn_default_error },
1.44      mycroft   150:        { &vop_lookup_desc, kernfs_lookup },            /* lookup */
                    151:        { &vop_create_desc, kernfs_create },            /* create */
                    152:        { &vop_mknod_desc, kernfs_mknod },              /* mknod */
                    153:        { &vop_open_desc, kernfs_open },                /* open */
                    154:        { &vop_close_desc, kernfs_close },              /* close */
                    155:        { &vop_access_desc, kernfs_access },            /* access */
                    156:        { &vop_getattr_desc, kernfs_getattr },          /* getattr */
                    157:        { &vop_setattr_desc, kernfs_setattr },          /* setattr */
                    158:        { &vop_read_desc, kernfs_read },                /* read */
                    159:        { &vop_write_desc, kernfs_write },              /* write */
1.65      wrstuden  160:        { &vop_fcntl_desc, kernfs_fcntl },              /* fcntl */
1.44      mycroft   161:        { &vop_ioctl_desc, kernfs_ioctl },              /* ioctl */
1.45      mycroft   162:        { &vop_poll_desc, kernfs_poll },                /* poll */
1.57      fvdl      163:        { &vop_revoke_desc, kernfs_revoke },            /* revoke */
1.44      mycroft   164:        { &vop_fsync_desc, kernfs_fsync },              /* fsync */
                    165:        { &vop_seek_desc, kernfs_seek },                /* seek */
                    166:        { &vop_remove_desc, kernfs_remove },            /* remove */
                    167:        { &vop_link_desc, kernfs_link },                /* link */
                    168:        { &vop_rename_desc, kernfs_rename },            /* rename */
                    169:        { &vop_mkdir_desc, kernfs_mkdir },              /* mkdir */
                    170:        { &vop_rmdir_desc, kernfs_rmdir },              /* rmdir */
                    171:        { &vop_symlink_desc, kernfs_symlink },          /* symlink */
                    172:        { &vop_readdir_desc, kernfs_readdir },          /* readdir */
                    173:        { &vop_readlink_desc, kernfs_readlink },        /* readlink */
                    174:        { &vop_abortop_desc, kernfs_abortop },          /* abortop */
                    175:        { &vop_inactive_desc, kernfs_inactive },        /* inactive */
                    176:        { &vop_reclaim_desc, kernfs_reclaim },          /* reclaim */
                    177:        { &vop_lock_desc, kernfs_lock },                /* lock */
                    178:        { &vop_unlock_desc, kernfs_unlock },            /* unlock */
                    179:        { &vop_bmap_desc, kernfs_bmap },                /* bmap */
                    180:        { &vop_strategy_desc, kernfs_strategy },        /* strategy */
                    181:        { &vop_print_desc, kernfs_print },              /* print */
                    182:        { &vop_islocked_desc, kernfs_islocked },        /* islocked */
                    183:        { &vop_pathconf_desc, kernfs_pathconf },        /* pathconf */
                    184:        { &vop_advlock_desc, kernfs_advlock },          /* advlock */
                    185:        { &vop_blkatoff_desc, kernfs_blkatoff },        /* blkatoff */
                    186:        { &vop_valloc_desc, kernfs_valloc },            /* valloc */
                    187:        { &vop_vfree_desc, kernfs_vfree },              /* vfree */
                    188:        { &vop_truncate_desc, kernfs_truncate },        /* truncate */
                    189:        { &vop_update_desc, kernfs_update },            /* update */
                    190:        { &vop_bwrite_desc, kernfs_bwrite },            /* bwrite */
1.79      chs       191:        { &vop_putpages_desc, kernfs_putpages },        /* putpages */
1.76      chs       192:        { NULL, NULL }
1.41      christos  193: };
1.71      jdolecek  194: const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
1.41      christos  195:        { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
                    196:
1.82      jdolecek  197: static int
                    198: kernfs_xread(kt, off, bufp, len, wrlen)
1.75      jdolecek  199:        const struct kern_target *kt;
1.28      mycroft   200:        int off;
                    201:        char **bufp;
1.82      jdolecek  202:        size_t len;
                    203:        size_t *wrlen;
1.1       cgd       204: {
                    205:
                    206:        switch (kt->kt_tag) {
                    207:        case KTT_TIME: {
                    208:                struct timeval tv;
1.28      mycroft   209:
1.1       cgd       210:                microtime(&tv);
1.47      christos  211:                sprintf(*bufp, "%ld %ld\n", tv.tv_sec, tv.tv_usec);
1.1       cgd       212:                break;
                    213:        }
                    214:
                    215:        case KTT_INT: {
                    216:                int *ip = kt->kt_data;
1.28      mycroft   217:
1.47      christos  218:                sprintf(*bufp, "%d\n", *ip);
1.1       cgd       219:                break;
                    220:        }
                    221:
                    222:        case KTT_STRING: {
                    223:                char *cp = kt->kt_data;
                    224:
1.28      mycroft   225:                *bufp = cp;
                    226:                break;
                    227:        }
1.1       cgd       228:
1.28      mycroft   229:        case KTT_MSGBUF: {
                    230:                long n;
                    231:
1.52      leo       232:                /*
                    233:                 * deal with cases where the message buffer has
                    234:                 * become corrupted.
                    235:                 */
                    236:                if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
                    237:                        msgbufenabled = 0;
                    238:                        return (ENXIO);
                    239:                }
                    240:
                    241:                /*
                    242:                 * Note that reads of /kern/msgbuf won't necessarily yield
                    243:                 * consistent results, if the message buffer is modified
                    244:                 * while the read is in progress.  The worst that can happen
                    245:                 * is that incorrect data will be read.  There's no way
                    246:                 * that this can crash the system unless the values in the
                    247:                 * message buffer header are corrupted, but that'll cause
                    248:                 * the system to die anyway.
                    249:                 */
1.82      jdolecek  250:                if (off >= msgbufp->msg_bufs) {
                    251:                        *wrlen = 0;
1.28      mycroft   252:                        return (0);
1.82      jdolecek  253:                }
1.28      mycroft   254:                n = msgbufp->msg_bufx + off;
1.52      leo       255:                if (n >= msgbufp->msg_bufs)
                    256:                        n -= msgbufp->msg_bufs;
                    257:                len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
1.28      mycroft   258:                *bufp = msgbufp->msg_bufc + n;
1.82      jdolecek  259:                *wrlen = len;
                    260:                return (0);
1.1       cgd       261:        }
                    262:
                    263:        case KTT_HOSTNAME: {
                    264:                char *cp = hostname;
                    265:                int xlen = hostnamelen;
                    266:
1.17      cgd       267:                if (xlen >= (len-2))
1.1       cgd       268:                        return (EINVAL);
                    269:
1.60      perry     270:                memcpy(*bufp, cp, xlen);
1.28      mycroft   271:                (*bufp)[xlen] = '\n';
                    272:                (*bufp)[xlen+1] = '\0';
1.1       cgd       273:                break;
                    274:        }
                    275:
                    276:        case KTT_AVENRUN:
1.31      mycroft   277:                averunnable.fscale = FSCALE;
1.47      christos  278:                sprintf(*bufp, "%d %d %d %ld\n",
1.23      mycroft   279:                    averunnable.ldavg[0], averunnable.ldavg[1],
                    280:                    averunnable.ldavg[2], averunnable.fscale);
1.1       cgd       281:                break;
                    282:
                    283:        default:
1.82      jdolecek  284:                *wrlen = 0;
1.28      mycroft   285:                return (0);
1.1       cgd       286:        }
                    287:
1.28      mycroft   288:        len = strlen(*bufp);
                    289:        if (len <= off)
1.82      jdolecek  290:                *wrlen = 0;
                    291:        else {
                    292:                *bufp += off;
                    293:                *wrlen = len - off;
                    294:        }
                    295:        return (0);
1.1       cgd       296: }
                    297:
1.82      jdolecek  298: static int
1.1       cgd       299: kernfs_xwrite(kt, buf, len)
1.75      jdolecek  300:        const struct kern_target *kt;
1.1       cgd       301:        char *buf;
1.82      jdolecek  302:        size_t len;
1.1       cgd       303: {
1.23      mycroft   304:
1.1       cgd       305:        switch (kt->kt_tag) {
1.23      mycroft   306:        case KTT_HOSTNAME:
1.1       cgd       307:                if (buf[len-1] == '\n')
                    308:                        --len;
1.60      perry     309:                memcpy(hostname, buf, len);
1.17      cgd       310:                hostname[len] = '\0';
1.82      jdolecek  311:                hostnamelen = (size_t) len;
1.1       cgd       312:                return (0);
                    313:
                    314:        default:
                    315:                return (EIO);
                    316:        }
                    317: }
                    318:
1.17      cgd       319:
                    320: /*
1.1       cgd       321:  * vp is the current namei directory
                    322:  * ndp is the name to locate in that directory...
                    323:  */
1.41      christos  324: int
                    325: kernfs_lookup(v)
                    326:        void *v;
                    327: {
1.23      mycroft   328:        struct vop_lookup_args /* {
                    329:                struct vnode * a_dvp;
                    330:                struct vnode ** a_vpp;
                    331:                struct componentname * a_cnp;
1.41      christos  332:        } */ *ap = v;
1.23      mycroft   333:        struct componentname *cnp = ap->a_cnp;
                    334:        struct vnode **vpp = ap->a_vpp;
                    335:        struct vnode *dvp = ap->a_dvp;
1.48      cgd       336:        const char *pname = cnp->cn_nameptr;
1.75      jdolecek  337:        const struct kern_target *kt;
1.1       cgd       338:        struct vnode *fvp;
1.64      wrstuden  339:        int error, i, wantpunlock;
1.1       cgd       340:
                    341: #ifdef KERNFS_DIAGNOSTIC
1.51      christos  342:        printf("kernfs_lookup(%p)\n", ap);
                    343:        printf("kernfs_lookup(dp = %p, vpp = %p, cnp = %p)\n", dvp, vpp, ap->a_cnp);
1.47      christos  344:        printf("kernfs_lookup(%s)\n", pname);
1.1       cgd       345: #endif
1.23      mycroft   346:
1.35      mycroft   347:        *vpp = NULLVP;
1.64      wrstuden  348:        cnp->cn_flags &= ~PDIRUNLOCK;
1.35      mycroft   349:
                    350:        if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
                    351:                return (EROFS);
                    352:
1.23      mycroft   353:        if (cnp->cn_namelen == 1 && *pname == '.') {
                    354:                *vpp = dvp;
1.1       cgd       355:                VREF(dvp);
                    356:                return (0);
                    357:        }
1.13      cgd       358:
1.64      wrstuden  359:        /*
                    360:         * This code only supports a flat directory, so we don't
                    361:         * need to worry about ..
                    362:         */
                    363:
1.17      cgd       364: #if 0
1.60      perry     365:        if (cnp->cn_namelen == 4 && memcmp(pname, "root", 4) == 0) {
1.23      mycroft   366:                *vpp = rootdir;
1.17      cgd       367:                VREF(rootdir);
1.57      fvdl      368:                vn_lock(rootdir, LK_SHARED | LK_RETRY);
1.1       cgd       369:                return (0);
                    370:        }
1.13      cgd       371: #endif
1.25      mycroft   372:
1.64      wrstuden  373:        wantpunlock = (~cnp->cn_flags & (LOCKPARENT | ISLASTCN));
                    374:
1.35      mycroft   375:        for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) {
1.26      mycroft   376:                if (cnp->cn_namelen == kt->kt_namlen &&
1.60      perry     377:                    memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
1.35      mycroft   378:                        goto found;
1.1       cgd       379:        }
                    380:
                    381: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  382:        printf("kernfs_lookup: i = %d, failed", i);
1.1       cgd       383: #endif
                    384:
1.35      mycroft   385:        return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
1.23      mycroft   386:
1.35      mycroft   387: found:
1.23      mycroft   388:        if (kt->kt_tag == KTT_DEVICE) {
                    389:                dev_t *dp = kt->kt_data;
1.24      mycroft   390:        loop:
1.57      fvdl      391:                if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) {
1.24      mycroft   392:                        return (ENOENT);
1.57      fvdl      393:                }
1.23      mycroft   394:                *vpp = fvp;
1.87      thorpej   395:                if (vget(fvp, LK_EXCLUSIVE))
1.24      mycroft   396:                        goto loop;
1.64      wrstuden  397:                if (wantpunlock) {
                    398:                        VOP_UNLOCK(dvp, 0);
                    399:                        cnp->cn_flags |= PDIRUNLOCK;
                    400:                }
1.23      mycroft   401:                return (0);
                    402:        }
1.1       cgd       403:
                    404: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  405:        printf("kernfs_lookup: allocate new vnode\n");
1.1       cgd       406: #endif
1.41      christos  407:        error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);
1.57      fvdl      408:        if (error) {
1.23      mycroft   409:                return (error);
1.57      fvdl      410:        }
1.23      mycroft   411:
                    412:        MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP,
                    413:            M_WAITOK);
                    414:        VTOKERN(fvp)->kf_kt = kt;
                    415:        fvp->v_type = kt->kt_vtype;
1.64      wrstuden  416:        vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY);
1.23      mycroft   417:        *vpp = fvp;
                    418:
1.1       cgd       419: #ifdef KERNFS_DIAGNOSTIC
1.51      christos  420:        printf("kernfs_lookup: newvp = %p\n", fvp);
1.1       cgd       421: #endif
1.64      wrstuden  422:        if (wantpunlock) {
                    423:                VOP_UNLOCK(dvp, 0);
                    424:                cnp->cn_flags |= PDIRUNLOCK;
                    425:        }
1.1       cgd       426:        return (0);
                    427: }
                    428:
1.28      mycroft   429: int
1.41      christos  430: kernfs_access(v)
                    431:        void *v;
                    432: {
1.23      mycroft   433:        struct vop_access_args /* {
                    434:                struct vnode *a_vp;
1.34      mycroft   435:                int a_mode;
1.23      mycroft   436:                struct ucred *a_cred;
                    437:                struct proc *a_p;
1.41      christos  438:        } */ *ap = v;
1.26      mycroft   439:        struct vnode *vp = ap->a_vp;
1.49      mycroft   440:        mode_t mode;
1.17      cgd       441:
1.49      mycroft   442:        if (vp->v_flag & VROOT) {
                    443:                mode = DIR_MODE;
                    444:        } else {
1.75      jdolecek  445:                const struct kern_target *kt = VTOKERN(vp)->kf_kt;
1.49      mycroft   446:                mode = kt->kt_mode;
                    447:        }
                    448:
                    449:        return (vaccess(vp->v_type, mode, (uid_t)0, (gid_t)0, ap->a_mode,
                    450:            ap->a_cred));
1.23      mycroft   451: }
                    452:
1.41      christos  453: int
                    454: kernfs_getattr(v)
                    455:        void *v;
                    456: {
1.23      mycroft   457:        struct vop_getattr_args /* {
                    458:                struct vnode *a_vp;
                    459:                struct vattr *a_vap;
                    460:                struct ucred *a_cred;
                    461:                struct proc *a_p;
1.41      christos  462:        } */ *ap = v;
1.23      mycroft   463:        struct vnode *vp = ap->a_vp;
                    464:        struct vattr *vap = ap->a_vap;
1.1       cgd       465:        int error = 0;
1.28      mycroft   466:        char strbuf[KSTRING], *buf;
1.1       cgd       467:
1.60      perry     468:        memset((caddr_t) vap, 0, sizeof(*vap));
1.1       cgd       469:        vattr_null(vap);
1.17      cgd       470:        vap->va_uid = 0;
                    471:        vap->va_gid = 0;
1.1       cgd       472:        vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1.23      mycroft   473:        vap->va_size = 0;
1.1       cgd       474:        vap->va_blocksize = DEV_BSIZE;
1.81      lukem     475:        /*
1.83      simonb    476:         * Make all times be current TOD.  Avoid microtime(9), it's slow.
                    477:         * We don't guard the read from time(9) with splclock(9) since we
                    478:         * don't actually need to be THAT sure the access is atomic.
1.81      lukem     479:         */
1.83      simonb    480:        TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime);
1.81      lukem     481:        vap->va_atime = vap->va_mtime = vap->va_ctime;
1.1       cgd       482:        vap->va_gen = 0;
                    483:        vap->va_flags = 0;
                    484:        vap->va_rdev = 0;
                    485:        vap->va_bytes = 0;
                    486:
                    487:        if (vp->v_flag & VROOT) {
                    488: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  489:                printf("kernfs_getattr: stat rootdir\n");
1.1       cgd       490: #endif
1.17      cgd       491:                vap->va_type = VDIR;
1.23      mycroft   492:                vap->va_mode = DIR_MODE;
1.1       cgd       493:                vap->va_nlink = 2;
                    494:                vap->va_fileid = 2;
                    495:                vap->va_size = DEV_BSIZE;
                    496:        } else {
1.75      jdolecek  497:                const struct kern_target *kt = VTOKERN(vp)->kf_kt;
1.84      jdolecek  498:                size_t nread, total;
1.1       cgd       499: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  500:                printf("kernfs_getattr: stat target %s\n", kt->kt_name);
1.1       cgd       501: #endif
1.17      cgd       502:                vap->va_type = kt->kt_vtype;
1.23      mycroft   503:                vap->va_mode = kt->kt_mode;
1.1       cgd       504:                vap->va_nlink = 1;
1.57      fvdl      505:                vap->va_fileid = 1 + (kt - kern_targets);
1.84      jdolecek  506:                total = 0;
                    507:                do {
                    508:                        buf = strbuf;
                    509:                        error = kernfs_xread(kt, total, &buf,
                    510:                                sizeof(strbuf), &nread);
                    511:                        total += nread;
                    512:                } while (error == 0 && nread != 0);
                    513:                vap->va_size = total;
1.1       cgd       514:        }
                    515:
                    516: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  517:        printf("kernfs_getattr: return error %d\n", error);
1.1       cgd       518: #endif
                    519:        return (error);
                    520: }
                    521:
1.41      christos  522: /*ARGSUSED*/
                    523: int
                    524: kernfs_setattr(v)
                    525:        void *v;
1.1       cgd       526: {
                    527:        /*
1.17      cgd       528:         * Silently ignore attribute changes.
                    529:         * This allows for open with truncate to have no
                    530:         * effect until some data is written.  I want to
                    531:         * do it this way because all writes are atomic.
1.1       cgd       532:         */
1.17      cgd       533:        return (0);
1.1       cgd       534: }
                    535:
1.28      mycroft   536: int
1.41      christos  537: kernfs_read(v)
                    538:        void *v;
                    539: {
1.23      mycroft   540:        struct vop_read_args /* {
                    541:                struct vnode *a_vp;
                    542:                struct uio *a_uio;
                    543:                int  a_ioflag;
                    544:                struct ucred *a_cred;
1.41      christos  545:        } */ *ap = v;
1.23      mycroft   546:        struct vnode *vp = ap->a_vp;
                    547:        struct uio *uio = ap->a_uio;
1.75      jdolecek  548:        const struct kern_target *kt;
1.28      mycroft   549:        char strbuf[KSTRING], *buf;
1.82      jdolecek  550:        off_t off;
                    551:        size_t len;
1.28      mycroft   552:        int error;
1.23      mycroft   553:
                    554:        if (vp->v_type == VDIR)
                    555:                return (EOPNOTSUPP);
                    556:
                    557:        kt = VTOKERN(vp)->kf_kt;
                    558:
1.1       cgd       559: #ifdef KERNFS_DIAGNOSTIC
1.47      christos  560:        printf("kern_read %s\n", kt->kt_name);
1.1       cgd       561: #endif
1.18      cgd       562:
1.28      mycroft   563:        off = uio->uio_offset;
1.82      jdolecek  564:        buf = strbuf;
                    565:        if ((error = kernfs_xread(kt, off, &buf, sizeof(strbuf), &len)) == 0)
                    566:                error = uiomove(buf, len, uio);
                    567:        return (error);
1.1       cgd       568: }
                    569:
1.28      mycroft   570: int
1.41      christos  571: kernfs_write(v)
                    572:        void *v;
                    573: {
1.23      mycroft   574:        struct vop_write_args /* {
                    575:                struct vnode *a_vp;
                    576:                struct uio *a_uio;
                    577:                int  a_ioflag;
                    578:                struct ucred *a_cred;
1.41      christos  579:        } */ *ap = v;
1.23      mycroft   580:        struct vnode *vp = ap->a_vp;
                    581:        struct uio *uio = ap->a_uio;
1.75      jdolecek  582:        const struct kern_target *kt;
1.23      mycroft   583:        int error, xlen;
1.1       cgd       584:        char strbuf[KSTRING];
1.23      mycroft   585:
                    586:        if (vp->v_type == VDIR)
                    587:                return (EOPNOTSUPP);
                    588:
                    589:        kt = VTOKERN(vp)->kf_kt;
1.1       cgd       590:
                    591:        if (uio->uio_offset != 0)
                    592:                return (EINVAL);
                    593:
                    594:        xlen = min(uio->uio_resid, KSTRING-1);
1.41      christos  595:        if ((error = uiomove(strbuf, xlen, uio)) != 0)
1.1       cgd       596:                return (error);
                    597:
                    598:        if (uio->uio_resid != 0)
                    599:                return (EIO);
                    600:
                    601:        strbuf[xlen] = '\0';
1.17      cgd       602:        xlen = strlen(strbuf);
1.1       cgd       603:        return (kernfs_xwrite(kt, strbuf, xlen));
                    604: }
                    605:
1.41      christos  606: int
                    607: kernfs_readdir(v)
                    608:        void *v;
                    609: {
1.23      mycroft   610:        struct vop_readdir_args /* {
                    611:                struct vnode *a_vp;
                    612:                struct uio *a_uio;
                    613:                struct ucred *a_cred;
1.26      mycroft   614:                int *a_eofflag;
1.57      fvdl      615:                off_t **a_cookies;
                    616:                int a_*ncookies;
1.41      christos  617:        } */ *ap = v;
1.23      mycroft   618:        struct uio *uio = ap->a_uio;
1.37      mycroft   619:        struct dirent d;
1.75      jdolecek  620:        const struct kern_target *kt;
1.67      sommerfe  621:        off_t i;
1.1       cgd       622:        int error;
1.57      fvdl      623:        off_t *cookies = NULL;
                    624:        int ncookies = 0, nc = 0;
1.1       cgd       625:
1.23      mycroft   626:        if (ap->a_vp->v_type != VDIR)
                    627:                return (ENOTDIR);
                    628:
1.37      mycroft   629:        if (uio->uio_resid < UIO_MX)
                    630:                return (EINVAL);
1.38      mycroft   631:        if (uio->uio_offset < 0)
1.37      mycroft   632:                return (EINVAL);
1.26      mycroft   633:
1.1       cgd       634:        error = 0;
1.38      mycroft   635:        i = uio->uio_offset;
1.66      sommerfe  636:
                    637:        if (i >= nkern_targets)
                    638:                return 0;
                    639:
1.60      perry     640:        memset((caddr_t)&d, 0, UIO_MX);
1.37      mycroft   641:        d.d_reclen = UIO_MX;
                    642:
1.57      fvdl      643:        if (ap->a_ncookies) {
                    644:                nc = uio->uio_resid / UIO_MX;
                    645:                nc = min(nc, (nkern_targets - i));
1.70      thorpej   646:                cookies = malloc(nc * sizeof(off_t), M_TEMP, M_WAITOK);
1.57      fvdl      647:                *ap->a_cookies = cookies;
                    648:        }
                    649:
1.23      mycroft   650:        for (kt = &kern_targets[i];
                    651:             uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) {
1.1       cgd       652: #ifdef KERNFS_DIAGNOSTIC
1.74      mrg       653:                printf("kernfs_readdir: i = %d\n", (int)i);
1.1       cgd       654: #endif
1.26      mycroft   655:
1.23      mycroft   656:                if (kt->kt_tag == KTT_DEVICE) {
1.26      mycroft   657:                        dev_t *dp = kt->kt_data;
1.23      mycroft   658:                        struct vnode *fvp;
1.26      mycroft   659:
1.23      mycroft   660:                        if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
                    661:                                continue;
                    662:                }
1.26      mycroft   663:
1.37      mycroft   664:                d.d_fileno = i + 3;
                    665:                d.d_namlen = kt->kt_namlen;
1.60      perry     666:                memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1.37      mycroft   667:                d.d_type = kt->kt_type;
1.26      mycroft   668:
1.41      christos  669:                if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
1.1       cgd       670:                        break;
1.57      fvdl      671:                if (cookies) {
1.38      mycroft   672:                        *cookies++ = i + 1;
1.57      fvdl      673:                        ncookies++;
                    674:                }
                    675:        }
                    676:
                    677:        if (ap->a_ncookies) {
                    678:                if (error) {
1.70      thorpej   679:                        free(*ap->a_cookies, M_TEMP);
1.57      fvdl      680:                        *ap->a_ncookies = 0;
                    681:                        *ap->a_cookies = NULL;
                    682:                } else
                    683:                        *ap->a_ncookies = ncookies;
1.1       cgd       684:        }
                    685:
1.38      mycroft   686:        uio->uio_offset = i;
1.1       cgd       687:        return (error);
                    688: }
                    689:
1.41      christos  690: int
                    691: kernfs_inactive(v)
                    692:        void *v;
                    693: {
1.23      mycroft   694:        struct vop_inactive_args /* {
                    695:                struct vnode *a_vp;
1.57      fvdl      696:                struct proc *a_p;
1.41      christos  697:        } */ *ap = v;
1.23      mycroft   698:        struct vnode *vp = ap->a_vp;
                    699:
                    700: #ifdef KERNFS_DIAGNOSTIC
1.51      christos  701:        printf("kernfs_inactive(%p)\n", vp);
1.23      mycroft   702: #endif
1.1       cgd       703:        /*
                    704:         * Clear out the v_type field to avoid
                    705:         * nasty things happening in vgone().
                    706:         */
1.57      fvdl      707:        VOP_UNLOCK(vp, 0);
1.1       cgd       708:        vp->v_type = VNON;
1.23      mycroft   709:        return (0);
                    710: }
                    711:
1.41      christos  712: int
                    713: kernfs_reclaim(v)
                    714:        void *v;
                    715: {
1.23      mycroft   716:        struct vop_reclaim_args /* {
                    717:                struct vnode *a_vp;
1.41      christos  718:        } */ *ap = v;
1.23      mycroft   719:        struct vnode *vp = ap->a_vp;
                    720:
1.1       cgd       721: #ifdef KERNFS_DIAGNOSTIC
1.51      christos  722:        printf("kernfs_reclaim(%p)\n", vp);
1.1       cgd       723: #endif
1.23      mycroft   724:        if (vp->v_data) {
                    725:                FREE(vp->v_data, M_TEMP);
                    726:                vp->v_data = 0;
                    727:        }
1.1       cgd       728:        return (0);
                    729: }
                    730:
                    731: /*
1.23      mycroft   732:  * Return POSIX pathconf information applicable to special devices.
                    733:  */
1.41      christos  734: int
                    735: kernfs_pathconf(v)
                    736:        void *v;
                    737: {
1.23      mycroft   738:        struct vop_pathconf_args /* {
                    739:                struct vnode *a_vp;
                    740:                int a_name;
1.29      cgd       741:                register_t *a_retval;
1.41      christos  742:        } */ *ap = v;
1.23      mycroft   743:
                    744:        switch (ap->a_name) {
                    745:        case _PC_LINK_MAX:
                    746:                *ap->a_retval = LINK_MAX;
                    747:                return (0);
                    748:        case _PC_MAX_CANON:
                    749:                *ap->a_retval = MAX_CANON;
                    750:                return (0);
                    751:        case _PC_MAX_INPUT:
                    752:                *ap->a_retval = MAX_INPUT;
                    753:                return (0);
                    754:        case _PC_PIPE_BUF:
                    755:                *ap->a_retval = PIPE_BUF;
                    756:                return (0);
                    757:        case _PC_CHOWN_RESTRICTED:
                    758:                *ap->a_retval = 1;
                    759:                return (0);
                    760:        case _PC_VDISABLE:
                    761:                *ap->a_retval = _POSIX_VDISABLE;
1.59      kleink    762:                return (0);
                    763:        case _PC_SYNC_IO:
                    764:                *ap->a_retval = 1;
1.23      mycroft   765:                return (0);
                    766:        default:
                    767:                return (EINVAL);
                    768:        }
                    769:        /* NOTREACHED */
                    770: }
                    771:
                    772: /*
                    773:  * Print out the contents of a /dev/fd vnode.
1.1       cgd       774:  */
                    775: /* ARGSUSED */
1.41      christos  776: int
                    777: kernfs_print(v)
                    778:        void *v;
1.23      mycroft   779: {
                    780:
1.47      christos  781:        printf("tag VT_KERNFS, kernfs vnode\n");
1.23      mycroft   782:        return (0);
                    783: }
                    784:
1.40      mycroft   785: int
1.41      christos  786: kernfs_link(v)
                    787:        void *v;
                    788: {
1.40      mycroft   789:        struct vop_link_args /* {
                    790:                struct vnode *a_dvp;
                    791:                struct vnode *a_vp;
                    792:                struct componentname *a_cnp;
1.41      christos  793:        } */ *ap = v;
1.40      mycroft   794:
                    795:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                    796:        vput(ap->a_dvp);
                    797:        return (EROFS);
                    798: }
                    799:
                    800: int
1.41      christos  801: kernfs_symlink(v)
                    802:        void *v;
                    803: {
1.40      mycroft   804:        struct vop_symlink_args /* {
                    805:                struct vnode *a_dvp;
                    806:                struct vnode **a_vpp;
                    807:                struct componentname *a_cnp;
                    808:                struct vattr *a_vap;
                    809:                char *a_target;
1.41      christos  810:        } */ *ap = v;
1.40      mycroft   811:
                    812:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
                    813:        vput(ap->a_dvp);
                    814:        return (EROFS);
1.1       cgd       815: }

CVSweb <webmaster@jp.NetBSD.org>