Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/pseudofs/pseudofs_vnops.c
Show First 20 Lines • Show All 699 Lines • ▼ Show 20 Lines | |||||
* Iterate through directory entries | * Iterate through directory entries | ||||
*/ | */ | ||||
static int | static int | ||||
pfs_iterate(struct thread *td, struct proc *proc, struct pfs_node *pd, | 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) | ||||
{ | { | ||||
int visible; | int visible; | ||||
sx_assert(&allproc_lock, SX_SLOCKED); | sx_assert(&V_allproc_lock, SX_SLOCKED); | ||||
pfs_assert_owned(pd); | pfs_assert_owned(pd); | ||||
again: | again: | ||||
if (*pn == NULL) { | if (*pn == NULL) { | ||||
/* first node */ | /* first node */ | ||||
*pn = pd->pn_nodes; | *pn = pd->pn_nodes; | ||||
} else if ((*pn)->pn_type != pfstype_procdir) { | } else if ((*pn)->pn_type != pfstype_procdir) { | ||||
/* next node */ | /* next node */ | ||||
*pn = (*pn)->pn_next; | *pn = (*pn)->pn_next; | ||||
} | } | ||||
if (*pn != NULL && (*pn)->pn_type == pfstype_procdir) { | if (*pn != NULL && (*pn)->pn_type == pfstype_procdir) { | ||||
/* | |||||
* Operate on current vps instance only. | |||||
* We must not iterate over all vps as duplicate process space | |||||
* would not work at all and leak a lot of information. | |||||
*/ | |||||
/* next process */ | /* next process */ | ||||
if (*p == NULL) | if (*p == NULL) | ||||
*p = LIST_FIRST(&allproc); | *p = LIST_FIRST(&V_allproc); | ||||
else | else | ||||
*p = LIST_NEXT(*p, p_list); | *p = LIST_NEXT(*p, p_list); | ||||
/* out of processes: next node */ | /* out of processes: next node */ | ||||
if (*p == NULL) | if (*p == NULL) | ||||
*pn = (*pn)->pn_next; | *pn = (*pn)->pn_next; | ||||
else | else | ||||
PROC_LOCK(*p); | PROC_LOCK(*p); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | pfs_readdir(struct vop_readdir_args *va) | ||||
offset = uio->uio_offset; | offset = uio->uio_offset; | ||||
resid = uio->uio_resid; | resid = uio->uio_resid; | ||||
if (offset < 0 || offset % PFS_DELEN != 0 || | if (offset < 0 || offset % PFS_DELEN != 0 || | ||||
(resid && resid < PFS_DELEN)) | (resid && resid < PFS_DELEN)) | ||||
PFS_RETURN (EINVAL); | PFS_RETURN (EINVAL); | ||||
if (resid == 0) | if (resid == 0) | ||||
PFS_RETURN (0); | PFS_RETURN (0); | ||||
sx_slock(&allproc_lock); | sx_slock(&V_allproc_lock); | ||||
pfs_lock(pd); | pfs_lock(pd); | ||||
/* check if the directory is visible to the caller */ | /* check if the directory is visible to the caller */ | ||||
if (!pfs_visible(curthread, pd, pid, true, &proc)) { | if (!pfs_visible(curthread, pd, pid, true, &proc)) { | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&V_allproc_lock); | ||||
pfs_unlock(pd); | pfs_unlock(pd); | ||||
PFS_RETURN (ENOENT); | PFS_RETURN (ENOENT); | ||||
} | } | ||||
KASSERT(pid == NO_PID || proc != NULL, | KASSERT(pid == NO_PID || proc != NULL, | ||||
("%s(): no process for pid %lu", __func__, (unsigned long)pid)); | ("%s(): no process for pid %lu", __func__, (unsigned long)pid)); | ||||
/* skip unwanted entries */ | /* skip unwanted entries */ | ||||
for (pn = NULL, p = NULL; offset > 0; offset -= PFS_DELEN) { | 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) == -1) { | ||||
/* nothing left... */ | /* nothing left... */ | ||||
if (proc != NULL) | if (proc != NULL) | ||||
PROC_UNLOCK(proc); | PROC_UNLOCK(proc); | ||||
pfs_unlock(pd); | pfs_unlock(pd); | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&V_allproc_lock); | ||||
PFS_RETURN (0); | PFS_RETURN (0); | ||||
} | } | ||||
} | } | ||||
/* fill in entries */ | /* fill in entries */ | ||||
while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 && | while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 && | ||||
resid >= PFS_DELEN) { | resid >= PFS_DELEN) { | ||||
if ((pfsent = malloc(sizeof(struct pfsentry), M_IOV, | if ((pfsent = malloc(sizeof(struct pfsentry), M_IOV, | ||||
Show All 33 Lines | while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 && | ||||
PFS_TRACE(("%s", pfsent->entry.d_name)); | PFS_TRACE(("%s", pfsent->entry.d_name)); | ||||
STAILQ_INSERT_TAIL(&lst, pfsent, link); | STAILQ_INSERT_TAIL(&lst, pfsent, link); | ||||
offset += PFS_DELEN; | offset += PFS_DELEN; | ||||
resid -= PFS_DELEN; | resid -= PFS_DELEN; | ||||
} | } | ||||
if (proc != NULL) | if (proc != NULL) | ||||
PROC_UNLOCK(proc); | PROC_UNLOCK(proc); | ||||
pfs_unlock(pd); | pfs_unlock(pd); | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&V_allproc_lock); | ||||
i = 0; | i = 0; | ||||
STAILQ_FOREACH_SAFE(pfsent, &lst, link, pfsent2) { | STAILQ_FOREACH_SAFE(pfsent, &lst, link, pfsent2) { | ||||
if (error == 0) | if (error == 0) | ||||
error = uiomove(&pfsent->entry, PFS_DELEN, uio); | error = uiomove(&pfsent->entry, PFS_DELEN, uio); | ||||
free(pfsent, M_IOV); | free(pfsent, M_IOV); | ||||
i++; | i++; | ||||
} | } | ||||
PFS_TRACE(("%ju bytes", (uintmax_t)(i * PFS_DELEN))); | PFS_TRACE(("%ju bytes", (uintmax_t)(i * PFS_DELEN))); | ||||
▲ Show 20 Lines • Show All 190 Lines • Show Last 20 Lines |