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

Annotation of src/sys/miscfs/procfs/procfs_subr.c, Revision 1.102.2.1

1.102.2.1! rmind       1: /*     $NetBSD: procfs_subr.c,v 1.102 2012/11/25 01:03:05 christos Exp $       */
1.75      ad          2:
                      3: /*-
1.86      ad          4:  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
1.75      ad          5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Andrew Doran.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
1.57      agc        31:
                     32: /*
                     33:  * Copyright (c) 1993
                     34:  *     The Regents of the University of California.  All rights reserved.
                     35:  *
                     36:  * This code is derived from software contributed to Berkeley by
                     37:  * Jan-Simon Pendry.
                     38:  *
                     39:  * Redistribution and use in source and binary forms, with or without
                     40:  * modification, are permitted provided that the following conditions
                     41:  * are met:
                     42:  * 1. Redistributions of source code must retain the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer.
                     44:  * 2. Redistributions in binary form must reproduce the above copyright
                     45:  *    notice, this list of conditions and the following disclaimer in the
                     46:  *    documentation and/or other materials provided with the distribution.
                     47:  * 3. Neither the name of the University nor the names of its contributors
                     48:  *    may be used to endorse or promote products derived from this software
                     49:  *    without specific prior written permission.
                     50:  *
                     51:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     52:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     53:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     54:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     55:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     56:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     57:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     58:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     59:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     60:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     61:  * SUCH DAMAGE.
                     62:  *
                     63:  *     @(#)procfs_subr.c       8.6 (Berkeley) 5/14/95
                     64:  */
1.13      cgd        65:
1.1       pk         66: /*
1.20      thorpej    67:  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
1.5       cgd        68:  * Copyright (c) 1993 Jan-Simon Pendry
1.2       pk         69:  *
1.5       cgd        70:  * This code is derived from software contributed to Berkeley by
                     71:  * Jan-Simon Pendry.
                     72:  *
1.2       pk         73:  * Redistribution and use in source and binary forms, with or without
                     74:  * modification, are permitted provided that the following conditions
                     75:  * are met:
                     76:  * 1. Redistributions of source code must retain the above copyright
                     77:  *    notice, this list of conditions and the following disclaimer.
                     78:  * 2. Redistributions in binary form must reproduce the above copyright
                     79:  *    notice, this list of conditions and the following disclaimer in the
                     80:  *    documentation and/or other materials provided with the distribution.
                     81:  * 3. All advertising materials mentioning features or use of this software
                     82:  *    must display the following acknowledgement:
1.5       cgd        83:  *     This product includes software developed by the University of
                     84:  *     California, Berkeley and its contributors.
                     85:  * 4. Neither the name of the University nor the names of its contributors
                     86:  *    may be used to endorse or promote products derived from this software
                     87:  *    without specific prior written permission.
                     88:  *
                     89:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     90:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     91:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     92:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     93:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     94:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     95:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     96:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     97:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     98:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     99:  * SUCH DAMAGE.
1.2       pk        100:  *
1.23      fvdl      101:  *     @(#)procfs_subr.c       8.6 (Berkeley) 5/14/95
1.1       pk        102:  */
1.39      lukem     103:
                    104: #include <sys/cdefs.h>
1.102.2.1! rmind     105: __KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.102 2012/11/25 01:03:05 christos Exp $");
1.5       cgd       106:
1.4       mycroft   107: #include <sys/param.h>
                    108: #include <sys/systm.h>
                    109: #include <sys/time.h>
                    110: #include <sys/kernel.h>
                    111: #include <sys/proc.h>
                    112: #include <sys/vnode.h>
1.11      mycroft   113: #include <sys/malloc.h>
1.18      mycroft   114: #include <sys/stat.h>
1.42      christos  115: #include <sys/file.h>
                    116: #include <sys/filedesc.h>
1.73      elad      117: #include <sys/kauth.h>
1.18      mycroft   118:
1.5       cgd       119: #include <miscfs/procfs/procfs.h>
1.1       pk        120:
1.65      xtraeme   121: void procfs_hashins(struct pfsnode *);
                    122: void procfs_hashrem(struct pfsnode *);
