svn commit: r279335 - in user/dchagin/lemul/sys: compat/linprocfs fs/procfs fs/pseudofs modules/procfs
Dmitry Chagin
dchagin at FreeBSD.org
Thu Feb 26 21:30:44 UTC 2015
Author: dchagin
Date: Thu Feb 26 21:30:40 2015
New Revision: 279335
URL: https://svnweb.freebsd.org/changeset/base/279335
Log:
Add preliminary support of /proc/[pid]/fd. On Linux this is a
subdirectory containing one entry for each file which the process
has open, named by its file descriptor, and which is a symbolic
link to the actual file.
For now only regular file descriptors are supported.
Added:
user/dchagin/lemul/sys/fs/procfs/procfs_fdlink.c (contents, props changed)
Modified:
user/dchagin/lemul/sys/compat/linprocfs/linprocfs.c
user/dchagin/lemul/sys/fs/procfs/procfs.c
user/dchagin/lemul/sys/fs/procfs/procfs.h
user/dchagin/lemul/sys/fs/pseudofs/pseudofs.c
user/dchagin/lemul/sys/fs/pseudofs/pseudofs.h
user/dchagin/lemul/sys/fs/pseudofs/pseudofs_fileno.c
user/dchagin/lemul/sys/fs/pseudofs/pseudofs_internal.h
user/dchagin/lemul/sys/fs/pseudofs/pseudofs_vncache.c
user/dchagin/lemul/sys/fs/pseudofs/pseudofs_vnops.c
user/dchagin/lemul/sys/modules/procfs/Makefile
Modified: user/dchagin/lemul/sys/compat/linprocfs/linprocfs.c
==============================================================================
--- user/dchagin/lemul/sys/compat/linprocfs/linprocfs.c Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/compat/linprocfs/linprocfs.c Thu Feb 26 21:30:40 2015 (r279335)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/exec.h>
#include <sys/fcntl.h>
+#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/jail.h>
#include <sys/kernel.h>
@@ -1351,21 +1352,6 @@ linprocfs_domodules(PFS_FILL_ARGS)
#endif
/*
- * Filler function for proc/pid/fd
- */
-static int
-linprocfs_dofdescfs(PFS_FILL_ARGS)
-{
-
- if (p == curproc)
- sbuf_printf(sb, "/dev/fd");
- else
- sbuf_printf(sb, "unknown");
- return (0);
-}
-
-
-/*
* Filler function for proc/sys/kernel/random/uuid
*/
static int
@@ -1498,10 +1484,11 @@ linprocfs_init(PFS_INIT_ARGS)
NULL, NULL, NULL, PFS_RD);
pfs_create_file(dir, "status", &linprocfs_doprocstatus,
NULL, NULL, NULL, PFS_RD);
- pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
- NULL, NULL, NULL, 0);
pfs_create_file(dir, "auxv", &linprocfs_doauxv,
NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
+ dir = pfs_create_dir(dir, "fd", NULL, NULL, NULL, 0);
+ pfs_create_link(dir, "---", &procfs_dofdlink,
+ NULL, &procfs_candebug, NULL, PFS_PROCFDDEP);
/* /proc/scsi/... */
dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
Modified: user/dchagin/lemul/sys/fs/procfs/procfs.c
==============================================================================
--- user/dchagin/lemul/sys/fs/procfs/procfs.c Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/fs/procfs/procfs.c Thu Feb 26 21:30:40 2015 (r279335)
@@ -196,6 +196,10 @@ procfs_init(PFS_INIT_ARGS)
pfs_create_link(dir, "file", procfs_doprocfile,
NULL, procfs_notsystem, NULL, 0);
+ dir = pfs_create_dir(dir, "fd", NULL, NULL, NULL, 0);
+ pfs_create_link(dir, "---", &procfs_dofdlink,
+ NULL, procfs_candebug, NULL, PFS_PROCFDDEP);
+
return (0);
}
Modified: user/dchagin/lemul/sys/fs/procfs/procfs.h
==============================================================================
--- user/dchagin/lemul/sys/fs/procfs/procfs.h Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/fs/procfs/procfs.h Thu Feb 26 21:30:40 2015 (r279335)
@@ -39,6 +39,7 @@
#ifdef _KERNEL
int procfs_docurproc(PFS_FILL_ARGS);
+int procfs_dofdlink(PFS_FILL_ARGS);
int procfs_doosrel(PFS_FILL_ARGS);
int procfs_doproccmdline(PFS_FILL_ARGS);
int procfs_doprocctl(PFS_FILL_ARGS);
Added: user/dchagin/lemul/sys/fs/procfs/procfs_fdlink.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/dchagin/lemul/sys/fs/procfs/procfs_fdlink.c Thu Feb 26 21:30:40 2015 (r279335)
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 2015 Dmitry Chagin
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/sbuf.h>
+#include <sys/vnode.h>
+#include <sys/uio.h>
+
+#include <fs/pseudofs/pseudofs.h>
+#include <fs/procfs/procfs.h>
+
+
+int
+procfs_dofdlink(PFS_FILL_ARGS)
+{
+ char *fullpath, *freepath, *endfileno;
+ struct filedesc *fdp;
+ struct vnode *vp;
+ struct file *fp;
+ int fileno, error;
+
+ if (vnode_name == NULL)
+ return (ENOENT);
+
+ fileno = (int)strtol(vnode_name, &endfileno, 10);
+ if (fileno == 0 && (vnode_namelen > 1 ||
+ (vnode_namelen == 1 && vnode_name[0] != '0')))
+ return (ENOENT);
+ if (vnode_namelen != endfileno - vnode_name)
+ return (ENOENT);
+
+ fdp = fdhold(p);
+ if (fdp == NULL)
+ return (ENOENT);
+
+ error = fget_unlocked(fdp, fileno, NULL, &fp, NULL);
+ if (error != 0)
+ goto out;
+
+ freepath = NULL;
+ fullpath = "-";
+ vp = fp->f_vnode;
+ if (vp != NULL) {
+ vref(vp);
+ error = vn_fullpath(td, vp, &fullpath, &freepath);
+ vrele(vp);
+ }
+ if (error == 0)
+ error = sbuf_printf(sb, "%s", fullpath);
+ if (freepath != NULL)
+ free(freepath, M_TEMP);
+ fdrop(fp, td);
+
+ out:
+ fddrop(fdp);
+ return (error);
+}
Modified: user/dchagin/lemul/sys/fs/pseudofs/pseudofs.c
==============================================================================
--- user/dchagin/lemul/sys/fs/pseudofs/pseudofs.c Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/fs/pseudofs/pseudofs.c Thu Feb 26 21:30:40 2015 (r279335)
@@ -222,7 +222,8 @@ pfs_create_link(struct pfs_node *parent,
{
struct pfs_node *pn;
- pn = pfs_alloc_node(parent->pn_info, name, pfstype_symlink);
+ pn = pfs_alloc_node(parent->pn_info, name,
+ (flags & PFS_PROCFDDEP) ? pfstype_fdlink : pfstype_symlink);
pn->pn_fill = fill;
pn->pn_attr = attr;
pn->pn_vis = vis;
@@ -361,7 +362,7 @@ pfs_root(struct mount *mp, int flags, st
struct pfs_info *pi;
pi = (struct pfs_info *)mp->mnt_data;
- return (pfs_vncache_alloc(mp, vpp, pi->pi_root, NO_PID));
+ return (pfs_vncache_alloc(mp, vpp, pi->pi_root, NO_PID, NULL, 0));
}
/*
Modified: user/dchagin/lemul/sys/fs/pseudofs/pseudofs.h
==============================================================================
--- user/dchagin/lemul/sys/fs/pseudofs/pseudofs.h Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/fs/pseudofs/pseudofs.h Thu Feb 26 21:30:40 2015 (r279335)
@@ -62,7 +62,8 @@ typedef enum {
pfstype_parent,
pfstype_file,
pfstype_symlink,
- pfstype_procdir
+ pfstype_procdir,
+ pfstype_fdlink
} pfs_type_t;
/*
@@ -75,6 +76,7 @@ typedef enum {
#define PFS_RAWWR 0x0008 /* raw writer */
#define PFS_RAW (PFS_RAWRD|PFS_RAWWR)
#define PFS_PROCDEP 0x0010 /* process-dependent */
+#define PFS_PROCFDDEP 0x0020 /* process-filedesc-dependent */
/*
* Data structures
@@ -100,9 +102,10 @@ typedef int (*pfs_init_t)(PFS_INIT_ARGS)
*/
#define PFS_FILL_ARGS \
struct thread *td, struct proc *p, struct pfs_node *pn, \
- struct sbuf *sb, struct uio *uio
+ struct sbuf *sb, struct uio *uio, char *vnode_name, \
+ int vnode_namelen
#define PFS_FILL_ARGNAMES \
- td, p, pn, sb, uio
+ td, p, pn, sb, uio, vnode_name, vnode_namelen
#define PFS_FILL_PROTO(name) \
int name(PFS_FILL_ARGS);
typedef int (*pfs_fill_t)(PFS_FILL_ARGS);
Modified: user/dchagin/lemul/sys/fs/pseudofs/pseudofs_fileno.c
==============================================================================
--- user/dchagin/lemul/sys/fs/pseudofs/pseudofs_fileno.c Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/fs/pseudofs/pseudofs_fileno.c Thu Feb 26 21:30:40 2015 (r279335)
@@ -92,6 +92,7 @@ pfs_fileno_alloc(struct pfs_node *pn)
case pfstype_file:
case pfstype_symlink:
case pfstype_procdir:
+ case pfstype_fdlink:
pn->pn_fileno = alloc_unr(pn->pn_info->pi_unrhdr);
break;
case pfstype_this:
@@ -145,6 +146,7 @@ pfs_fileno_free(struct pfs_node *pn)
case pfstype_file:
case pfstype_symlink:
case pfstype_procdir:
+ case pfstype_fdlink:
free_unr(pn->pn_info->pi_unrhdr, pn->pn_fileno);
break;
case pfstype_this:
Modified: user/dchagin/lemul/sys/fs/pseudofs/pseudofs_internal.h
==============================================================================
--- user/dchagin/lemul/sys/fs/pseudofs/pseudofs_internal.h Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/fs/pseudofs/pseudofs_internal.h Thu Feb 26 21:30:40 2015 (r279335)
@@ -43,6 +43,8 @@ struct pfs_vdata {
struct pfs_node *pvd_pn;
pid_t pvd_pid;
struct vnode *pvd_vnode;
+ char *pvd_vnode_name;
+ int pvd_vnode_namelen;
struct pfs_vdata*pvd_prev, *pvd_next;
int pvd_dead:1;
};
@@ -53,7 +55,8 @@ struct pfs_vdata {
void pfs_vncache_load (void);
void pfs_vncache_unload (void);
int pfs_vncache_alloc (struct mount *, struct vnode **,
- struct pfs_node *, pid_t pid);
+ struct pfs_node *, pid_t pid,
+ char *name, int namelen);
int pfs_vncache_free (struct vnode *);
/*
Modified: user/dchagin/lemul/sys/fs/pseudofs/pseudofs_vncache.c
==============================================================================
--- user/dchagin/lemul/sys/fs/pseudofs/pseudofs_vncache.c Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/fs/pseudofs/pseudofs_vncache.c Thu Feb 26 21:30:40 2015 (r279335)
@@ -108,13 +108,15 @@ pfs_vncache_unload(void)
* Allocate a vnode
*/
int
-pfs_vncache_alloc(struct mount *mp, struct vnode **vpp,
- struct pfs_node *pn, pid_t pid)
+pfs_vncache_alloc(struct mount *mp, struct vnode **vpp, struct pfs_node *pn,
+ pid_t pid, char *name, int namelen)
{
struct pfs_vdata *pvd, *pvd2;
struct vnode *vp;
int error;
+ PFS_TRACE(("%s", (name != NULL? name : pn->pn_name)));
+
/*
* See if the vnode is in the cache.
* XXX linear search is not very efficient.
@@ -124,6 +126,10 @@ retry:
for (pvd = pfs_vncache; pvd; pvd = pvd->pvd_next) {
if (pvd->pvd_pn == pn && pvd->pvd_pid == pid &&
pvd->pvd_vnode->v_mount == mp) {
+ if ((pn->pn_flags & PFS_PROCFDDEP) &&
+ (namelen != pvd->pvd_vnode_namelen ||
+ bcmp(name, pvd->pvd_vnode_name, namelen)))
+ continue;
vp = pvd->pvd_vnode;
VI_LOCK(vp);
mtx_unlock(&pfs_vncache_mutex);
@@ -148,7 +154,7 @@ retry:
mtx_unlock(&pfs_vncache_mutex);
/* nope, get a new one */
- pvd = malloc(sizeof *pvd, M_PFSVNCACHE, M_WAITOK);
+ pvd = malloc(sizeof *pvd, M_PFSVNCACHE, M_WAITOK|M_ZERO);
pvd->pvd_next = pvd->pvd_prev = NULL;
error = getnewvnode("pseudofs", mp, &pfs_vnodeops, vpp);
if (error) {
@@ -157,6 +163,12 @@ retry:
}
pvd->pvd_pn = pn;
pvd->pvd_pid = pid;
+ if (name != NULL && namelen > 0) {
+ pvd->pvd_vnode_name = malloc(namelen + 1, M_PFSVNCACHE,
+ M_WAITOK);
+ strlcpy(pvd->pvd_vnode_name, name, namelen + 1);
+ pvd->pvd_vnode_namelen = namelen;
+ }
(*vpp)->v_data = pvd;
switch (pn->pn_type) {
case pfstype_root:
@@ -175,6 +187,7 @@ retry:
(*vpp)->v_type = VREG;
break;
case pfstype_symlink:
+ case pfstype_fdlink:
(*vpp)->v_type = VLNK;
break;
case pfstype_none:
@@ -207,6 +220,10 @@ retry2:
for (pvd2 = pfs_vncache; pvd2; pvd2 = pvd2->pvd_next) {
if (pvd2->pvd_pn == pn && pvd2->pvd_pid == pid &&
pvd2->pvd_vnode->v_mount == mp) {
+ if ((pn->pn_flags & PFS_PROCFDDEP) &&
+ (namelen != pvd2->pvd_vnode_namelen ||
+ bcmp(name, pvd2->pvd_vnode_name, namelen)))
+ continue;
vp = pvd2->pvd_vnode;
VI_LOCK(vp);
mtx_unlock(&pfs_vncache_mutex);
@@ -243,7 +260,11 @@ pfs_vncache_free(struct vnode *vp)
mtx_lock(&pfs_vncache_mutex);
pvd = (struct pfs_vdata *)vp->v_data;
+
KASSERT(pvd != NULL, ("pfs_vncache_free(): no vnode data\n"));
+ PFS_TRACE(("%s", (pvd->pvd_vnode_name != NULL ?
+ pvd->pvd_vnode_name : pvd->pvd_pn->pn_name)));
+
if (pvd->pvd_next)
pvd->pvd_next->pvd_prev = pvd->pvd_prev;
if (pvd->pvd_prev) {
@@ -255,6 +276,8 @@ pfs_vncache_free(struct vnode *vp)
}
mtx_unlock(&pfs_vncache_mutex);
+ if (pvd->pvd_vnode_name != NULL)
+ free(pvd->pvd_vnode_name, M_PFSVNCACHE);
free(pvd, M_PFSVNCACHE);
vp->v_data = NULL;
return (0);
Modified: user/dchagin/lemul/sys/fs/pseudofs/pseudofs_vnops.c
==============================================================================
--- user/dchagin/lemul/sys/fs/pseudofs/pseudofs_vnops.c Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/fs/pseudofs/pseudofs_vnops.c Thu Feb 26 21:30:40 2015 (r279335)
@@ -34,9 +34,12 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/capsicum.h>
#include <sys/ctype.h>
#include <sys/dirent.h>
#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -63,7 +66,8 @@ __FBSDID("$FreeBSD$");
("%s(): VREG vnode refers to non-file pfs_node", __func__))
#define KASSERT_PN_IS_LINK(pn) \
- KASSERT((pn)->pn_type == pfstype_symlink, \
+ KASSERT((pn)->pn_type == pfstype_symlink || \
+ (pn)->pn_type == pfstype_fdlink, \
("%s(): VLNK vnode refers to non-link pfs_node", __func__))
/*
@@ -139,7 +143,8 @@ pfs_access(struct vop_access_args *va)
struct vattr vattr;
int error;
- PFS_TRACE(("%s", pvd->pvd_pn->pn_name));
+ PFS_TRACE(("%s", (pvd->pvd_vnode_name != NULL ?
+ pvd->pvd_vnode_name : pvd->pvd_pn->pn_name)));
(void)pvd;
error = VOP_GETATTR(vn, &vattr, va->a_cred);
@@ -229,6 +234,7 @@ pfs_getattr(struct vop_getattr_args *va)
break;
case pfstype_file:
case pfstype_symlink:
+ case pfstype_fdlink:
vap->va_mode = 0444;
break;
default:
@@ -402,7 +408,7 @@ pfs_vptocnp(struct vop_vptocnp_args *ap)
locked = VOP_ISLOCKED(vp);
VOP_UNLOCK(vp, 0);
- error = pfs_vncache_alloc(mp, dvp, pn, pid);
+ error = pfs_vncache_alloc(mp, dvp, pn, pid, NULL, 0);
if (error) {
vn_lock(vp, locked | LK_RETRY);
vfs_unbusy(mp);
@@ -432,10 +438,15 @@ pfs_lookup(struct vop_cachedlookup_args
struct pfs_vdata *pvd = vn->v_data;
struct pfs_node *pd = pvd->pvd_pn;
struct pfs_node *pn, *pdn = NULL;
+ struct thread *td = curthread;
struct mount *mp;
+ cap_rights_t rights;
pid_t pid = pvd->pvd_pid;
- char *pname;
- int error, i, namelen, visible;
+ char *pname, *pnameend;
+ int error, i, namelen, visible, fileno;
+ struct filedesc *fdp;
+ struct file *fp;
+ struct proc *p;
PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr));
pfs_assert_not_owned(pd);
@@ -519,7 +530,8 @@ pfs_lookup(struct vop_cachedlookup_args
/* named node */
for (pn = pd->pn_nodes; pn != NULL; pn = pn->pn_next)
- if (pn->pn_type == pfstype_procdir)
+ if (pn->pn_type == pfstype_procdir ||
+ pn->pn_type == pfstype_fdlink)
pdn = pn;
else if (pn->pn_name[namelen] == '\0' &&
bcmp(pname, pn->pn_name, namelen) == 0) {
@@ -528,7 +540,7 @@ pfs_lookup(struct vop_cachedlookup_args
}
/* process dependent node */
- if ((pn = pdn) != NULL) {
+ if ((pn = pdn) != NULL && pn->pn_type == pfstype_procdir) {
pid = 0;
for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i)
if ((pid = pid * 10 + pname[i] - '0') > PID_MAX)
@@ -539,8 +551,38 @@ pfs_lookup(struct vop_cachedlookup_args
}
}
- pfs_unlock(pd);
+ /* process filedesc dependent node */
+ if ((pn = pdn) != NULL && pn->pn_type == pfstype_fdlink) {
+ pfs_unlock(pd);
+ fileno = (int)strtol(pname, &pnameend, 10);
+ if ((fileno == 0 && (namelen > 1 ||
+ (namelen == 1 && pname[0] != '0'))) ||
+ (namelen != pnameend - pname)) {
+ goto bad;
+ }
+ if ((p = pfind(pid)) == NULL)
+ goto bad;
+ fdp = fdhold(p);
+ if (fdp == NULL) {
+ PROC_UNLOCK(p);
+ goto bad;
+ }
+
+ error = fget_unlocked(fdp, fileno,
+ cap_rights_init(&rights, CAP_READ), &fp, NULL);
+ if (error == 0) {
+ fdrop(fp, td);
+ fddrop(fdp);
+ PROC_UNLOCK(p);
+ goto got_pnode;
+ }
+ fddrop(fdp);
+ PROC_UNLOCK(p);
+ goto bad;
+ }
+ pfs_unlock(pd);
+ bad:
PFS_RETURN (ENOENT);
got_pnode:
@@ -552,7 +594,7 @@ pfs_lookup(struct vop_cachedlookup_args
goto failed;
}
- error = pfs_vncache_alloc(mp, vpp, pn, pid);
+ error = pfs_vncache_alloc(mp, vpp, pn, pid, pname, namelen);
if (error)
goto failed;
@@ -648,7 +690,8 @@ pfs_read(struct vop_read_args *va)
if (pn->pn_flags & PFS_RAWRD) {
PFS_TRACE(("%zd resid", uio->uio_resid));
- error = pn_fill(curthread, proc, pn, NULL, uio);
+ error = pn_fill(curthread, proc, pn, NULL, uio,
+ pvd->pvd_vnode_name, pvd->pvd_vnode_namelen);
PFS_TRACE(("%zd resid", uio->uio_resid));
goto ret;
}
@@ -668,7 +711,8 @@ pfs_read(struct vop_read_args *va)
goto ret;
}
- error = pn_fill(curthread, proc, pn, sb, uio);
+ error = pn_fill(curthread, proc, pn, sb, uio,
+ pvd->pvd_vnode_name, pvd->pvd_vnode_namelen);
if (error) {
sbuf_delete(sb);
@@ -697,9 +741,11 @@ ret:
*/
static int
pfs_iterate(struct thread *td, struct proc *proc, struct pfs_node *pd,
- struct pfs_node **pn, struct proc **p)
+ struct pfs_node **pn, struct proc **p, struct filedesc **fdp, int *fileno)
{
- int visible;
+ struct file *fp;
+ cap_rights_t rights;
+ int error, visible;
sx_assert(&allproc_lock, SX_SLOCKED);
pfs_assert_owned(pd);
@@ -707,7 +753,8 @@ pfs_iterate(struct thread *td, struct pr
if (*pn == NULL) {
/* first node */
*pn = pd->pn_nodes;
- } else if ((*pn)->pn_type != pfstype_procdir) {
+ } else if ((*pn)->pn_type != pfstype_procdir &&
+ (*pn)->pn_type != pfstype_fdlink) {
/* next node */
*pn = (*pn)->pn_next;
}
@@ -723,7 +770,35 @@ pfs_iterate(struct thread *td, struct pr
else
PROC_LOCK(*p);
}
+ if (*pn != NULL && (*pn)->pn_type == pfstype_fdlink) {
+ /* Next fileno */
+ KASSERT(proc != NULL,
+ ("%s(): fdlink has no proc", __func__));
+ if (*fdp == NULL) {
+ *fdp = fdhold(proc);
+ if (*fdp != NULL)
+ *fileno = -1;
+ }
+ while (*fdp != NULL) {
+ (*fileno) += 1;
+ if ((*fdp)->fd_nfiles == 0 ||
+ *fileno > (*fdp)->fd_lastfile) {
+ fddrop(*fdp);
+ *fdp = NULL;
+ break;
+ }
+ error = fget_unlocked(*fdp, *fileno,
+ cap_rights_init(&rights, CAP_READ), &fp, NULL);
+ if (error == 0) {
+ fdrop(fp, td);
+ break;
+ }
+ }
+ /* Out of process files: next node */
+ if (*fdp == NULL)
+ *pn = (*pn)->pn_next;
+ }
if ((*pn) == NULL)
return (-1);
@@ -759,12 +834,13 @@ pfs_readdir(struct vop_readdir_args *va)
struct pfs_node *pd = pvd->pvd_pn;
pid_t pid = pvd->pvd_pid;
struct proc *p, *proc;
+ struct filedesc *fdp;
struct pfs_node *pn;
struct uio *uio;
struct pfsentry *pfsent, *pfsent2;
struct pfsdirentlist lst;
off_t offset;
- int error, i, resid;
+ int error, i, resid, fileno;
STAILQ_INIT(&lst);
error = 0;
@@ -799,12 +875,16 @@ pfs_readdir(struct vop_readdir_args *va)
KASSERT(pid == NO_PID || proc != NULL,
("%s(): no process for pid %lu", __func__, (unsigned long)pid));
+ fdp = NULL;
/* skip unwanted entries */
for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) {
- if (pfs_iterate(curthread, proc, pd, &pn, &p) == -1) {
+ if (pfs_iterate(curthread,
+ proc, pd, &pn, &p, &fdp, &fileno) == -1) {
/* nothing left... */
if (proc != NULL)
PROC_UNLOCK(proc);
+ if (fdp != NULL)
+ fddrop(fdp);
pfs_unlock(pd);
sx_sunlock(&allproc_lock);
PFS_RETURN (0);
@@ -812,7 +892,7 @@ pfs_readdir(struct vop_readdir_args *va)
}
/* fill in entries */
- while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 &&
+ while (pfs_iterate(curthread, proc, pd, &pn, &p, &fdp, &fileno) != -1 &&
resid >= PFS_DELEN) {
if ((pfsent = malloc(sizeof(struct pfsentry), M_IOV,
M_NOWAIT | M_ZERO)) == NULL) {
@@ -822,8 +902,12 @@ pfs_readdir(struct vop_readdir_args *va)
pfsent->entry.d_reclen = PFS_DELEN;
pfsent->entry.d_fileno = pn_fileno(pn, pid);
/* PFS_DELEN was picked to fit PFS_NAMLEN */
- for (i = 0; i < PFS_NAMELEN - 1 && pn->pn_name[i] != '\0'; ++i)
- pfsent->entry.d_name[i] = pn->pn_name[i];
+
+ if (pn->pn_type != pfstype_procdir &&
+ pn->pn_type != pfstype_fdlink)
+ for (i = 0; i < PFS_NAMELEN - 1 &&
+ pn->pn_name[i] != '\0'; ++i)
+ pfsent->entry.d_name[i] = pn->pn_name[i];
pfsent->entry.d_name[i] = 0;
pfsent->entry.d_namlen = i;
switch (pn->pn_type) {
@@ -842,6 +926,10 @@ pfs_readdir(struct vop_readdir_args *va)
case pfstype_file:
pfsent->entry.d_type = DT_REG;
break;
+ case pfstype_fdlink:
+ pfsent->entry.d_namlen = snprintf(pfsent->entry.d_name,
+ PFS_NAMELEN, "%d", fileno);
+ /* FALLTHROUGH */
case pfstype_symlink:
pfsent->entry.d_type = DT_LNK;
break;
@@ -855,6 +943,8 @@ pfs_readdir(struct vop_readdir_args *va)
}
if (proc != NULL)
PROC_UNLOCK(proc);
+ if (fdp != NULL)
+ fddrop(fdp);
pfs_unlock(pd);
sx_sunlock(&allproc_lock);
i = 0;
@@ -883,7 +973,8 @@ pfs_readlink(struct vop_readlink_args *v
struct sbuf sb;
int error, locked;
- PFS_TRACE(("%s", pn->pn_name));
+ PFS_TRACE(("%s", (pvd->pvd_vnode_name != NULL ?
+ pvd->pvd_vnode_name : pn->pn_name)));
pfs_assert_not_owned(pn);
if (vn->v_type != VLNK)
@@ -910,12 +1001,21 @@ pfs_readlink(struct vop_readlink_args *v
/* sbuf_new() can't fail with a static buffer */
sbuf_new(&sb, buf, sizeof buf, 0);
- error = pn_fill(curthread, proc, pn, &sb, NULL);
+ error = pn_fill(curthread, proc, pn, &sb, NULL,
+ pvd->pvd_vnode_name, pvd->pvd_vnode_namelen);
if (proc != NULL)
PRELE(proc);
vn_lock(vn, locked | LK_RETRY);
- vdrop(vn);
+
+ /*
+ * Vgone file descriptor dependent node right after use as
+ * is not trivial to control file operations from pseudofs
+ */
+ if (pn->pn_flags & PFS_PROCFDDEP)
+ vgone(vn);
+ else
+ vdrop(vn);
if (error) {
sbuf_delete(&sb);
@@ -942,7 +1042,8 @@ pfs_reclaim(struct vop_reclaim_args *va)
struct pfs_vdata *pvd = vn->v_data;
struct pfs_node *pn = pvd->pvd_pn;
- PFS_TRACE(("%s", pn->pn_name));
+ PFS_TRACE(("%s", (pvd->pvd_vnode_name != NULL ?
+ pvd->pvd_vnode_name : pn->pn_name)));
pfs_assert_not_owned(pn);
return (pfs_vncache_free(va->a_vp));
@@ -1003,7 +1104,8 @@ pfs_write(struct vop_write_args *va)
}
if (pn->pn_flags & PFS_RAWWR) {
- error = pn_fill(curthread, proc, pn, NULL, uio);
+ error = pn_fill(curthread, proc, pn, NULL, uio,
+ pvd->pvd_vnode_name, pvd->pvd_vnode_namelen);
if (proc != NULL)
PRELE(proc);
PFS_RETURN (error);
@@ -1016,7 +1118,8 @@ pfs_write(struct vop_write_args *va)
PFS_RETURN (error);
}
- error = pn_fill(curthread, proc, pn, &sb, uio);
+ error = pn_fill(curthread, proc, pn, &sb, uio,
+ pvd->pvd_vnode_name, pvd->pvd_vnode_namelen);
sbuf_delete(&sb);
if (proc != NULL)
Modified: user/dchagin/lemul/sys/modules/procfs/Makefile
==============================================================================
--- user/dchagin/lemul/sys/modules/procfs/Makefile Thu Feb 26 21:15:02 2015 (r279334)
+++ user/dchagin/lemul/sys/modules/procfs/Makefile Thu Feb 26 21:30:40 2015 (r279335)
@@ -8,6 +8,7 @@ SRCS+= opt_compat.h
SRCS+= vnode_if.h
SRCS+= procfs_ctl.c
SRCS+= procfs_dbregs.c
+SRCS+= procfs_fdlink.c
SRCS+= procfs_fpregs.c
SRCS+= procfs_ioctl.c
SRCS+= procfs_map.c
@@ -27,6 +28,7 @@ EXPORT_SYMS+= procfs_docurproc
EXPORT_SYMS+= procfs_doprocfile
EXPORT_SYMS+= procfs_doprocmem
EXPORT_SYMS+= procfs_notsystem
+EXPORT_SYMS+= procfs_dofdlink
.if !defined(KERNBUILDDIR)
opt_compat.h:
More information about the svn-src-user
mailing list