* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software donated to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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 by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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
* @(#)kernfs_vnops.c 8.6 (Berkeley) 2/10/94
* Kernel parameter filesystem (/kern)
#include <miscfs/kernfs/kernfs.h>
#define KSTRING 256 /* Largest I/O available via this filesystem */
#define READ_MODE (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)
/* NOTE: The name must be less than UIO_MX-16 chars in length */
/* name data tag ro/rw */
{ ".", 0, KTT_NULL
, VREAD
, VDIR
},
{ "..", 0, KTT_NULL
, VREAD
, VDIR
},
{ "boottime", &boottime
.tv_sec
, KTT_INT
, VREAD
, VREG
},
{ "copyright", copyright
, KTT_STRING
, VREAD
, VREG
},
{ "hostname", 0, KTT_HOSTNAME
, VREAD
|VWRITE
, VREG
},
{ "hz", &hz
, KTT_INT
, VREAD
, VREG
},
{ "loadavg", 0, KTT_AVENRUN
, VREAD
, VREG
},
{ "pagesize", &cnt
.v_page_size
, KTT_INT
, VREAD
, VREG
},
{ "physmem", &physmem
, KTT_INT
, VREAD
, VREG
},
{ "root", 0, KTT_NULL
, VREAD
, VDIR
},
{ "rootdev", 0, KTT_NULL
, VREAD
, VBLK
},
{ "rrootdev", 0, KTT_NULL
, VREAD
, VCHR
},
{ "time", 0, KTT_TIME
, VREAD
, VREG
},
{ "version", version
, KTT_STRING
, VREAD
, VREG
},
static int nkern_targets
= sizeof(kern_targets
) / sizeof(kern_targets
[0]);
kernfs_xread(kt
, buf
, len
, lenp
)
sprintf(buf
, "%d %d\n", tv
.tv_sec
, tv
.tv_usec
);
sprintf(buf
, "%d\n", *ip
);
int xlen
= strlen(cp
) + 1;
sprintf(buf
, "%ld %ld %ld %ld\n",
kernfs_xwrite(kt
, buf
, len
)
bcopy(buf
, hostname
, len
);
* vp is the current namei directory
* ndp is the name to locate in that directory...
struct vop_lookup_args
/* {
struct componentname * a_cnp;
struct vnode
**vpp
= ap
->a_vpp
;
struct vnode
*dvp
= ap
->a_dvp
;
struct componentname
*cnp
= ap
->a_cnp
;
printf("kernfs_lookup(%x)\n", ap
);
printf("kernfs_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp
, vpp
, ap
->a_cnp
);
printf("kernfs_lookup(%s)\n", pname
);
if (cnp
->cn_namelen
== 1 && *pname
== '.') {
if (cnp
->cn_namelen
== 4 && bcmp(pname
, "root", 4) == 0) {
* /kern/rootdev is the root device
if (cnp
->cn_namelen
== 7 && bcmp(pname
, "rootdev", 7) == 0) {
* /kern/rrootdev is the raw root device
if (cnp
->cn_namelen
== 8 && bcmp(pname
, "rrootdev", 8) == 0) {
for (i
= 0; i
< nkern_targets
; i
++) {
struct kern_target
*kt
= &kern_targets
[i
];
if (cnp
->cn_namelen
== strlen(kt
->kt_name
) &&
bcmp(kt
->kt_name
, pname
, cnp
->cn_namelen
) == 0) {
printf("kernfs_lookup: i = %d, error = %d\n", i
, error
);
printf("kernfs_lookup: allocate new vnode\n");
error
= getnewvnode(VT_KERNFS
, dvp
->v_mount
, kernfs_vnodeop_p
, &fvp
);
MALLOC(fvp
->v_data
, void *, sizeof(struct kernfs_node
), M_TEMP
, M_WAITOK
);
VTOKERN(fvp
)->kf_kt
= &kern_targets
[i
];
fvp
->v_type
= VTOKERN(fvp
)->kf_kt
->kt_vtype
;
printf("kernfs_lookup: newvp = %x\n", fvp
);
printf("kernfs_lookup: error = %d\n", error
);
struct vop_open_args
/* {
struct vnode
*vp
= ap
->a_vp
;
* Can always open the root (modulo perms)
printf("kernfs_open, mode = %x, file = %s\n",
ap
->a_mode
, VTOKERN(vp
)->kf_kt
->kt_name
);
if ((ap
->a_mode
& FWRITE
) && !(VTOKERN(vp
)->kf_kt
->kt_rw
& VWRITE
))
struct vop_access_args
/* {
struct vnode
*vp
= ap
->a_vp
;
struct ucred
*cred
= ap
->a_cred
;
mode_t mode
= ap
->a_mode
;
if ((vp
->v_flag
& VROOT
) == 0) {
struct kern_target
*kt
= VTOKERN(vp
)->kf_kt
;
if ((mode
& VWRITE
) && !(kt
->kt_rw
& VWRITE
))
struct vop_getattr_args
/* {
struct vnode
*vp
= ap
->a_vp
;
struct vattr
*vap
= ap
->a_vap
;
bzero((caddr_t
) vap
, sizeof(*vap
));
vap
->va_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
.val
[0];
vap
->va_blocksize
= DEV_BSIZE
;
microtime(&vap
->va_atime
);
vap
->va_mtime
= vap
->va_atime
;
vap
->va_ctime
= vap
->va_ctime
;
/* vap->va_qbytes = 0; */
if (vp
->v_flag
& VROOT
) {
printf("kernfs_getattr: stat rootdir\n");
vap
->va_size
= DEV_BSIZE
;
struct kern_target
*kt
= VTOKERN(vp
)->kf_kt
;
printf("kernfs_getattr: stat target %s\n", kt
->kt_name
);
vap
->va_type
= kt
->kt_vtype
;
vap
->va_mode
= (kt
->kt_rw
& VWRITE
? WRITE_MODE
: READ_MODE
);
vap
->va_fileid
= 3 + (kt
- kern_targets
) / sizeof(*kt
);
error
= kernfs_xread(kt
, strbuf
, sizeof(strbuf
), &nbytes
);
vp
->v_type
= vap
->va_type
;
printf("kernfs_getattr: return error %d\n", error
);
struct vop_setattr_args
/* {
* Silently ignore attribute changes.
* This allows for open with truncate to have no
* effect until some data is written. I want to
* do it this way because all writes are atomic.
struct vop_read_args
/* {
struct vnode
*vp
= ap
->a_vp
;
struct uio
*uio
= ap
->a_uio
;
int off
= uio
->uio_offset
;
printf("kern_read %s\n", kt
->kt_name
);
error
= kernfs_xread(kt
, strbuf
, sizeof(strbuf
), &len
);
return (uiomove(cp
, len
, uio
));
struct vop_write_args
/* {
struct vnode
*vp
= ap
->a_vp
;
struct uio
*uio
= ap
->a_uio
;
if (uio
->uio_offset
!= 0)
xlen
= min(uio
->uio_resid
, KSTRING
-1);
error
= uiomove(strbuf
, xlen
, uio
);
return (kernfs_xwrite(kt
, strbuf
, xlen
));
struct vop_readdir_args
/* {
struct uio
*uio
= ap
->a_uio
;
i
= uio
->uio_offset
/ UIO_MX
;
while (uio
->uio_resid
> 0 && i
< nkern_targets
) {
struct kern_target
*kt
= &kern_targets
[i
];
printf("kernfs_readdir: i = %d\n", i
);
bzero((caddr_t
) dp
, UIO_MX
);
dp
->d_namlen
= strlen(kt
->kt_name
);
bcopy(kt
->kt_name
, dp
->d_name
, dp
->d_namlen
+1);
printf("kernfs_readdir: name = %s, len = %d\n",
dp
->d_name
, dp
->d_namlen
);
* Fill in the remaining fields
dp
->d_type
= DT_UNKNOWN
; /* XXX */
error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
uio
->uio_offset
= i
* UIO_MX
;
struct vop_inactive_args
/* {
struct vnode
*vp
= ap
->a_vp
;
* Clear out the v_type field to avoid
* nasty things happening in vgone().
printf("kernfs_inactive(%x)\n", vp
);
struct vop_reclaim_args
/* {
struct vnode
*vp
= ap
->a_vp
;
printf("kernfs_reclaim(%x)\n", vp
);
FREE(vp
->v_data
, M_TEMP
);
* Return POSIX pathconf information applicable to special devices.
struct vop_pathconf_args
/* {
*ap
->a_retval
= LINK_MAX
;
*ap
->a_retval
= MAX_CANON
;
*ap
->a_retval
= MAX_INPUT
;
*ap
->a_retval
= PIPE_BUF
;
case _PC_CHOWN_RESTRICTED
:
*ap
->a_retval
= _POSIX_VDISABLE
;
* Print out the contents of a /dev/fd vnode.
struct vop_print_args
/* {
printf("tag VT_KERNFS, kernfs vnode\n");
struct vop_vfree_args
/* {
* /dev/fd vnode unsupported operation
* /dev/fd "should never get here" operation
* kernfs vnode null operation
#define kernfs_create ((int (*) __P((struct vop_create_args *)))kernfs_enotsupp)
#define kernfs_mknod ((int (*) __P((struct vop_mknod_args *)))kernfs_enotsupp)
#define kernfs_close ((int (*) __P((struct vop_close_args *)))nullop)
#define kernfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))kernfs_enotsupp)
#define kernfs_select ((int (*) __P((struct vop_select_args *)))kernfs_enotsupp)
#define kernfs_mmap ((int (*) __P((struct vop_mmap_args *)))kernfs_enotsupp)
#define kernfs_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define kernfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
#define kernfs_remove ((int (*) __P((struct vop_remove_args *)))kernfs_enotsupp)
#define kernfs_link ((int (*) __P((struct vop_link_args *)))kernfs_enotsupp)
#define kernfs_rename ((int (*) __P((struct vop_rename_args *)))kernfs_enotsupp)
#define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))kernfs_enotsupp)
#define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))kernfs_enotsupp)
#define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp)
#define kernfs_readlink \
((int (*) __P((struct vop_readlink_args *)))kernfs_enotsupp)
#define kernfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
#define kernfs_lock ((int (*) __P((struct vop_lock_args *)))nullop)
#define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
#define kernfs_bmap ((int (*) __P((struct vop_bmap_args *)))kernfs_badop)
#define kernfs_strategy ((int (*) __P((struct vop_strategy_args *)))kernfs_badop)
#define kernfs_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
#define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))kernfs_enotsupp)
#define kernfs_blkatoff \
((int (*) __P((struct vop_blkatoff_args *)))kernfs_enotsupp)
#define kernfs_valloc ((int(*) __P(( \
struct vnode **vpp))) kernfs_enotsupp)
#define kernfs_truncate \
((int (*) __P((struct vop_truncate_args *)))kernfs_enotsupp)
#define kernfs_update ((int (*) __P((struct vop_update_args *)))kernfs_enotsupp)
#define kernfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))kernfs_enotsupp)
int (**kernfs_vnodeop_p
)();
struct vnodeopv_entry_desc kernfs_vnodeop_entries
[] = {
{ &vop_default_desc
, vn_default_error
},
{ &vop_lookup_desc
, kernfs_lookup
}, /* lookup */
{ &vop_create_desc
, kernfs_create
}, /* create */
{ &vop_mknod_desc
, kernfs_mknod
}, /* mknod */
{ &vop_open_desc
, kernfs_open
}, /* open */
{ &vop_close_desc
, kernfs_close
}, /* close */
{ &vop_access_desc
, kernfs_access
}, /* access */
{ &vop_getattr_desc
, kernfs_getattr
}, /* getattr */
{ &vop_setattr_desc
, kernfs_setattr
}, /* setattr */
{ &vop_read_desc
, kernfs_read
}, /* read */
{ &vop_write_desc
, kernfs_write
}, /* write */
{ &vop_ioctl_desc
, kernfs_ioctl
}, /* ioctl */
{ &vop_select_desc
, kernfs_select
}, /* select */
{ &vop_mmap_desc
, kernfs_mmap
}, /* mmap */
{ &vop_fsync_desc
, kernfs_fsync
}, /* fsync */
{ &vop_seek_desc
, kernfs_seek
}, /* seek */
{ &vop_remove_desc
, kernfs_remove
}, /* remove */
{ &vop_link_desc
, kernfs_link
}, /* link */
{ &vop_rename_desc
, kernfs_rename
}, /* rename */
{ &vop_mkdir_desc
, kernfs_mkdir
}, /* mkdir */
{ &vop_rmdir_desc
, kernfs_rmdir
}, /* rmdir */
{ &vop_symlink_desc
, kernfs_symlink
}, /* symlink */
{ &vop_readdir_desc
, kernfs_readdir
}, /* readdir */
{ &vop_readlink_desc
, kernfs_readlink
},/* readlink */
{ &vop_abortop_desc
, kernfs_abortop
}, /* abortop */
{ &vop_inactive_desc
, kernfs_inactive
},/* inactive */
{ &vop_reclaim_desc
, kernfs_reclaim
}, /* reclaim */
{ &vop_lock_desc
, kernfs_lock
}, /* lock */
{ &vop_unlock_desc
, kernfs_unlock
}, /* unlock */
{ &vop_bmap_desc
, kernfs_bmap
}, /* bmap */
{ &vop_strategy_desc
, kernfs_strategy
},/* strategy */
{ &vop_print_desc
, kernfs_print
}, /* print */
{ &vop_islocked_desc
, kernfs_islocked
},/* islocked */
{ &vop_pathconf_desc
, kernfs_pathconf
},/* pathconf */
{ &vop_advlock_desc
, kernfs_advlock
}, /* advlock */
{ &vop_blkatoff_desc
, kernfs_blkatoff
},/* blkatoff */
{ &vop_valloc_desc
, kernfs_valloc
}, /* valloc */
{ &vop_vfree_desc
, kernfs_vfree
}, /* vfree */
{ &vop_truncate_desc
, kernfs_truncate
},/* truncate */
{ &vop_update_desc
, kernfs_update
}, /* update */
{ &vop_bwrite_desc
, kernfs_bwrite
}, /* bwrite */
{ (struct vnodeop_desc
*)NULL
, (int(*)())NULL
}
struct vnodeopv_desc kernfs_vnodeop_opv_desc
=
{ &kernfs_vnodeop_p
, kernfs_vnodeop_entries
};