1.102.2.1! rmind     123: struct vnode *procfs_hashget(pid_t, pfstype, int, struct mount *);
1.29      fvdl      124:
                    125: LIST_HEAD(pfs_hashhead, pfsnode) *pfs_hashtbl;
1.30      fvdl      126: u_long pfs_ihash;      /* size of hash table - 1 */
1.38      chs       127: #define PFSPIDHASH(pid)        ((pid) & pfs_ihash)
1.29      fvdl      128:
1.76      ad        129: kmutex_t pfs_hashlock;
                    130: kmutex_t pfs_ihash_lock;
1.1       pk        131:
1.20      thorpej   132: #define        ISSET(t, f)     ((t) & (f))
                    133:
1.1       pk        134: /*
1.5       cgd       135:  * allocate a pfsnode/vnode pair.  the vnode is
1.27      wrstuden  136:  * referenced, and locked.
1.5       cgd       137:  *
                    138:  * the pid, pfs_type, and mount point uniquely
                    139:  * identify a pfsnode.  the mount point is needed
                    140:  * because someone might mount this filesystem
                    141:  * twice.
                    142:  *
                    143:  * all pfsnodes are maintained on a singly-linked
                    144:  * list.  new nodes are only allocated when they cannot
                    145:  * be found on this list.  entries on the list are
                    146:  * removed when the vfs reclaim entry is called.
                    147:  *
                    148:  * a single lock is kept for the entire list.  this is
                    149:  * needed because the getnewvnode() function can block
                    150:  * waiting for a vnode to become free, in which case there
                    151:  * may be more than one process trying to get the same
                    152:  * vnode.  this lock is only taken if we are going to
                    153:  * call getnewvnode, since the kernel itself is single-threaded.
                    154:  *
                    155:  * if an entry is found on the list, then call vget() to
                    156:  * take a reference.  this is done because there may be
                    157:  * zero references to it and so it needs to removed from
                    158:  * the vnode free list.
1.1       pk        159:  */
1.11      mycroft   160: int
1.99      rmind     161: procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid,
                    162:     pfstype pfs_type, int fd, struct proc *p)
1.1       pk        163: {
1.12      mycroft   164:        struct pfsnode *pfs;
                    165:        struct vnode *vp;
1.5       cgd       166:        int error;
                    167:
1.102.2.1! rmind     168:        *vpp = procfs_hashget(pid, pfs_type, fd, mp);
1.82      ad        169:        if (*vpp != NULL)
1.76      ad        170:                return (0);
1.1       pk        171:
1.99      rmind     172:        error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, NULL, &vp);
                    173:        if (error) {
1.29      fvdl      174:                *vpp = NULL;
                    175:                return (error);
1.5       cgd       176:        }
1.93      cegger    177:        pfs = malloc(sizeof(struct pfsnode), M_TEMP, M_WAITOK);
1.76      ad        178:
                    179:        mutex_enter(&pfs_hashlock);
1.102.2.1! rmind     180:        if ((*vpp = procfs_hashget(pid, pfs_type, fd, mp)) != NULL) {
1.76      ad        181:                mutex_exit(&pfs_hashlock);
                    182:                ungetnewvnode(vp);
1.93      cegger    183:                free(pfs, M_TEMP);
1.102.2.1! rmind     184:                return 0;
1.76      ad        185:        }
1.5       cgd       186:
1.11      mycroft   187:        vp->v_data = pfs;
1.42      christos  188:        pfs->pfs_pid = pid;
1.5       cgd       189:        pfs->pfs_type = pfs_type;
1.11      mycroft   190:        pfs->pfs_vnode = vp;
1.5       cgd       191:        pfs->pfs_flags = 0;
1.42      christos  192:        pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type, fd);
                    193:        pfs->pfs_fd = fd;
