Add a few linux-style files, only enabled when -o linux is specified

for the mount. Currently these are /proc/cpuinfo and /proc/meminfo.
The former only does something on i386 right now.
This commit is contained in:
fvdl 2001-01-17 00:09:07 +00:00
parent c7f1462f3e
commit 4e000b75b2
8 changed files with 268 additions and 39 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs.h,v 1.30 2000/11/24 18:58:37 chs Exp $ */
/* $NetBSD: procfs.h,v 1.31 2001/01/17 00:09:07 fvdl Exp $ */
/*
* Copyright (c) 1993 Jan-Simon Pendry
@ -56,7 +56,9 @@ typedef enum {
Pnote, /* process notifier */
Pnotepg, /* process group notifier */
Pmap, /* memory map */
Pcmdline /* process command line args */
Pcmdline, /* process command line args */
Pmeminfo, /* system memory info (if -o linux) */
Pcpuinfo /* CPU info (if -o linux) */
} pfstype;
/*
@ -75,6 +77,15 @@ struct pfsnode {
#define PROCFS_NOTELEN 64 /* max length of a note (/proc/$pid/note) */
#define PROCFS_CTLLEN 8 /* max length of a ctl msg (/proc/$pid/ctl */
struct procfs_args {
int version;
int flags;
};
#define PROCFS_ARGSVERSION 1
#define PROCFSMNT_LINUXCOMPAT 0x01
/*
* Kernel stuff follows
*/
@ -93,6 +104,7 @@ struct pfsnode {
struct procfsmount {
void *pmnt_exechook;
struct mount *pmnt_mp;
int pmnt_flags;
};
#define VFSTOPROC(mp) ((struct procfsmount *)(mp)->mnt_data)
@ -132,6 +144,10 @@ int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *,
struct uio *));
int procfs_docmdline __P((struct proc *, struct proc *, struct pfsnode *,
struct uio *));
int procfs_domeminfo __P((struct proc *, struct proc *, struct pfsnode *,
struct uio *));
int procfs_docpuinfo __P((struct proc *, struct proc *, struct pfsnode *,
struct uio *));
int procfs_checkioperm __P((struct proc *, struct proc *));
void procfs_revoke_vnodes __P((struct proc *, void *));
@ -139,13 +155,15 @@ void procfs_hashinit __P((void));
void procfs_hashdone __P((void));
/* functions to check whether or not files should be displayed */
int procfs_validfile __P((struct proc *));
int procfs_validfpregs __P((struct proc *));
int procfs_validregs __P((struct proc *));
int procfs_validmap __P((struct proc *));
int procfs_validfile __P((struct proc *, struct mount *));
int procfs_validfpregs __P((struct proc *, struct mount *));
int procfs_validregs __P((struct proc *, struct mount *));
int procfs_validmap __P((struct proc *, struct mount *));
int procfs_rw __P((void *));
int procfs_getcpuinfstr __P((char *, int *));
#define PROCFS_LOCKED 0x01
#define PROCFS_WANT 0x02

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_fpregs.c,v 1.6 1997/08/27 08:52:52 thorpej Exp $ */
/* $NetBSD: procfs_fpregs.c,v 1.7 2001/01/17 00:09:07 fvdl Exp $ */
/*
* Copyright (c) 1993 Jan-Simon Pendry
@ -98,8 +98,9 @@ procfs_dofpregs(curp, p, pfs, uio)
}
int
procfs_validfpregs(p)
procfs_validfpregs(p, mp)
struct proc *p;
struct mount *mp;
{
#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)

View File

@ -0,0 +1,126 @@
/* $NetBSD: procfs_linux.c,v 1.1 2001/01/17 00:09:08 fvdl Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Frank van der Linden for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <miscfs/procfs/procfs.h>
#include <uvm/uvm_extern.h>
#define PGTOB(p) ((unsigned long)(p) << PAGE_SHIFT)
#define PGTOKB(p) ((unsigned long)(p) << (PAGE_SHIFT - 10))
/*
* Linux compatible /proc/meminfo. Only active when the -o linux
* mountflag is used.
*/
int
procfs_domeminfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
struct uio *uio)
{
char buf[512], *cp;
int len, error;
len = snprintf(buf, sizeof buf,
" total: used: free: shared: buffers: cached:\n"
"Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n"
"Swap: %8lu %8lu %8lu\n"
"MemTotal: %8lu kB\n"
"MemFree: %8lu kB\n"
"MemShared: %8lu kB\n"
"Buffers: %8lu kB\n"
"Cached: %8lu kB\n"
"SwapTotal: %8lu kB\n"
"SwapFree: %8lu kB\n",
PGTOB(uvmexp.npages),
PGTOB(uvmexp.npages - uvmexp.free),
PGTOB(uvmexp.free),
0L,
PGTOB(uvmexp.vnodepages),
PGTOB(uvmexp.anonpages + uvmexp.vnodepages + uvmexp.vtextpages),
PGTOB(uvmexp.swpages),
PGTOB(uvmexp.swpginuse),
PGTOB(uvmexp.swpages - uvmexp.swpginuse),
PGTOKB(uvmexp.npages),
PGTOKB(uvmexp.free),
0L,
PGTOKB(uvmexp.vnodepages),
PGTOKB(uvmexp.anonpages + uvmexp.vnodepages +uvmexp.vtextpages),
PGTOKB(uvmexp.swpages),
PGTOKB(uvmexp.swpages - uvmexp.swpginuse));
if (len == 0)
return 0;
len -= uio->uio_offset;
cp = buf + uio->uio_offset;
len = imin(len, uio->uio_resid);
if (len <= 0)
error = 0;
else
error = uiomove(cp, len, uio);
return error;
}
int
procfs_docpuinfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
struct uio *uio)
{
char buf[512], *cp;
int len, error;
len = sizeof buf;
if (procfs_getcpuinfstr(buf, &len) < 0)
return EIO;
if (len == 0)
return 0;
len -= uio->uio_offset;
cp = buf + uio->uio_offset;
len = imin(len, uio->uio_resid);
if (len <= 0)
error = 0;
else
error = uiomove(cp, len, uio);
return error;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_map.c,v 1.9 2000/11/24 18:58:37 chs Exp $ */
/* $NetBSD: procfs_map.c,v 1.10 2001/01/17 00:09:08 fvdl Exp $ */
/*
* Copyright (c) 1993 Jan-Simon Pendry
@ -120,8 +120,9 @@ procfs_domap(curp, p, pfs, uio)
}
int
procfs_validmap(p)
procfs_validmap(p, mp)
struct proc *p;
struct mount *mp;
{
return ((p->p_flag & P_SYSTEM) == 0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_regs.c,v 1.11 1997/08/27 08:52:54 thorpej Exp $ */
/* $NetBSD: procfs_regs.c,v 1.12 2001/01/17 00:09:08 fvdl Exp $ */
/*
* Copyright (c) 1993 Jan-Simon Pendry
@ -98,8 +98,9 @@ procfs_doregs(curp, p, pfs, uio)
}
int
procfs_validregs(p)
procfs_validregs(p, mp)
struct proc *p;
struct mount *mp;
{
#if defined(PT_SETREGS) || defined(PT_GETREGS)

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_subr.c,v 1.34 2000/11/27 08:39:46 chs Exp $ */
/* $NetBSD: procfs_subr.c,v 1.35 2001/01/17 00:09:08 fvdl Exp $ */
/*
* Copyright (c) 1994 Christopher G. Demetriou. All rights reserved.
@ -158,6 +158,8 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
case Pmap: /* /proc/N/map = -r--r--r-- */
case Pstatus: /* /proc/N/status = -r--r--r-- */
case Pcmdline: /* /proc/N/cmdline = -r--r--r-- */
case Pmeminfo: /* /proc/meminfo = -r--r--r-- */
case Pcpuinfo: /* /proc/cpuinfo = -r--r--r-- */
pfs->pfs_mode = S_IRUSR|S_IRGRP|S_IROTH;
vp->v_type = VREG;
break;
@ -244,6 +246,11 @@ procfs_rw(v)
case Pcmdline:
return (procfs_docmdline(curp, p, pfs, uio));
case Pmeminfo:
return (procfs_domeminfo(curp, p, pfs, uio));
case Pcpuinfo:
return (procfs_docpuinfo(curp, p, pfs, uio));
default:
return (EOPNOTSUPP);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_vfsops.c,v 1.35 2000/06/28 02:44:07 mrg Exp $ */
/* $NetBSD: procfs_vfsops.c,v 1.36 2001/01/17 00:09:08 fvdl Exp $ */
/*
* Copyright (c) 1993 Jan-Simon Pendry
@ -96,6 +96,8 @@ procfs_mount(mp, path, data, ndp, p)
{
size_t size;
struct procfsmount *pmnt;
struct procfs_args args;
int error;
if (UIO_MX & (UIO_MX-1)) {
log(LOG_ERR, "procfs: invalid directory entry size");
@ -105,6 +107,16 @@ procfs_mount(mp, path, data, ndp, p)
if (mp->mnt_flag & MNT_UPDATE)
return (EOPNOTSUPP);
if (data != NULL) {
error = copyin(data, &args, sizeof args);
if (error != 0)
return error;
if (args.version != PROCFS_ARGSVERSION)
return EINVAL;
} else
args.flags = 0;
mp->mnt_flag |= MNT_LOCAL;
pmnt = (struct procfsmount *) malloc(sizeof(struct procfsmount),
M_UFSMNT, M_WAITOK); /* XXX need new malloc type */
@ -119,6 +131,7 @@ procfs_mount(mp, path, data, ndp, p)
pmnt->pmnt_exechook = exechook_establish(procfs_revoke_vnodes, mp);
pmnt->pmnt_mp = mp;
pmnt->pmnt_flags = args.flags;
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: procfs_vnops.c,v 1.75 2000/11/24 18:58:37 chs Exp $ */
/* $NetBSD: procfs_vnops.c,v 1.76 2001/01/17 00:09:08 fvdl Exp $ */
/*
* Copyright (c) 1993 Jan-Simon Pendry
@ -43,10 +43,6 @@
* procfs vnode interface
*/
#if defined(_KERNEL) && !defined(_LKM)
#include "opt_compat_linux.h"
#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/time.h>
@ -56,6 +52,7 @@
#include <sys/vnode.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/dirent.h>
#include <sys/resourcevar.h>
#include <sys/ptrace.h>
@ -73,9 +70,7 @@
*
*/
#ifdef COMPAT_LINUX
static int procfs_validfile_linux __P((struct proc *));
#endif
static int procfs_validfile_linux __P((struct proc *, struct mount *));
/*
* This is a list of the valid names in the
@ -87,7 +82,7 @@ struct proc_target {
u_char pt_namlen;
char *pt_name;
pfstype pt_pfstype;
int (*pt_valid) __P((struct proc *p));
int (*pt_valid) __P((struct proc *, struct mount *));
} proc_targets[] = {
#define N(s) sizeof(s)-1, s
/* name type validp */
@ -103,13 +98,25 @@ struct proc_target {
{ DT_REG, N("notepg"), Pnotepg, NULL },
{ DT_REG, N("map"), Pmap, procfs_validmap },
{ DT_REG, N("cmdline"), Pcmdline, NULL },
#ifdef COMPAT_LINUX
{ DT_REG, N("exe"), Pfile, procfs_validfile_linux },
#endif
#undef N
};
static int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
/*
* List of files in the root directory. Note: the validate function will
* be called with p == NULL for these ones.
*/
struct proc_target proc_root_targets[] = {
#define N(s) sizeof(s)-1, s
/* name type validp */
{ DT_REG, N("meminfo"), Pmeminfo, procfs_validfile_linux },
{ DT_REG, N("cpuinfo"), Pcpuinfo, procfs_validfile_linux },
#undef N
};
static int nproc_root_targets =
sizeof(proc_root_targets) / sizeof(proc_root_targets[0]);
int procfs_lookup __P((void *));
#define procfs_create genfs_eopnotsupp_rele
#define procfs_mknod genfs_eopnotsupp_rele
@ -550,6 +557,11 @@ procfs_getattr(v)
vap->va_uid = procp->p_ucred->cr_uid;
vap->va_gid = procp->p_ucred->cr_gid;
break;
case Pmeminfo:
case Pcpuinfo:
vap->va_nlink = 1;
vap->va_uid = vap->va_gid = 0;
break;
default:
break;
@ -629,6 +641,8 @@ procfs_getattr(v)
case Pnotepg:
case Pmap:
case Pcmdline:
case Pmeminfo:
case Pcpuinfo:
vap->va_bytes = vap->va_size = 0;
break;
@ -718,11 +732,11 @@ procfs_lookup(v)
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
const char *pname = cnp->cn_nameptr;
struct proc_target *pt;
struct proc_target *pt = NULL;
struct vnode *fvp;
pid_t pid;
struct pfsnode *pfs;
struct proc *p;
struct proc *p = NULL;
int i, error, wantpunlock, iscurproc = 0, isself = 0;
*vpp = NULL;
@ -760,6 +774,25 @@ procfs_lookup(v)
return (error);
}
for (i = 0; i < nproc_root_targets; i++) {
pt = &proc_root_targets[i];
if (cnp->cn_namelen == pt->pt_namlen &&
memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
(pt->pt_valid == NULL ||
(*pt->pt_valid)(p, dvp->v_mount)))
break;
}
if (i != nproc_root_targets) {
error = procfs_allocvp(dvp->v_mount, vpp, 0,
pt->pt_pfstype);
if ((error == 0) && (wantpunlock)) {
VOP_UNLOCK(dvp, 0);
cnp->cn_flags |= PDIRUNLOCK;
}
return (error);
}
pid = atopid(pname, cnp->cn_namelen);
if (pid == NO_PID)
break;
@ -799,7 +832,8 @@ procfs_lookup(v)
for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
if (cnp->cn_namelen == pt->pt_namlen &&
memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
(pt->pt_valid == NULL || (*pt->pt_valid)(p)))
(pt->pt_valid == NULL ||
(*pt->pt_valid)(p, dvp->v_mount)))
goto found;
}
break;
@ -834,20 +868,24 @@ procfs_lookup(v)
}
int
procfs_validfile(p)
procfs_validfile(p, mp)
struct proc *p;
struct mount *mp;
{
return (p->p_textvp != NULL);
}
#ifdef COMPAT_LINUX
static int
procfs_validfile_linux(p)
procfs_validfile_linux(p, mp)
struct proc *p;
struct mount *mp;
{
return (!strcmp("linux", p->p_emul->e_name) && procfs_validfile(p));
int flags;
flags = VFSTOPROC(mp)->pmnt_flags;
return ((flags & PROCFSMNT_LINUXCOMPAT) &&
(p == NULL || procfs_validfile(p, mp)));
}
#endif
/*
* readdir returns directory entries from pfsnode (vp).
@ -879,9 +917,12 @@ procfs_readdir(v)
off_t i;
int error;
off_t *cookies = NULL;
int ncookies;
int ncookies, left, skip, j;
struct vnode *vp;
struct proc_target *pt;
pfs = VTOPFS(ap->a_vp);
vp = ap->a_vp;
pfs = VTOPFS(vp);
if (uio->uio_resid < UIO_MX)
return (EINVAL);
@ -902,7 +943,6 @@ procfs_readdir(v)
*/
case Pproc: {
struct proc *p;
struct proc_target *pt;
if (i >= nproc_targets)
return 0;
@ -920,7 +960,8 @@ procfs_readdir(v)
for (pt = &proc_targets[i];
uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
if (pt->pt_valid && (*pt->pt_valid)(p) == 0)
if (pt->pt_valid &&
(*pt->pt_valid)(p, vp->v_mount) == 0)
continue;
d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype);
@ -1027,10 +1068,31 @@ procfs_readdir(v)
goto again;
#endif
proclist_unlock_read();
skip = i - pcnt;
if (skip >= nproc_root_targets)
break;
left = nproc_root_targets - skip;
for (j = 0, pt = &proc_root_targets[0];
uio->uio_resid >= UIO_MX && j < left;
pt++, j++, i++) {
if (pt->pt_valid &&
(*pt->pt_valid)(NULL, vp->v_mount) == 0)
continue;
d.d_fileno = PROCFS_FILENO(0, pt->pt_pfstype);
d.d_namlen = pt->pt_namlen;
memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
d.d_type = pt->pt_type;
if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
break;
nc++;
if (cookies)
*cookies++ = i + 1;
}
ncookies = nc;
break;
}
default: