version 1.72, 2001/01/27 11:42:41 |
version 1.87, 2003/06/29 18:43:33 |
|
|
* Kernel parameter filesystem (/kern) |
* Kernel parameter filesystem (/kern) |
*/ |
*/ |
|
|
|
#include <sys/cdefs.h> |
|
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
#include <sys/kernel.h> |
#include <sys/kernel.h> |
#include <sys/vmmeter.h> |
#include <sys/vmmeter.h> |
#include <sys/types.h> |
|
#include <sys/time.h> |
#include <sys/time.h> |
#include <sys/proc.h> |
#include <sys/proc.h> |
#include <sys/vnode.h> |
#include <sys/vnode.h> |
|
|
#define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) |
#define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) |
#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) |
#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) |
|
|
struct kern_target kern_targets[] = { |
const struct kern_target kern_targets[] = { |
/* NOTE: The name must be less than UIO_MX-16 chars in length */ |
/* NOTE: The name must be less than UIO_MX-16 chars in length */ |
#define N(s) sizeof(s)-1, s |
#define N(s) sizeof(s)-1, s |
/* name data tag type ro/rw */ |
/* name data tag type ro/rw */ |
Line 86 struct kern_target kern_targets[] = { |
|
Line 88 struct kern_target kern_targets[] = { |
|
{ DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE }, |
{ DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE }, |
{ DT_REG, N("msgbuf"), 0, KTT_MSGBUF, VREG, READ_MODE }, |
{ DT_REG, N("msgbuf"), 0, KTT_MSGBUF, VREG, READ_MODE }, |
{ DT_REG, N("pagesize"), &uvmexp.pagesize, KTT_INT, VREG, READ_MODE }, |
{ DT_REG, N("pagesize"), &uvmexp.pagesize, KTT_INT, VREG, READ_MODE }, |
{ DT_REG, N("physmem"), 0, KTT_PHYSMEM, VREG, READ_MODE }, |
{ DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE }, |
#if 0 |
#if 0 |
{ DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE }, |
{ DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE }, |
#endif |
#endif |
Line 101 struct kern_target kern_targets[] = { |
|
Line 103 struct kern_target kern_targets[] = { |
|
static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); |
static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); |
|
|
int kernfs_lookup __P((void *)); |
int kernfs_lookup __P((void *)); |
#define kernfs_create genfs_eopnotsupp_rele |
#define kernfs_create genfs_eopnotsupp |
#define kernfs_mknod genfs_eopnotsupp_rele |
#define kernfs_mknod genfs_eopnotsupp |
#define kernfs_open genfs_nullop |
#define kernfs_open genfs_nullop |
#define kernfs_close genfs_nullop |
#define kernfs_close genfs_nullop |
int kernfs_access __P((void *)); |
int kernfs_access __P((void *)); |
Line 114 int kernfs_write __P((void *)); |
|
Line 116 int kernfs_write __P((void *)); |
|
#define kernfs_ioctl genfs_enoioctl |
#define kernfs_ioctl genfs_enoioctl |
#define kernfs_poll genfs_poll |
#define kernfs_poll genfs_poll |
#define kernfs_revoke genfs_revoke |
#define kernfs_revoke genfs_revoke |
#define kernfs_mmap genfs_eopnotsupp |
|
#define kernfs_fsync genfs_nullop |
#define kernfs_fsync genfs_nullop |
#define kernfs_seek genfs_nullop |
#define kernfs_seek genfs_nullop |
#define kernfs_remove genfs_eopnotsupp_rele |
#define kernfs_remove genfs_eopnotsupp |
int kernfs_link __P((void *)); |
int kernfs_link __P((void *)); |
#define kernfs_rename genfs_eopnotsupp_rele |
#define kernfs_rename genfs_eopnotsupp |
#define kernfs_mkdir genfs_eopnotsupp_rele |
#define kernfs_mkdir genfs_eopnotsupp |
#define kernfs_rmdir genfs_eopnotsupp_rele |
#define kernfs_rmdir genfs_eopnotsupp |
int kernfs_symlink __P((void *)); |
int kernfs_symlink __P((void *)); |
int kernfs_readdir __P((void *)); |
int kernfs_readdir __P((void *)); |
#define kernfs_readlink genfs_eopnotsupp |
#define kernfs_readlink genfs_eopnotsupp |
Line 142 int kernfs_pathconf __P((void *)); |
|
Line 143 int kernfs_pathconf __P((void *)); |
|
#define kernfs_truncate genfs_eopnotsupp |
#define kernfs_truncate genfs_eopnotsupp |
#define kernfs_update genfs_nullop |
#define kernfs_update genfs_nullop |
#define kernfs_bwrite genfs_eopnotsupp |
#define kernfs_bwrite genfs_eopnotsupp |
|
#define kernfs_putpages genfs_putpages |
|
|
int kernfs_xread __P((struct kern_target *, int, char **, int)); |
static int kernfs_xread __P((const struct kern_target *, int, char **, size_t, size_t *)); |
int kernfs_xwrite __P((struct kern_target *, char *, int)); |
static int kernfs_xwrite __P((const struct kern_target *, char *, size_t)); |
|
|
int (**kernfs_vnodeop_p) __P((void *)); |
int (**kernfs_vnodeop_p) __P((void *)); |
const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { |
const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { |
Line 163 const struct vnodeopv_entry_desc kernfs_ |
|
Line 165 const struct vnodeopv_entry_desc kernfs_ |
|
{ &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ |
{ &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ |
{ &vop_poll_desc, kernfs_poll }, /* poll */ |
{ &vop_poll_desc, kernfs_poll }, /* poll */ |
{ &vop_revoke_desc, kernfs_revoke }, /* revoke */ |
{ &vop_revoke_desc, kernfs_revoke }, /* revoke */ |
{ &vop_mmap_desc, kernfs_mmap }, /* mmap */ |
|
{ &vop_fsync_desc, kernfs_fsync }, /* fsync */ |
{ &vop_fsync_desc, kernfs_fsync }, /* fsync */ |
{ &vop_seek_desc, kernfs_seek }, /* seek */ |
{ &vop_seek_desc, kernfs_seek }, /* seek */ |
{ &vop_remove_desc, kernfs_remove }, /* remove */ |
{ &vop_remove_desc, kernfs_remove }, /* remove */ |
Line 191 const struct vnodeopv_entry_desc kernfs_ |
|
Line 192 const struct vnodeopv_entry_desc kernfs_ |
|
{ &vop_truncate_desc, kernfs_truncate }, /* truncate */ |
{ &vop_truncate_desc, kernfs_truncate }, /* truncate */ |
{ &vop_update_desc, kernfs_update }, /* update */ |
{ &vop_update_desc, kernfs_update }, /* update */ |
{ &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ |
{ &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ |
{ (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } |
{ &vop_putpages_desc, kernfs_putpages }, /* putpages */ |
|
{ NULL, NULL } |
}; |
}; |
const struct vnodeopv_desc kernfs_vnodeop_opv_desc = |
const struct vnodeopv_desc kernfs_vnodeop_opv_desc = |
{ &kernfs_vnodeop_p, kernfs_vnodeop_entries }; |
{ &kernfs_vnodeop_p, kernfs_vnodeop_entries }; |
|
|
int |
static int |
kernfs_xread(kt, off, bufp, len) |
kernfs_xread(kt, off, bufp, len, wrlen) |
struct kern_target *kt; |
const struct kern_target *kt; |
int off; |
int off; |
char **bufp; |
char **bufp; |
int len; |
size_t len; |
|
size_t *wrlen; |
{ |
{ |
|
|
switch (kt->kt_tag) { |
switch (kt->kt_tag) { |
Line 248 kernfs_xread(kt, off, bufp, len) |
|
Line 251 kernfs_xread(kt, off, bufp, len) |
|
* message buffer header are corrupted, but that'll cause |
* message buffer header are corrupted, but that'll cause |
* the system to die anyway. |
* the system to die anyway. |
*/ |
*/ |
if (off >= msgbufp->msg_bufs) |
if (off >= msgbufp->msg_bufs) { |
|
*wrlen = 0; |
return (0); |
return (0); |
|
} |
n = msgbufp->msg_bufx + off; |
n = msgbufp->msg_bufx + off; |
if (n >= msgbufp->msg_bufs) |
if (n >= msgbufp->msg_bufs) |
n -= msgbufp->msg_bufs; |
n -= msgbufp->msg_bufs; |
len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off); |
len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off); |
*bufp = msgbufp->msg_bufc + n; |
*bufp = msgbufp->msg_bufc + n; |
return (len); |
*wrlen = len; |
|
return (0); |
} |
} |
|
|
case KTT_HOSTNAME: { |
case KTT_HOSTNAME: { |
Line 278 kernfs_xread(kt, off, bufp, len) |
|
Line 284 kernfs_xread(kt, off, bufp, len) |
|
averunnable.ldavg[2], averunnable.fscale); |
averunnable.ldavg[2], averunnable.fscale); |
break; |
break; |
|
|
case KTT_PHYSMEM: |
|
sprintf(*bufp, "%llu", (u_int64_t) ctob(physmem)); |
|
break; |
|
|
|
default: |
default: |
|
*wrlen = 0; |
return (0); |
return (0); |
} |
} |
|
|
len = strlen(*bufp); |
len = strlen(*bufp); |
if (len <= off) |
if (len <= off) |
return (0); |
*wrlen = 0; |
*bufp += off; |
else { |
return (len - off); |
*bufp += off; |
|
*wrlen = len - off; |
|
} |
|
return (0); |
} |
} |
|
|
int |
static int |
kernfs_xwrite(kt, buf, len) |
kernfs_xwrite(kt, buf, len) |
struct kern_target *kt; |
const struct kern_target *kt; |
char *buf; |
char *buf; |
int len; |
size_t len; |
{ |
{ |
|
|
switch (kt->kt_tag) { |
switch (kt->kt_tag) { |
Line 306 kernfs_xwrite(kt, buf, len) |
|
Line 312 kernfs_xwrite(kt, buf, len) |
|
--len; |
--len; |
memcpy(hostname, buf, len); |
memcpy(hostname, buf, len); |
hostname[len] = '\0'; |
hostname[len] = '\0'; |
hostnamelen = len; |
hostnamelen = (size_t) len; |
return (0); |
return (0); |
|
|
default: |
default: |
Line 332 kernfs_lookup(v) |
|
Line 338 kernfs_lookup(v) |
|
struct vnode **vpp = ap->a_vpp; |
struct vnode **vpp = ap->a_vpp; |
struct vnode *dvp = ap->a_dvp; |
struct vnode *dvp = ap->a_dvp; |
const char *pname = cnp->cn_nameptr; |
const char *pname = cnp->cn_nameptr; |
struct kern_target *kt; |
const struct kern_target *kt; |
struct vnode *fvp; |
struct vnode *fvp; |
int error, i, wantpunlock; |
int error, i, wantpunlock; |
|
|
Line 440 kernfs_access(v) |
|
Line 446 kernfs_access(v) |
|
if (vp->v_flag & VROOT) { |
if (vp->v_flag & VROOT) { |
mode = DIR_MODE; |
mode = DIR_MODE; |
} else { |
} else { |
struct kern_target *kt = VTOKERN(vp)->kf_kt; |
const struct kern_target *kt = VTOKERN(vp)->kf_kt; |
mode = kt->kt_mode; |
mode = kt->kt_mode; |
} |
} |
|
|
Line 460 kernfs_getattr(v) |
|
Line 466 kernfs_getattr(v) |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct vattr *vap = ap->a_vap; |
struct vattr *vap = ap->a_vap; |
struct timeval tv; |
|
int error = 0; |
int error = 0; |
char strbuf[KSTRING], *buf; |
char strbuf[KSTRING], *buf; |
|
|
Line 471 kernfs_getattr(v) |
|
Line 476 kernfs_getattr(v) |
|
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; |
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; |
vap->va_size = 0; |
vap->va_size = 0; |
vap->va_blocksize = DEV_BSIZE; |
vap->va_blocksize = DEV_BSIZE; |
microtime(&tv); |
/* |
TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime); |
* Make all times be current TOD. Avoid microtime(9), it's slow. |
vap->va_mtime = vap->va_atime; |
* We don't guard the read from time(9) with splclock(9) since we |
vap->va_ctime = vap->va_ctime; |
* don't actually need to be THAT sure the access is atomic. |
|
*/ |
|
TIMEVAL_TO_TIMESPEC(&time, &vap->va_ctime); |
|
vap->va_atime = vap->va_mtime = vap->va_ctime; |
vap->va_gen = 0; |
vap->va_gen = 0; |
vap->va_flags = 0; |
vap->va_flags = 0; |
vap->va_rdev = 0; |
vap->va_rdev = 0; |
Line 490 kernfs_getattr(v) |
|
Line 498 kernfs_getattr(v) |
|
vap->va_fileid = 2; |
vap->va_fileid = 2; |
vap->va_size = DEV_BSIZE; |
vap->va_size = DEV_BSIZE; |
} else { |
} else { |
struct kern_target *kt = VTOKERN(vp)->kf_kt; |
const struct kern_target *kt = VTOKERN(vp)->kf_kt; |
int nbytes, total; |
size_t nread, total; |
#ifdef KERNFS_DIAGNOSTIC |
#ifdef KERNFS_DIAGNOSTIC |
printf("kernfs_getattr: stat target %s\n", kt->kt_name); |
printf("kernfs_getattr: stat target %s\n", kt->kt_name); |
#endif |
#endif |
Line 500 kernfs_getattr(v) |
|
Line 508 kernfs_getattr(v) |
|
vap->va_nlink = 1; |
vap->va_nlink = 1; |
vap->va_fileid = 1 + (kt - kern_targets); |
vap->va_fileid = 1 + (kt - kern_targets); |
total = 0; |
total = 0; |
while (buf = strbuf, |
do { |
nbytes = kernfs_xread(kt, total, &buf, sizeof(strbuf))) |
buf = strbuf; |
total += nbytes; |
error = kernfs_xread(kt, total, &buf, |
|
sizeof(strbuf), &nread); |
|
total += nread; |
|
} while (error == 0 && nread != 0); |
vap->va_size = total; |
vap->va_size = total; |
} |
} |
|
|
|
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct uio *uio = ap->a_uio; |
struct uio *uio = ap->a_uio; |
struct kern_target *kt; |
const struct kern_target *kt; |
char strbuf[KSTRING], *buf; |
char strbuf[KSTRING], *buf; |
int off, len; |
off_t off; |
|
size_t len; |
int error; |
int error; |
|
|
if (vp->v_type == VDIR) |
if (vp->v_type == VDIR) |
|
|
#endif |
#endif |
|
|
off = uio->uio_offset; |
off = uio->uio_offset; |
#if 0 |
buf = strbuf; |
while (buf = strbuf, |
if ((error = kernfs_xread(kt, off, &buf, sizeof(strbuf), &len)) == 0) |
#else |
error = uiomove(buf, len, uio); |
if (buf = strbuf, |
return (error); |
#endif |
|
len = kernfs_xread(kt, off, &buf, sizeof(strbuf))) { |
|
if ((error = uiomove(buf, len, uio)) != 0) |
|
return (error); |
|
off += len; |
|
} |
|
return (0); |
|
} |
} |
|
|
int |
int |
|
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct uio *uio = ap->a_uio; |
struct uio *uio = ap->a_uio; |
struct kern_target *kt; |
const struct kern_target *kt; |
int error, xlen; |
int error, xlen; |
char strbuf[KSTRING]; |
char strbuf[KSTRING]; |
|
|
Line 616 kernfs_readdir(v) |
|
Line 621 kernfs_readdir(v) |
|
} */ *ap = v; |
} */ *ap = v; |
struct uio *uio = ap->a_uio; |
struct uio *uio = ap->a_uio; |
struct dirent d; |
struct dirent d; |
struct kern_target *kt; |
const struct kern_target *kt; |
off_t i; |
off_t i; |
int error; |
int error; |
off_t *cookies = NULL; |
off_t *cookies = NULL; |
Line 649 kernfs_readdir(v) |
|
Line 654 kernfs_readdir(v) |
|
for (kt = &kern_targets[i]; |
for (kt = &kern_targets[i]; |
uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) { |
uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) { |
#ifdef KERNFS_DIAGNOSTIC |
#ifdef KERNFS_DIAGNOSTIC |
printf("kernfs_readdir: i = %d\n", i); |
printf("kernfs_readdir: i = %d\n", (int)i); |
#endif |
#endif |
|
|
if (kt->kt_tag == KTT_DEVICE) { |
if (kt->kt_tag == KTT_DEVICE) { |