1.5       cgd       194:
                    195:        switch (pfs_type) {
1.58      darcy     196:        case PFSroot:   /* /proc = dr-xr-xr-x */
1.82      ad        197:                vp->v_vflag |= VV_ROOT;
1.74      christos  198:                /*FALLTHROUGH*/
                    199:        case PFSproc:   /* /proc/N = dr-xr-xr-x */
1.17      mycroft   200:                pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
1.11      mycroft   201:                vp->v_type = VDIR;
                    202:                break;
                    203:
1.101     christos  204:        case PFStask:   /* /proc/N/task = dr-xr-xr-x */
                    205:                if (fd == -1) {
                    206:                        pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|
                    207:                            S_IROTH|S_IXOTH;
                    208:                        vp->v_type = VDIR;
                    209:                        break;
                    210:                }
                    211:                /*FALLTHROUGH*/
1.58      darcy     212:        case PFScurproc:        /* /proc/curproc = lr-xr-xr-x */
                    213:        case PFSself:   /* /proc/self    = lr-xr-xr-x */
1.66      atatat    214:        case PFScwd:    /* /proc/N/cwd = lr-xr-xr-x */
                    215:        case PFSchroot: /* /proc/N/chroot = lr-xr-xr-x */
1.70      christos  216:        case PFSexe:    /* /proc/N/exe = lr-xr-xr-x */
1.22      mycroft   217:                pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
1.11      mycroft   218:                vp->v_type = VLNK;
1.5       cgd       219:                break;
                    220:
1.58      darcy     221:        case PFSfd:
1.101     christos  222:                if (fd == -1) { /* /proc/N/fd = dr-x------ */
1.52      christos  223:                        pfs->pfs_mode = S_IRUSR|S_IXUSR;
1.42      christos  224:                        vp->v_type = VDIR;
                    225:                } else {        /* /proc/N/fd/M = [ps-]rw------- */
1.86      ad        226:                        file_t *fp;
                    227:                        vnode_t *vxp;
1.44      jdolecek  228:
1.86      ad        229:                        if ((fp = fd_getfile2(p, pfs->pfs_fd)) == NULL) {
1.75      ad        230:                                error = EBADF;
1.44      jdolecek  231:                                goto bad;
1.75      ad        232:                        }
1.44      jdolecek  233:
1.42      christos  234:                        pfs->pfs_mode = S_IRUSR|S_IWUSR;
                    235:                        switch (fp->f_type) {
                    236:                        case DTYPE_VNODE:
1.86      ad        237:                                vxp = fp->f_data;
1.50      jdolecek  238:
1.51      christos  239:                                /*
1.63      perry     240:                                 * We make symlinks for directories
1.51      christos  241:                                 * to avoid cycles.
                    242:                                 */
                    243:                                if (vxp->v_type == VDIR)
                    244:                                        goto symlink;
1.42      christos  245:                                vp->v_type = vxp->v_type;
                    246:                                break;
                    247:                        case DTYPE_PIPE:
                    248:                                vp->v_type = VFIFO;
                    249:                                break;
                    250:                        case DTYPE_SOCKET:
                    251:                                vp->v_type = VSOCK;
1.51      christos  252:                                break;
                    253:                        case DTYPE_KQUEUE:
                    254:                        case DTYPE_MISC:
1.102     christos  255:                        case DTYPE_SEM:
1.51      christos  256:                        symlink:
                    257:                                pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|
                    258:                                    S_IXGRP|S_IROTH|S_IXOTH;
                    259:                                vp->v_type = VLNK;
1.42      christos  260:                                break;
1.45      jdolecek  261:                        default:
1.44      jdolecek  262:                                error = EOPNOTSUPP;
1.86      ad        263:                                closef(fp);
1.44      jdolecek  264:                                goto bad;
1.42      christos  265:                        }
1.86      ad        266:                        closef(fp);
1.42      christos  267:                }
1.5       cgd       268:                break;
                    269:
1.58      darcy     270:        case PFSfile:   /* /proc/N/file = -rw------- */
                    271:        case PFSmem:    /* /proc/N/mem = -rw------- */
                    272:        case PFSregs:   /* /proc/N/regs = -rw------- */
                    273:        case PFSfpregs: /* /proc/N/fpregs = -rw------- */
1.17      mycroft   274:                pfs->pfs_mode = S_IRUSR|S_IWUSR;
1.9       cgd       275:                vp->v_type = VREG;
                    276:                break;
                    277:
1.58      darcy     278:        case PFSctl:    /* /proc/N/ctl = --w------ */
                    279:        case PFSnote:   /* /proc/N/note = --w------ */
                    280:        case PFSnotepg: /* /proc/N/notepg = --w------ */
1.17      mycroft   281:                pfs->pfs_mode = S_IWUSR;
1.6       ws        282:                vp->v_type = VREG;
1.5       cgd       283:                break;
                    284:
1.58      darcy     285:        case PFSmap:    /* /proc/N/map = -r--r--r-- */
                    286:        case PFSmaps:   /* /proc/N/maps = -r--r--r-- */
                    287:        case PFSstatus: /* /proc/N/status = -r--r--r-- */
                    288:        case PFSstat:   /* /proc/N/stat = -r--r--r-- */
                    289:        case PFScmdline:        /* /proc/N/cmdline = -r--r--r-- */
1.71      christos  290:        case PFSemul:   /* /proc/N/emul = -r--r--r-- */
1.58      darcy     291:        case PFSmeminfo:        /* /proc/meminfo = -r--r--r-- */
1.80      agc       292:        case PFScpustat:        /* /proc/stat = -r--r--r-- */
1.69      manu      293:        case PFSdevices:        /* /proc/devices = -r--r--r-- */
1.58      darcy     294:        case PFScpuinfo:        /* /proc/cpuinfo = -r--r--r-- */
                    295:        case PFSuptime: /* /proc/uptime = -r--r--r-- */
1.62      jdolecek  296:        case PFSmounts: /* /proc/mounts = -r--r--r-- */
1.80      agc       297:        case PFSloadavg:        /* /proc/loadavg = -r--r--r-- */
                    298:        case PFSstatm:  /* /proc/N/statm = -r--r--r-- */
1.100     jmcneill  299:        case PFSversion:        /* /proc/version = -r--r--r-- */
1.17      mycroft   300:                pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
1.6       ws        301:                vp->v_type = VREG;
1.5       cgd       302:                break;
                    303:
1.40      thorpej   304: #ifdef __HAVE_PROCFS_MACHDEP
                    305:        PROCFS_MACHDEP_NODETYPE_CASES
                    306:                procfs_machdep_allocvp(vp);
                    307:                break;
                    308: #endif
                    309:
1.5       cgd       310:        default:
1.11      mycroft   311:                panic("procfs_allocvp");
1.5       cgd       312:        }
1.27      wrstuden  313:
1.29      fvdl      314:        procfs_hashins(pfs);
1.34      chs       315:        uvm_vnp_setsize(vp, 0);
1.76      ad        316:        mutex_exit(&pfs_hashlock);
1.1       pk        317:
1.44      jdolecek  318:        *vpp = vp;
                    319:        return (0);
                    320:
                    321:  bad:
