Forcibly remove the cached items from pseudofs vncache on module unload.

If some process' nodes were accessed using procfs and the process
cannot exit properly at the time modunload event is reported to the
pseudofs-backed filesystem, the assertion in pfs_vncache_unload() is
triggered.  Assertion is correct, the cache should be cleaned.

Approved by:	des (pseudofs maintainer)
Reported and tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2017-01-09 20:14:18 +00:00
parent 3ac0e4769e
commit d72b4d3918

View File

@ -51,6 +51,7 @@ static struct mtx pfs_vncache_mutex;
static struct pfs_vdata *pfs_vncache;
static eventhandler_tag pfs_exit_tag;
static void pfs_exit(void *arg, struct proc *p);
static void pfs_purge_locked(struct pfs_node *pn, bool force);
static SYSCTL_NODE(_vfs_pfs, OID_AUTO, vncache, CTLFLAG_RW, 0,
"pseudofs vnode cache");
@ -97,6 +98,9 @@ pfs_vncache_unload(void)
{
EVENTHANDLER_DEREGISTER(process_exit, pfs_exit_tag);
mtx_lock(&pfs_vncache_mutex);
pfs_purge_locked(NULL, true);
mtx_unlock(&pfs_vncache_mutex);
KASSERT(pfs_vncache_entries == 0,
("%d vncache entries remaining", pfs_vncache_entries));
mtx_destroy(&pfs_vncache_mutex);
@ -272,7 +276,7 @@ pfs_vncache_free(struct vnode *vp)
* used to implement the cache.
*/
static void
pfs_purge_locked(struct pfs_node *pn)
pfs_purge_locked(struct pfs_node *pn, bool force)
{
struct pfs_vdata *pvd;
struct vnode *vnp;
@ -280,7 +284,8 @@ pfs_purge_locked(struct pfs_node *pn)
mtx_assert(&pfs_vncache_mutex, MA_OWNED);
pvd = pfs_vncache;
while (pvd != NULL) {
if (pvd->pvd_dead || (pn != NULL && pvd->pvd_pn == pn)) {
if (force || pvd->pvd_dead ||
(pn != NULL && pvd->pvd_pn == pn)) {
vnp = pvd->pvd_vnode;
vhold(vnp);
mtx_unlock(&pfs_vncache_mutex);
@ -301,7 +306,7 @@ pfs_purge(struct pfs_node *pn)
{
mtx_lock(&pfs_vncache_mutex);
pfs_purge_locked(pn);
pfs_purge_locked(pn, false);
mtx_unlock(&pfs_vncache_mutex);
}
@ -321,6 +326,6 @@ pfs_exit(void *arg, struct proc *p)
if (pvd->pvd_pid == p->p_pid)
dead = pvd->pvd_dead = 1;
if (dead)
pfs_purge_locked(NULL);
pfs_purge_locked(NULL, false);
mtx_unlock(&pfs_vncache_mutex);
}