summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2001-06-10 18:39:21 +0000
committerdes <des@FreeBSD.org>2001-06-10 18:39:21 +0000
commitda96d2410a9b9a69efa0c6f3ed1087c224061089 (patch)
tree3a102271c7e1fe1e96777fe125c2dcfb57246657 /sys/fs
parent081b21dba9aa5d3c70bc54fcf7ae5a1a982d0355 (diff)
downloadFreeBSD-src-da96d2410a9b9a69efa0c6f3ed1087c224061089.zip
FreeBSD-src-da96d2410a9b9a69efa0c6f3ed1087c224061089.tar.gz
Add support for process-dependent directories. This means that save for
the lack of a man page, pseudofs is mostly complete now.
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/pseudofs/pseudofs.c2
-rw-r--r--sys/fs/pseudofs/pseudofs.h22
-rw-r--r--sys/fs/pseudofs/pseudofs_fileno.c26
-rw-r--r--sys/fs/pseudofs/pseudofs_internal.h16
-rw-r--r--sys/fs/pseudofs/pseudofs_vncache.c57
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c219
6 files changed, 195 insertions, 147 deletions
diff --git a/sys/fs/pseudofs/pseudofs.c b/sys/fs/pseudofs/pseudofs.c
index 24379aa..e74c683 100644
--- a/sys/fs/pseudofs/pseudofs.c
+++ b/sys/fs/pseudofs/pseudofs.c
@@ -101,7 +101,7 @@ pfs_root(struct mount *mp, struct vnode **vpp)
struct pfs_info *pi;
pi = (struct pfs_info *)mp->mnt_data;
- return pfs_vncache_alloc(mp, vpp, pi->pi_root);
+ return pfs_vncache_alloc(mp, vpp, pi->pi_root, NO_PID);
}
/*
diff --git a/sys/fs/pseudofs/pseudofs.h b/sys/fs/pseudofs/pseudofs.h
index 928d2db..539a04d 100644
--- a/sys/fs/pseudofs/pseudofs.h
+++ b/sys/fs/pseudofs/pseudofs.h
@@ -45,12 +45,9 @@ typedef enum {
pfstype_parent,
pfstype_file,
pfstype_symlink,
- pfstype_procdep
+ pfstype_procdir
} pfs_type_t;
-/* Flags */
-#define PFS_DYNAMIC 1
-
/*
* Data structures
*/
@@ -58,7 +55,11 @@ struct pfs_info;
struct pfs_node;
struct pfs_bitmap;
-typedef int (*pfs_fill_t)(struct pfs_node *, struct proc *, struct sbuf *);
+#define PFS_FILL_ARGS \
+ struct proc *curp, struct proc *p, struct pfs_node *pn, struct sbuf *sb
+#define PFS_FILL_PROTO(name) \
+ int name(PFS_FILL_ARGS);
+typedef int (*pfs_fill_t)(PFS_FILL_ARGS);
struct pfs_bitmap; /* opaque */
@@ -75,7 +76,7 @@ struct pfs_info {
};
/*
- * pfs_node: describes a node (file or directory) within a pseudofs
+ * pfs_node: describes a node (file or directory) within a pseudofs
*/
struct pfs_node {
char pn_name[PFS_NAMELEN];
@@ -94,12 +95,7 @@ struct pfs_node {
#define pn_nodes u1._pn_nodes
/* members below this line aren't initialized */
struct pfs_node *pn_parent;
- union {
- u_int32_t _pn_fileno;
- struct pfs_node *_pn_shadow;
- } u2;
-#define pn_fileno u2._pn_fileno
-#define pn_shadow u2._pn_shadow
+ u_int32_t pn_fileno;
};
#define PFS_NODE(name, type, flags, uid, gid, mode, data) \
@@ -116,6 +112,8 @@ struct pfs_node {
PFS_NODE(name, pfstype_file, flags, uid, gid, mode, func)
#define PFS_SYMLINK(name, flags, uid, gid, mode, func) \
PFS_NODE(name, pfstype_symlink, flags, uid, gid, mode, func)
+#define PFS_PROCDIR(uid, gid, mode, nodes) \
+ PFS_NODE("", pfstype_procdir, 0, uid, gid, mode, nodes)
#define PFS_LASTNODE \
PFS_NODE("", pfstype_none, 0, 0, 0, 0, NULL)
diff --git a/sys/fs/pseudofs/pseudofs_fileno.c b/sys/fs/pseudofs/pseudofs_fileno.c
index f27b885..fa23edf 100644
--- a/sys/fs/pseudofs/pseudofs_fileno.c
+++ b/sys/fs/pseudofs/pseudofs_fileno.c
@@ -43,12 +43,12 @@
#include <fs/pseudofs/pseudofs.h>
#include <fs/pseudofs/pseudofs_internal.h>
-static MALLOC_DEFINE(M_PFSFILENO, "pseudofs_fileno", "pseudofs fileno bitmap");
+static MALLOC_DEFINE(M_PFSFILENO, "pfs_fileno", "pseudofs fileno bitmap");
static struct mtx pfs_fileno_mutex;
#define PFS_BITMAP_SIZE 4096
-#define PFS_SLOT_BITS (sizeof(unsigned int) * CHAR_BIT)
+#define PFS_SLOT_BITS (int)(sizeof(unsigned int) * CHAR_BIT)
#define PFS_BITMAP_BITS (PFS_BITMAP_SIZE * PFS_SLOT_BITS)
struct pfs_bitmap {
u_int32_t pb_offset;
@@ -117,8 +117,11 @@ pfs_fileno_uninit(struct pfs_info *pi)
used += pb->pb_used;
FREE(pb, M_PFSFILENO);
}
+#if 0
+ /* we currently don't reclaim filenos */
if (used > 2)
printf("WARNING: %d file numbers still in use\n", used);
+#endif
}
/*
@@ -202,6 +205,7 @@ pfs_free_fileno(struct pfs_info *pi, u_int32_t fileno)
--pb->pb_used;
mtx_unlock(&pi->pi_mutex);
+ printf("pfs_free_fileno(): reclaimed %d\n", fileno);
}
/*
@@ -219,6 +223,7 @@ pfs_fileno_alloc(struct pfs_info *pi, struct pfs_node *pn)
case pfstype_dir:
case pfstype_file:
case pfstype_symlink:
+ case pfstype_procdir:
pn->pn_fileno = pfs_get_fileno(pi);
break;
case pfstype_this:
@@ -237,16 +242,13 @@ pfs_fileno_alloc(struct pfs_info *pi, struct pfs_node *pn)
("pfstype_parent node has no grandparent"));
pn->pn_fileno = pn->pn_parent->pn_parent->pn_fileno;
break;
- case pfstype_procdep:
- KASSERT(1,
- ("pfs_fileno_alloc() called for pfstype_procdep node"));
- break;
case pfstype_none:
- KASSERT(1,
+ KASSERT(0,
("pfs_fileno_alloc() called for pfstype_none node"));
break;
}
-
+
+#if 0
printf("pfs_fileno_alloc(): %s: ", pi->pi_name);
if (pn->pn_parent) {
if (pn->pn_parent->pn_parent) {
@@ -255,6 +257,7 @@ pfs_fileno_alloc(struct pfs_info *pi, struct pfs_node *pn)
printf("%s/", pn->pn_parent->pn_name);
}
printf("%s -> %d\n", pn->pn_name, pn->pn_fileno);
+#endif
}
/*
@@ -268,18 +271,15 @@ pfs_fileno_free(struct pfs_info *pi, struct pfs_node *pn)
case pfstype_dir:
case pfstype_file:
case pfstype_symlink:
+ case pfstype_procdir:
pfs_free_fileno(pi, pn->pn_fileno);
break;
case pfstype_this:
case pfstype_parent:
/* ignore these, as they don't "own" their file number */
break;
- case pfstype_procdep:
- KASSERT(1,
- ("pfs_fileno_free() called for pfstype_procdep node"));
- break;
case pfstype_none:
- KASSERT(1,
+ KASSERT(0,
("pfs_fileno_free() called for pfstype_none node"));
break;
}
diff --git a/sys/fs/pseudofs/pseudofs_internal.h b/sys/fs/pseudofs/pseudofs_internal.h
index 0e25c47..9307466 100644
--- a/sys/fs/pseudofs/pseudofs_internal.h
+++ b/sys/fs/pseudofs/pseudofs_internal.h
@@ -37,12 +37,20 @@
SYSCTL_DECL(_vfs_pfs);
/*
+ * Vnode data
+ */
+struct pfs_vdata {
+ struct pfs_node *pvd_pn;
+ pid_t pvd_pid;
+};
+
+/*
* Vnode cache
*/
void pfs_vncache_load (void);
void pfs_vncache_unload (void);
int pfs_vncache_alloc (struct mount *, struct vnode **,
- struct pfs_node *);
+ struct pfs_node *, pid_t pid);
int pfs_vncache_free (struct vnode *);
/*
@@ -55,10 +63,4 @@ void pfs_fileno_uninit (struct pfs_info *);
void pfs_fileno_alloc (struct pfs_info *, struct pfs_node *);
void pfs_fileno_free (struct pfs_info *, struct pfs_node *);
-/*
- * Shadow manager
- */
-void pfs_create_shadow (struct pfs_info *, struct pfs_node *, pid_t);
-void pfs_reap_shadows (pid_t);
-
#endif
diff --git a/sys/fs/pseudofs/pseudofs_vncache.c b/sys/fs/pseudofs/pseudofs_vncache.c
index 8c822f2..f222f64 100644
--- a/sys/fs/pseudofs/pseudofs_vncache.c
+++ b/sys/fs/pseudofs/pseudofs_vncache.c
@@ -41,7 +41,7 @@
#include <fs/pseudofs/pseudofs.h>
#include <fs/pseudofs/pseudofs_internal.h>
-static MALLOC_DEFINE(M_PFSVNCACHE, "pseudofs_vncache", "pseudofs vnode cache");
+static MALLOC_DEFINE(M_PFSVNCACHE, "pfs_vncache", "pseudofs vnode cache");
static struct mtx pfs_vncache_mutex;
@@ -85,32 +85,40 @@ pfs_vncache_unload(void)
* Allocate a vnode
*/
int
-pfs_vncache_alloc(struct mount *mp, struct vnode **vpp, struct pfs_node *pn)
+pfs_vncache_alloc(struct mount *mp, struct vnode **vpp,
+ struct pfs_node *pn, pid_t pid)
{
struct pfs_vnode *pv;
+ struct pfs_vdata *pvd;
int error;
- mtx_lock(&pfs_vncache_mutex);
-
/* see if the vnode is in the cache */
- for (pv = pfs_vncache; pv; pv = pv->pv_next)
- if (pv->pv_vnode->v_data == pn)
+ mtx_lock(&pfs_vncache_mutex);
+ for (pv = pfs_vncache; pv; pv = pv->pv_next) {
+ pvd = (struct pfs_vdata *)pv->pv_vnode->v_data;
+ if (pvd->pvd_pn == pn && pvd->pvd_pid == pid) {
if (vget(pv->pv_vnode, 0, curproc) == 0) {
++pfs_vncache_hits;
*vpp = pv->pv_vnode;
mtx_unlock(&pfs_vncache_mutex);
return (0);
}
+ /* XXX if this can happen, we're in trouble */
+ break;
+ }
+ }
+ mtx_unlock(&pfs_vncache_mutex);
++pfs_vncache_misses;
/* nope, get a new one */
MALLOC(pv, struct pfs_vnode *, sizeof *pv, M_PFSVNCACHE, M_WAITOK);
+ MALLOC(pvd, struct pfs_vdata *, sizeof *pvd, M_PFSVNCACHE, M_WAITOK);
error = getnewvnode(VT_PSEUDOFS, mp, pfs_vnodeop_p, vpp);
- if (error) {
- mtx_unlock(&pfs_vncache_mutex);
+ if (error)
return (error);
- }
- (*vpp)->v_data = pn;
+ pvd->pvd_pn = pn;
+ pvd->pvd_pid = pid;
+ (*vpp)->v_data = pvd;
switch (pn->pn_type) {
case pfstype_root:
(*vpp)->v_flag = VROOT;
@@ -120,6 +128,7 @@ pfs_vncache_alloc(struct mount *mp, struct vnode **vpp, struct pfs_node *pn)
case pfstype_dir:
case pfstype_this:
case pfstype_parent:
+ case pfstype_procdir:
(*vpp)->v_type = VDIR;
break;
case pfstype_file:
@@ -128,10 +137,13 @@ pfs_vncache_alloc(struct mount *mp, struct vnode **vpp, struct pfs_node *pn)
case pfstype_symlink:
(*vpp)->v_type = VLNK;
break;
+ case pfstype_none:
+ KASSERT(0, ("pfs_vncache_alloc called for null node\n"));
default:
panic("%s has unexpected type: %d", pn->pn_name, pn->pn_type);
}
pv->pv_vnode = *vpp;
+ mtx_lock(&pfs_vncache_mutex);
pv->pv_next = pfs_vncache;
pfs_vncache = pv;
mtx_unlock(&pfs_vncache_mutex);
@@ -145,25 +157,22 @@ int
pfs_vncache_free(struct vnode *vp)
{
struct pfs_vnode *prev, *pv;
+ struct pfs_vdata *pvd;
mtx_lock(&pfs_vncache_mutex);
for (prev = NULL, pv = pfs_vncache; pv; prev = pv, pv = pv->pv_next)
if (pv->pv_vnode == vp)
break;
- if (!pv)
- printf("pfs_vncache_free(): not in cache\n"); /* it should be! */
-#if 0
- if (vp->v_data == ((struct pfs_info *)vp->v_mount->mnt_data)->pi_root)
- printf("root vnode reclaimed\n");
-#endif
- vp->v_data = NULL;
- if (pv) {
- if (prev)
- prev->pv_next = pv->pv_next;
- else
- pfs_vncache = pv->pv_next;
- FREE(pv, M_PFSVNCACHE);
- }
+ KASSERT(pv != NULL, ("pfs_vncache_free(): not in cache\n"));
+ if (prev)
+ prev->pv_next = pv->pv_next;
+ else
+ pfs_vncache = pv->pv_next;
mtx_unlock(&pfs_vncache_mutex);
+
+ pvd = (struct pfs_vdata *)vp->v_data;
+ FREE(pvd, M_PFSVNCACHE);
+ vp->v_data = NULL;
+ FREE(pv, M_PFSVNCACHE);
return (0);
}
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index ae6cbe1..473b414 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -79,7 +79,8 @@ static int
pfs_getattr(struct vop_getattr_args *va)
{
struct vnode *vn = va->a_vp;
- struct pfs_node *pn = (struct pfs_node *)vn->v_data;
+ struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
+ struct pfs_node *pn = pvd->pvd_pn;
struct vattr *vap = va->a_vap;
VATTR_NULL(vap);
@@ -105,19 +106,17 @@ pfs_getattr(struct vop_getattr_args *va)
static int
pfs_lookup(struct vop_lookup_args *va)
{
- struct vnode *dvp = va->a_dvp;
+ struct vnode *vn = va->a_dvp;
struct vnode **vpp = va->a_vpp;
struct componentname *cnp = va->a_cnp;
-#if 0
- struct pfs_info *pi = (struct pfs_info *)dvp->v_mount->mnt_data;
-#endif
- struct pfs_node *pd = (struct pfs_node *)dvp->v_data, *pn;
- struct proc *p;
+ struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
+ struct pfs_node *pd = pvd->pvd_pn;
+ struct pfs_node *pn, *pdn = NULL;
+ pid_t pid = pvd->pvd_pid;
char *pname;
- int error, i;
- pid_t pid;
+ int error, i, namelen;
- if (dvp->v_type != VDIR)
+ if (vn->v_type != VDIR)
return (ENOTDIR);
/* don't support CREATE, RENAME or DELETE */
@@ -129,11 +128,12 @@ pfs_lookup(struct vop_lookup_args *va)
return (ENOENT);
/* self */
+ namelen = cnp->cn_namelen;
pname = cnp->cn_nameptr;
- if (cnp->cn_namelen == 1 && *pname == '.') {
+ if (namelen == 1 && *pname == '.') {
pn = pd;
- *vpp = dvp;
- VREF(dvp);
+ *vpp = vn;
+ VREF(vn);
goto got_vnode;
}
@@ -142,61 +142,48 @@ pfs_lookup(struct vop_lookup_args *va)
if (pd->pn_type == pfstype_root)
return (EIO);
KASSERT(pd->pn_parent, ("non-root directory has no parent"));
- return pfs_vncache_alloc(dvp->v_mount, vpp, pd->pn_parent);
+ /*
+ * This one is tricky. Descendents of procdir nodes
+ * inherit their parent's process affinity, but
+ * there's no easy reverse mapping. For simplicity,
+ * we assume that if this node is a procdir, its
+ * parent isn't (which is correct as long as
+ * descendents of procdir nodes are never procdir
+ * nodes themselves)
+ */
+ if (pd->pn_type == pfstype_procdir)
+ pid = NO_PID;
+ return pfs_vncache_alloc(vn->v_mount, vpp, pd->pn_parent, pid);
}
- /* process dependent */
- for (i = 0, pid = 0; i < cnp->cn_namelen && isdigit(pname[i]); ++i)
- pid = pid * 10 + pname[i] - '0';
- /* XXX assume that 8 digits is the maximum safe length for a pid */
- if (i == cnp->cn_namelen && i < 8) {
- /* see if this directory has process-dependent children */
- for (pn = pd->pn_nodes; pn->pn_type; ++pn)
- if (pn->pn_type == pfstype_procdep)
- break;
- if (pn->pn_type) {
- /* XXX pfind(0) should DTRT here */
- p = pid ? pfind(pid) : &proc0;
- if (p == NULL)
- return (ENOENT);
- if (p_can(cnp->cn_proc, p, P_CAN_SEE, NULL)) {
- /* pretend it doesn't exist */
- PROC_UNLOCK(p);
- return (ENOENT);
- }
-#if 0
- if (!pn->pn_shadow)
- pfs_create_shadow(pn, p);
- pn = pn->pn_shadow;
- PROC_UNLOCK(p);
+ /* named node */
+ for (pn = pd->pn_nodes; pn->pn_type; ++pn)
+ if (pn->pn_type == pfstype_procdir)
+ pdn = pn;
+ else if (pn->pn_name[namelen] == '\0'
+ && bcmp(pname, pn->pn_name, namelen) == 0)
goto got_pnode;
-#else
- /* not yet implemented */
- PROC_UNLOCK(p);
- return (EIO);
-#endif
- }
- }
-
- /* something else */
- for (pn = pd->pn_nodes; pn->pn_type; ++pn) {
- for (i = 0; i < cnp->cn_namelen && pn->pn_name[i]; ++i)
- if (pname[i] != pn->pn_name[i])
+
+ /* process dependent node */
+ if ((pn = pdn) != NULL) {
+ pid = 0;
+ for (pid = 0, i = 0; i < namelen && isdigit(pname[i]); ++i)
+ if ((pid = pid * 10 + pname[i] - '0') > PID_MAX)
break;
if (i == cnp->cn_namelen)
goto got_pnode;
}
-
+
return (ENOENT);
got_pnode:
if (!pn->pn_parent)
pn->pn_parent = pd;
- error = pfs_vncache_alloc(dvp->v_mount, vpp, pn);
+ error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid);
if (error)
return error;
got_vnode:
if (cnp->cn_flags & MAKEENTRY)
- cache_enter(dvp, *vpp, cnp);
+ cache_enter(vn, *vpp, cnp);
return (0);
}
@@ -217,8 +204,10 @@ static int
pfs_read(struct vop_read_args *va)
{
struct vnode *vn = va->a_vp;
- struct pfs_node *pn = vn->v_data;
+ struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
+ struct pfs_node *pn = pvd->pvd_pn;
struct uio *uio = va->a_uio;
+ struct proc *proc = NULL;
struct sbuf *sb = NULL;
char *ps;
int error, xlen;
@@ -226,11 +215,24 @@ pfs_read(struct vop_read_args *va)
if (vn->v_type != VREG)
return (EINVAL);
+ if (pvd->pvd_pid != NO_PID) {
+ if ((proc = pfind(pvd->pvd_pid)) == NULL)
+ return (EIO);
+ _PHOLD(proc);
+ PROC_UNLOCK(proc);
+ }
+
sb = sbuf_new(sb, NULL, uio->uio_offset + uio->uio_resid, 0);
- if (sb == NULL)
+ if (sb == NULL) {
+ if (proc != NULL)
+ PRELE(proc);
return (EIO);
+ }
- error = (pn->pn_func)(pn, curproc, sb);
+ error = (pn->pn_func)(curproc, proc, pn, sb);
+
+ if (proc != NULL)
+ PRELE(proc);
/* XXX we should possibly detect and handle overflows */
sbuf_finish(sb);
@@ -243,27 +245,52 @@ pfs_read(struct vop_read_args *va)
}
/*
+ * Iterate through directory entries
+ */
+static int
+pfs_iterate(struct pfs_info *pi, struct pfs_node **pn, struct proc **p)
+{
+ if ((*pn)->pn_type == pfstype_none)
+ return (-1);
+
+ if ((*pn)->pn_type != pfstype_procdir)
+ ++*pn;
+
+ while ((*pn)->pn_type == pfstype_procdir) {
+ if (*p == NULL)
+ *p = LIST_FIRST(&allproc);
+ else
+ *p = LIST_NEXT(*p, p_list);
+ if (*p != NULL)
+ return (0);
+ ++*pn;
+ }
+
+ if ((*pn)->pn_type == pfstype_none)
+ return (-1);
+
+ return (0);
+}
+
+/*
* Return directory entries.
*/
static int
pfs_readdir(struct vop_readdir_args *va)
{
struct vnode *vn = va->a_vp;
- struct pfs_info *pi;
- struct pfs_node *pd, *pn;
+ struct pfs_info *pi = (struct pfs_info *)vn->v_mount->mnt_data;
+ struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
+ struct pfs_node *pd = pvd->pvd_pn;
+ struct pfs_node *pn;
struct dirent entry;
struct uio *uio;
-#if 0
struct proc *p;
-#endif
off_t offset;
int error, i, resid;
if (vn->v_type != VDIR)
return (ENOTDIR);
- pi = (struct pfs_info *)vn->v_mount->mnt_data;
- pd = (struct pfs_node *)vn->v_data;
- pn = pd->pn_nodes;
uio = va->a_uio;
/* only allow reading entire entries */
@@ -273,23 +300,35 @@ pfs_readdir(struct vop_readdir_args *va)
return (EINVAL);
/* skip unwanted entries */
- for (; pn->pn_type && offset > 0; ++pn, offset -= PFS_DELEN)
- /* nothing */ ;
-
+ sx_slock(&allproc_lock);
+ for (pn = pd->pn_nodes, p = NULL; offset > 0; offset -= PFS_DELEN)
+ if (pfs_iterate(pi, &pn, &p) == -1)
+ break;
+
/* fill in entries */
entry.d_reclen = PFS_DELEN;
- for (; pn->pn_type && resid > 0; ++pn) {
+ while (pfs_iterate(pi, &pn, &p) != -1 && resid > 0) {
if (!pn->pn_parent)
pn->pn_parent = pd;
if (!pn->pn_fileno)
pfs_fileno_alloc(pi, pn);
- entry.d_fileno = pn->pn_fileno;
+ if (pvd->pvd_pid != NO_PID)
+ entry.d_fileno = pn->pn_fileno * NO_PID + pvd->pvd_pid;
+ else
+ entry.d_fileno = pn->pn_fileno;
/* PFS_DELEN was picked to fit PFS_NAMLEN */
for (i = 0; i < PFS_NAMELEN - 1 && pn->pn_name[i] != '\0'; ++i)
entry.d_name[i] = pn->pn_name[i];
entry.d_name[i] = 0;
entry.d_namlen = i;
switch (pn->pn_type) {
+ case pfstype_procdir:
+ KASSERT(p != NULL,
+ ("reached procdir node with p == NULL"));
+ entry.d_fileno = pn->pn_fileno * NO_PID + p->p_pid;
+ entry.d_namlen = snprintf(entry.d_name,
+ PFS_NAMELEN, "%d", p->p_pid);
+ /* fall through */
case pfstype_root:
case pfstype_dir:
case pfstype_this:
@@ -302,32 +341,19 @@ pfs_readdir(struct vop_readdir_args *va)
case pfstype_symlink:
entry.d_type = DT_LNK;
break;
- case pfstype_procdep:
- /* don't handle process-dependent nodes here */
- continue;
default:
+ sx_sunlock(&allproc_lock);
panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type);
}
- if ((error = uiomove((caddr_t)&entry, PFS_DELEN, uio)))
+ if ((error = uiomove((caddr_t)&entry, PFS_DELEN, uio))) {
+ sx_sunlock(&allproc_lock);
return (error);
+ }
offset += PFS_DELEN;
resid -= PFS_DELEN;
}
-#if 0
- for (pn = pd->pn_nodes; pn->pn_type && resid > 0; ++pn) {
- if (pn->pn_type != pfstype_procdep)
- continue;
-
- sx_slock(&allproc_lock);
- p = LIST_FIRST(&allproc);
-
- sx_sunlock(&allproc_lock);
- offset += PFS_DELEN;
- resid -= PFS_DELEN;
- break;
- }
-#endif
-
+
+ sx_sunlock(&allproc_lock);
uio->uio_offset += offset;
return (0);
}
@@ -339,8 +365,10 @@ static int
pfs_readlink(struct vop_readlink_args *va)
{
struct vnode *vn = va->a_vp;
- struct pfs_node *pn = vn->v_data;
+ struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data;
+ struct pfs_node *pn = pvd->pvd_pn;
struct uio *uio = va->a_uio;
+ struct proc *proc = NULL;
char buf[MAXPATHLEN], *ps;
struct sbuf sb;
int error, xlen;
@@ -348,10 +376,20 @@ pfs_readlink(struct vop_readlink_args *va)
if (vn->v_type != VLNK)
return (EINVAL);
+ if (pvd->pvd_pid != NO_PID) {
+ if ((proc = pfind(pvd->pvd_pid)) == NULL)
+ return (EIO);
+ _PHOLD(proc);
+ PROC_UNLOCK(proc);
+ }
+
/* sbuf_new() can't fail with a static buffer */
sbuf_new(&sb, buf, sizeof buf, 0);
- error = (pn->pn_func)(pn, curproc, &sb);
+ error = (pn->pn_func)(curproc, proc, pn, &sb);
+
+ if (proc != NULL)
+ PRELE(proc);
/* XXX we should detect and handle overflows */
sbuf_finish(&sb);
@@ -378,8 +416,9 @@ pfs_reclaim(struct vop_reclaim_args *va)
static int
pfs_setattr(struct vop_setattr_args *va)
{
- if (va->a_vap->va_flags != VNOVAL)
+ if (va->a_vap->va_flags != (u_long)VNOVAL)
return (EOPNOTSUPP);
+ /* XXX it's a bit more complex than that, really... */
return (0);
}
OpenPOWER on IntegriCloud