1.76      ad        322:        mutex_exit(&pfs_hashlock);
1.93      cegger    323:        free(pfs, M_TEMP);
1.82      ad        324:        vp->v_data = NULL;
1.44      jdolecek  325:        ungetnewvnode(vp);
1.5       cgd       326:        return (error);
1.1       pk        327: }
                    328:
1.11      mycroft   329: int
1.94      dsl       330: procfs_freevp(struct vnode *vp)
1.1       pk        331: {
1.5       cgd       332:        struct pfsnode *pfs = VTOPFS(vp);
                    333:
1.29      fvdl      334:        procfs_hashrem(pfs);
1.1       pk        335:
1.93      cegger    336:        free(vp->v_data, M_TEMP);
                    337:        vp->v_data = NULL;
1.5       cgd       338:        return (0);
1.1       pk        339: }
                    340:
1.11      mycroft   341: int
1.94      dsl       342: procfs_rw(void *v)
1.1       pk        343: {
1.15      christos  344:        struct vop_read_args *ap = v;
1.11      mycroft   345:        struct vnode *vp = ap->a_vp;
                    346:        struct uio *uio = ap->a_uio;
1.67      christos  347:        struct lwp *curl;
                    348:        struct lwp *l;
1.56      fvdl      349:        struct pfsnode *pfs = VTOPFS(vp);
1.5       cgd       350:        struct proc *p;
1.73      elad      351:        int error;
1.5       cgd       352:
1.59      christos  353:        if (uio->uio_offset < 0)
                    354:                return EINVAL;
1.73      elad      355:
1.75      ad        356:        if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0)
                    357:                return error;
1.73      elad      358:
                    359:        curl = curlwp;
                    360:
1.59      christos  361:        /*
                    362:         * Do not allow init to be modified while in secure mode; it
                    363:         * could be duped into changing the security level.
                    364:         */
