* Copyright (c) 1993 Jan-Simon Pendry
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* %sccs.include.redist.c%
* @(#)procfs_subr.c 8.4 (Berkeley) %G%
* $Id: procfs_subr.c,v 3.2 1993/12/15 09:40:17 jsp Exp $
#include <miscfs/procfs/procfs.h>
static struct pfsnode
*pfshead
;
* allocate a pfsnode/vnode pair. the vnode is
* referenced, but not locked.
* the pid, pfs_type, and mount point uniquely
* identify a pfsnode. the mount point is needed
* because someone might mount this filesystem
* all pfsnodes are maintained on a singly-linked
* list. new nodes are only allocated when they cannot
* be found on this list. entries on the list are
* removed when the vfs reclaim entry is called.
* a single lock is kept for the entire list. this is
* needed because the getnewvnode() function can block
* waiting for a vnode to become free, in which case there
* may be more than one process trying to get the same
* vnode. this lock is only taken if we are going to
* call getnewvnode, since the kernel itself is single-threaded.
* if an entry is found on the list, then call vget() to
* take a reference. this is done because there may be
* zero references to it and so it needs to removed from
procfs_allocvp(mp
, vpp
, pid
, pfs_type
)
for (pfs
= pfshead
; pfs
!= 0; pfs
= pfs
->pfs_next
) {
if (pfs
->pfs_pid
== pid
&&
pfs
->pfs_type
== pfs_type
&&
PFSTOV(pfs
)->v_mount
== mp
) {
if (vget(pfs
->pfs_vnode
, 0))
* otherwise lock the vp list while we call getnewvnode
if (pfsvplock
& PROCFS_LOCKED
) {
pfsvplock
|= PROCFS_WANT
;
sleep((caddr_t
) &pfsvplock
, PINOD
);
pfsvplock
|= PROCFS_LOCKED
;
error
= getnewvnode(VT_PROCFS
, mp
, procfs_vnodeop_p
, vpp
);
MALLOC((*vpp
)->v_data
, void *, sizeof(struct pfsnode
),
pfs
->pfs_pid
= (pid_t
) pid
;
pfs
->pfs_type
= pfs_type
;
pfs
->pfs_fileno
= PROCFS_FILENO(pid
, pfs_type
);
case Proot
: /* /proc = dr-xr-xr-x */
pfs
->pfs_mode
= (VREAD
|VEXEC
) |
pfs
->pfs_mode
= (VREAD
|VEXEC
) |
pfs
->pfs_mode
= (VREAD
|VWRITE
);
pfs
->pfs_mode
= (VREAD
|VWRITE
);
pfs
->pfs_mode
= (VREAD
|VWRITE
);
pfs
->pfs_mode
= (VREAD
|VWRITE
);
pfs
->pfs_mode
= (VWRITE
);
pfs
->pfs_mode
= (VREAD
) |
pfs
->pfs_mode
= (VWRITE
);
pfs
->pfs_mode
= (VWRITE
);
/* add to procfs vnode list */
for (pp
= &pfshead
; *pp
; pp
= &(*pp
)->pfs_next
)
pfsvplock
&= ~PROCFS_LOCKED
;
if (pfsvplock
& PROCFS_WANT
) {
pfsvplock
&= ~PROCFS_WANT
;
wakeup((caddr_t
) &pfsvplock
);
struct pfsnode
*pfs
= VTOPFS(vp
);
for (pfspp
= &pfshead
; *pfspp
!= 0; pfspp
= &(*pfspp
)->pfs_next
) {
FREE(vp
->v_data
, M_TEMP
);
struct vop_read_args
*ap
;
struct vnode
*vp
= ap
->a_vp
;
struct uio
*uio
= ap
->a_uio
;
struct proc
*curp
= uio
->uio_procp
;
struct pfsnode
*pfs
= VTOPFS(vp
);
return (procfs_donote(curp
, p
, pfs
, uio
));
return (procfs_doregs(curp
, p
, pfs
, uio
));
return (procfs_dofpregs(curp
, p
, pfs
, uio
));
return (procfs_doctl(curp
, p
, pfs
, uio
));
return (procfs_dostatus(curp
, p
, pfs
, uio
));
return (procfs_domem(curp
, p
, pfs
, uio
));
* Get a string from userland into (buf). Strip a trailing
* nl character (to allow easy access from the shell).
* The buffer should be *buflenp + 1 chars long. vfs_getuserstr
* will automatically add a nul char at the end.
* Returns 0 on success or the following errors
* EINVAL: file offset is non-zero.
* EMSGSIZE: message is longer than kernel buffer
* EFAULT: user i/o buffer is not addressable
vfs_getuserstr(uio
, buf
, buflenp
)
if (uio
->uio_offset
!= 0)
/* must be able to read the whole string in one go */
if (xlen
< uio
->uio_resid
)
error
= uiomove(buf
, xlen
, uio
);
/* allow multiple writes without seeks */
/* cleanup string and remove trailing newline */
if (xlen
> 0 && buf
[xlen
-1] == '\n')
vfs_findname(nm
, buf
, buflen
)
for (; nm
->nm_name
; nm
++)
if (bcmp(buf
, (char *) nm
->nm_name
, buflen
+1) == 0)