1.84      elad      365: #define        M2K(m)  ((m) == UIO_READ ? KAUTH_REQ_PROCESS_PROCFS_READ : \
                    366:                 KAUTH_REQ_PROCESS_PROCFS_WRITE)
1.88      ad        367:        mutex_enter(p->p_lock);
1.84      elad      368:        error = kauth_authorize_process(curl->l_cred, KAUTH_PROCESS_PROCFS,
1.73      elad      369:            p, pfs, KAUTH_ARG(M2K(uio->uio_rw)), NULL);
1.88      ad        370:        mutex_exit(p->p_lock);
1.75      ad        371:        if (error) {
                    372:                procfs_proc_unlock(p);
1.73      elad      373:                return (error);
1.75      ad        374:        }
1.73      elad      375: #undef M2K
1.67      christos  376:
1.88      ad        377:        mutex_enter(p->p_lock);
1.92      skrll     378:        LIST_FOREACH(l, &p->p_lwps, l_sibling) {
                    379:                if (l->l_stat != LSZOMB)
                    380:                        break;
                    381:        }
                    382:        /* Process is exiting if no-LWPS or all LWPs are LSZOMB */
                    383:        if (l == NULL) {
                    384:                mutex_exit(p->p_lock);
                    385:                procfs_proc_unlock(p);
                    386:                return ESRCH;
                    387:        }
                    388:
1.75      ad        389:        lwp_addref(l);
1.88      ad        390:        mutex_exit(p->p_lock);
1.63      perry     391:
1.19      mycroft   392:        switch (pfs->pfs_type) {
1.58      darcy     393:        case PFSnote:
                    394:        case PFSnotepg:
1.75      ad        395:                error = procfs_donote(curl, p, pfs, uio);
                    396:                break;
1.5       cgd       397:
1.58      darcy     398:        case PFSregs:
1.75      ad        399:                error = procfs_doregs(curl, l, pfs, uio);
                    400:                break;
1.9       cgd       401:
1.58      darcy     402:        case PFSfpregs:
1.75      ad        403:                error = procfs_dofpregs(curl, l, pfs, uio);
                    404:                break;
1.5       cgd       405:
1.58      darcy     406:        case PFSctl:
1.75      ad        407:                error = procfs_doctl(curl, l, pfs, uio);
                    408:                break;
1.5       cgd       409:
1.58      darcy     410:        case PFSstatus:
1.75      ad        411:                error = procfs_dostatus(curl, l, pfs, uio);
                    412:                break;
1.53      christos  413:
1.58      darcy     414:        case PFSstat:
1.75      ad        415:                error = procfs_do_pid_stat(curl, l, pfs, uio);
                    416:                break;
1.25      msaitoh   417:
1.58      darcy     418:        case PFSmap:
1.75      ad        419:                error = procfs_domap(curl, p, pfs, uio, 0);
                    420:                break;
1.37      fvdl      421:
1.58      darcy     422:        case PFSmaps:
1.75      ad        423:                error = procfs_domap(curl, p, pfs, uio, 1);
                    424:                break;
1.1       pk        425:
1.58      darcy     426:        case PFSmem:
1.75      ad        427:                error = procfs_domem(curl, l, pfs, uio);
                    428:                break;
1.26      christos  429:
1.58      darcy     430:        case PFScmdline:
1.75      ad        431:                error = procfs_docmdline(curl, p, pfs, uio);
                    432:                break;
1.35      fvdl      433:
1.58      darcy     434:        case PFSmeminfo:
1.75      ad        435:                error = procfs_domeminfo(curl, p, pfs, uio);
                    436:                break;
1.40      thorpej   437:
1.69      manu      438:        case PFSdevices:
1.75      ad        439:                error = procfs_dodevices(curl, p, pfs, uio);
                    440:                break;
1.69      manu      441:
1.58      darcy     442:        case PFScpuinfo:
1.75      ad        443:                error = procfs_docpuinfo(curl, p, pfs, uio);
                    444:                break;
1.40      thorpej   445:
1.80      agc       446:        case PFScpustat:
                    447:                error = procfs_docpustat(curl, p, pfs, uio);
                    448:                break;
                    449:
                    450:        case PFSloadavg:
                    451:                error = procfs_doloadavg(curl, p, pfs, uio);
                    452:                break;
                    453:
                    454:        case PFSstatm:
                    455:                error = procfs_do_pid_statm(curl, l, pfs, uio);
                    456:                break;
                    457:
1.58      darcy     458:        case PFSfd:
1.75      ad        459:                error = procfs_dofd(curl, p, pfs, uio);
                    460:                break;
1.46      jrf       461:
1.58      darcy     462:        case PFSuptime:
1.75      ad        463:                error = procfs_douptime(curl, p, pfs, uio);
                    464:                break;
1.42      christos  465:
1.62      jdolecek  466:        case PFSmounts:
1.75      ad        467:                error = procfs_domounts(curl, p, pfs, uio);
                    468:                break;
1.62      jdolecek  469:
1.71      christos  470:        case PFSemul:
1.75      ad        471:                error = procfs_doemul(curl, p, pfs, uio);
                    472:                break;
1.71      christos  473:
1.100     jmcneill  474:        case PFSversion:
                    475:                error = procfs_doversion(curl, p, pfs, uio);
                    476:                break;
                    477:
1.40      thorpej   478: #ifdef __HAVE_PROCFS_MACHDEP
                    479:        PROCFS_MACHDEP_NODETYPE_CASES
1.75      ad        480:                error = procfs_machdep_rw(curl, l, pfs, uio);
                    481:                break;
1.40      thorpej   482: #endif
1.1       pk        483:
1.5       cgd       484:        default:
1.75      ad        485:                error = EOPNOTSUPP;
                    486:                break;
1.5       cgd       487:        }
1.75      ad        488:
                    489:        /*
                    490:         * Release the references that we acquired earlier.
                    491:         */
                    492:        lwp_delref(l);
                    493:        procfs_proc_unlock(p);
                    494:
                    495:        return (error);
1.1       pk        496: }
                    497:
1.5       cgd       498: /*
1.64      christos  499:  * Get a string from userland into (bf).  Strip a trailing
1.5       cgd       500:  * nl character (to allow easy access from the shell).
1.11      mycroft   501:  * The buffer should be *buflenp + 1 chars long.  vfs_getuserstr
1.5       cgd       502:  * will automatically add a nul char at the end.
                    503:  *
                    504:  * Returns 0 on success or the following errors
                    505:  *
                    506:  * EINVAL:    file offset is non-zero.
                    507:  * EMSGSIZE:  message is longer than kernel buffer
                    508:  * EFAULT:    user i/o buffer is not addressable
                    509:  */
1.11      mycroft   510: int
1.94      dsl       511: vfs_getuserstr(struct uio *uio, char *bf, int *buflenp)
1.1       pk        512: {
1.5       cgd       513:        int xlen;
                    514:        int error;
                    515:
1.11      mycroft   516:        if (uio->uio_offset != 0)
                    517:                return (EINVAL);
                    518:
1.5       cgd       519:        xlen = *buflenp;
1.1       pk        520:
1.5       cgd       521:        /* must be able to read the whole string in one go */
                    522:        if (xlen < uio->uio_resid)
                    523:                return (EMSGSIZE);
                    524:        xlen = uio->uio_resid;
                    525:
1.64      christos  526:        if ((error = uiomove(bf, xlen, uio)) != 0)
1.5       cgd       527:                return (error);
                    528:
1.11      mycroft   529:        /* allow multiple writes without seeks */
                    530:        uio->uio_offset = 0;
                    531:
1.5       cgd       532:        /* cleanup string and remove trailing newline */
1.64      christos  533:        bf[xlen] = '\0';
                    534:        xlen = strlen(bf);
                    535:        if (xlen > 0 && bf[xlen-1] == '\n')
                    536:                bf[--xlen] = '\0';
1.5       cgd       537:        *buflenp = xlen;
1.1       pk        538:
1.5       cgd       539:        return (0);
1.1       pk        540: }
                    541:
1.36      jdolecek  542: const vfs_namemap_t *
1.94      dsl       543: vfs_findname(const vfs_namemap_t *nm, const char *bf, int buflen)
1.1       pk        544: {
1.11      mycroft   545:
1.5       cgd       546:        for (; nm->nm_name; nm++)
1.64      christos  547:                if (memcmp(bf, nm->nm_name, buflen+1) == 0)
1.5       cgd       548:                        return (nm);
                    549:
                    550:        return (0);
1.29      fvdl      551: }
                    552:
                    553: /*
                    554:  * Initialize pfsnode hash table.
                    555:  */
                    556: void
1.95      cegger    557: procfs_hashinit(void)
1.29      fvdl      558: {
1.76      ad        559:        mutex_init(&pfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
                    560:        mutex_init(&pfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE);
1.90      ad        561:        pfs_hashtbl = hashinit(desiredvnodes / 4, HASH_LIST, true, &pfs_ihash);
1.31      jdolecek  562: }
                    563:
1.38      chs       564: void
1.95      cegger    565: procfs_hashreinit(void)
1.38      chs       566: {
                    567:        struct pfsnode *pp;
                    568:        struct pfs_hashhead *oldhash, *hash;
1.41      thorpej   569:        u_long i, oldmask, mask, val;
1.38      chs       570:
1.90      ad        571:        hash = hashinit(desiredvnodes / 4, HASH_LIST, true, &mask);
1.38      chs       572:
1.76      ad        573:        mutex_enter(&pfs_ihash_lock);
1.38      chs       574:        oldhash = pfs_hashtbl;
                    575:        oldmask = pfs_ihash;
                    576:        pfs_hashtbl = hash;
                    577:        pfs_ihash = mask;
                    578:        for (i = 0; i <= oldmask; i++) {
                    579:                while ((pp = LIST_FIRST(&oldhash[i])) != NULL) {
                    580:                        LIST_REMOVE(pp, pfs_hash);
                    581:                        val = PFSPIDHASH(pp->pfs_pid);
                    582:                        LIST_INSERT_HEAD(&hash[val], pp, pfs_hash);
                    583:                }
                    584:        }
1.76      ad        585:        mutex_exit(&pfs_ihash_lock);
1.90      ad        586:        hashdone(oldhash, HASH_LIST, oldmask);
1.38      chs       587: }
                    588:
1.31      jdolecek  589: /*
                    590:  * Free pfsnode hash table.
                    591:  */
                    592: void
1.95      cegger    593: procfs_hashdone(void)
1.31      jdolecek  594: {
1.90      ad        595:        hashdone(pfs_hashtbl, HASH_LIST, pfs_ihash);
1.78      ad        596:        mutex_destroy(&pfs_hashlock);
                    597:        mutex_destroy(&pfs_ihash_lock);
1.29      fvdl      598: }
                    599:
                    600: struct vnode *
1.102.2.1! rmind     601: procfs_hashget(pid_t pid, pfstype type, int fd, struct mount *mp)
1.29      fvdl      602: {
1.38      chs       603:        struct pfs_hashhead *ppp;
1.29      fvdl      604:        struct pfsnode *pp;
                    605:        struct vnode *vp;
                    606:
                    607: loop:
1.76      ad        608:        mutex_enter(&pfs_ihash_lock);
1.38      chs       609:        ppp = &pfs_hashtbl[PFSPIDHASH(pid)];
                    610:        LIST_FOREACH(pp, ppp, pfs_hash) {
1.29      fvdl      611:                vp = PFSTOV(pp);
                    612:                if (pid == pp->pfs_pid && pp->pfs_type == type &&
1.42      christos  613:                    pp->pfs_fd == fd && vp->v_mount == mp) {
1.102.2.1! rmind     614:                        mutex_enter(vp->v_interlock);
        !           615:                        mutex_exit(&pfs_ihash_lock);
        !           616:                        if (vget(vp, 0))
        !           617:                                goto loop;
1.29      fvdl      618:                        return (vp);
                    619:                }
                    620:        }
1.76      ad        621:        mutex_exit(&pfs_ihash_lock);
1.29      fvdl      622:        return (NULL);
                    623: }
                    624:
                    625: /*
                    626:  * Insert the pfsnode into the hash table and lock it.
                    627:  */
                    628: void
1.94      dsl       629: procfs_hashins(struct pfsnode *pp)
1.29      fvdl      630: {
                    631:        struct pfs_hashhead *ppp;
                    632:
1.76      ad        633:        mutex_enter(&pfs_ihash_lock);
1.38      chs       634:        ppp = &pfs_hashtbl[PFSPIDHASH(pp->pfs_pid)];
1.29      fvdl      635:        LIST_INSERT_HEAD(ppp, pp, pfs_hash);
1.76      ad        636:        mutex_exit(&pfs_ihash_lock);
1.29      fvdl      637: }
                    638:
                    639: /*
                    640:  * Remove the pfsnode from the hash table.
                    641:  */
                    642: void
1.94      dsl       643: procfs_hashrem(struct pfsnode *pp)
1.29      fvdl      644: {
1.76      ad        645:        mutex_enter(&pfs_ihash_lock);
1.29      fvdl      646:        LIST_REMOVE(pp, pfs_hash);
1.76      ad        647:        mutex_exit(&pfs_ihash_lock);
1.29      fvdl      648: }
                    649:
                    650: void
1.94      dsl       651: procfs_revoke_vnodes(struct proc *p, void *arg)
1.29      fvdl      652: {
                    653:        struct pfsnode *pfs, *pnext;
                    654:        struct vnode *vp;
                    655:        struct mount *mp = (struct mount *)arg;
1.38      chs       656:        struct pfs_hashhead *ppp;
1.29      fvdl      657:
1.77      pavel     658:        if (!(p->p_flag & PK_SUGID))
1.29      fvdl      659:                return;
                    660:
1.82      ad        661:        mutex_enter(&pfs_ihash_lock);
1.38      chs       662:        ppp = &pfs_hashtbl[PFSPIDHASH(p->p_pid)];
                    663:        for (pfs = LIST_FIRST(ppp); pfs; pfs = pnext) {
1.29      fvdl      664:                vp = PFSTOV(pfs);
1.38      chs       665:                pnext = LIST_NEXT(pfs, pfs_hash);
1.102.2.1! rmind     666:                if (pfs->pfs_pid != p->p_pid || vp->v_mount != mp)
        !           667:                        continue;
1.99      rmind     668:                mutex_enter(vp->v_interlock);
1.102.2.1! rmind     669:                mutex_exit(&pfs_ihash_lock);
        !           670:                if (vget(vp, 0) != 0) {
1.82      ad        671:                        mutex_enter(&pfs_ihash_lock);
1.102.2.1! rmind     672:                        continue;
1.82      ad        673:                }
1.102.2.1! rmind     674:                VOP_REVOKE(vp, REVOKEALL);
        !           675:                vrele(vp);
        !           676:                mutex_enter(&pfs_ihash_lock);
1.29      fvdl      677:        }
1.82      ad        678:        mutex_exit(&pfs_ihash_lock);
1.42      christos  679: }
                    680:
                    681: int
1.75      ad        682: procfs_proc_lock(int pid, struct proc **bunghole, int notfound)
1.42      christos  683: {
1.75      ad        684:        struct proc *tp;
                    685:        int error = 0;
1.42      christos  686:
1.87      ad        687:        mutex_enter(proc_lock);
1.42      christos  688:
1.75      ad        689:        if (pid == 0)
                    690:                tp = &proc0;
1.96      rmind     691:        else if ((tp = proc_find(pid)) == NULL)
1.75      ad        692:                error = notfound;
1.82      ad        693:        if (tp != NULL && !rw_tryenter(&tp->p_reflock, RW_READER))
                    694:                error = EBUSY;
1.75      ad        695:
1.87      ad        696:        mutex_exit(proc_lock);
1.42      christos  697:
1.75      ad        698:        *bunghole = tp;
                    699:        return error;
                    700: }
1.49      jdolecek  701:
1.75      ad        702: void
                    703: procfs_proc_unlock(struct proc *p)
                    704: {
1.82      ad        705:
                    706:        rw_exit(&p->p_reflock);
1.1       pk        707: }
1.71      christos  708:
                    709: int
1.72      christos  710: procfs_doemul(struct lwp *curl, struct proc *p,
                    711:     struct pfsnode *pfs, struct uio *uio)
1.71      christos  712: {
                    713:        const char *ename = p->p_emul->e_name;
                    714:        return uiomove_frombuf(__UNCONST(ename), strlen(ename), uio);
                    715: }

CVSweb <webmaster@jp.NetBSD.org>