Add a PUFFS_UNMOUNT server->kernel request, which causes the kernel

to initiate self destruct, i.e. unmount(MNT_FORCE).  This, however,
is a semi-controlled self-destruct, since all caches are flushed
before the (possibly) violent unmount takes place.
This commit is contained in:
pooka 2010-01-07 22:45:31 +00:00
parent e9d13d47e1
commit d728f5380d
3 changed files with 52 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_msgif.c,v 1.76 2009/12/07 20:57:55 pooka Exp $ */
/* $NetBSD: puffs_msgif.c,v 1.77 2010/01/07 22:45:31 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.76 2009/12/07 20:57:55 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.77 2010/01/07 22:45:31 pooka Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@ -855,6 +855,7 @@ puffs_msgif_dispatch(void *this, struct putter_hdr *pth)
DPRINTF(("dispatch: vn/vfs message 0x%x\n", preq->preq_optype));
puffsop_msg(pmp, preq);
break;
case PUFFSOP_FLUSH: /* process in sop thread */
{
struct puffs_flush *pf;
@ -877,6 +878,23 @@ puffs_msgif_dispatch(void *this, struct putter_hdr *pth)
mutex_exit(&pmp->pmp_sopmtx);
break;
}
case PUFFSOP_UNMOUNT: /* process in sop thread */
{
DPRINTF(("dispatch: unmount 0x%x\n", preq->preq_optype));
psopr = kmem_alloc(sizeof(*psopr), KM_SLEEP);
psopr->psopr_preq = *preq;
psopr->psopr_sopreq = PUFFS_SOPREQ_UNMOUNT;
mutex_enter(&pmp->pmp_sopmtx);
TAILQ_INSERT_TAIL(&pmp->pmp_sopreqs, psopr, psopr_entries);
cv_signal(&pmp->pmp_sopcv);
mutex_exit(&pmp->pmp_sopmtx);
break;
}
default:
DPRINTF(("dispatch: invalid class 0x%x\n", preq->preq_opclass));
puffs_msg_sendresp(pmp, preq, EOPNOTSUPP);
@ -897,8 +915,10 @@ void
puffs_sop_thread(void *arg)
{
struct puffs_mount *pmp = arg;
struct mount *mp = PMPTOMP(pmp);
struct puffs_sopreq *psopr;
bool keeprunning;
bool unmountme = false;
mutex_enter(&pmp->pmp_sopmtx);
for (keeprunning = true; keeprunning; ) {
@ -914,6 +934,18 @@ puffs_sop_thread(void *arg)
case PUFFS_SOPREQ_FLUSH:
puffsop_flush(pmp, &psopr->psopr_pf);
break;
case PUFFS_SOPREQ_UNMOUNT:
puffs_msg_sendresp(pmp, &sopreq->psopr_preq, 0);
unmountme = true;
keeprunning = false;
/*
* We know the mountpoint is still alive because
* the thread that is us (poetic?) is still alive.
*/
atomic_inc_uint((unsigned int*)&mp->mnt_refcnt);
break;
}
kmem_free(psopr, sizeof(*psopr));
@ -921,8 +953,7 @@ puffs_sop_thread(void *arg)
}
/*
* Purge remaining ops. could send error, but that is highly
* unlikely to reach the caller.
* Purge remaining ops. could send error, but ...
*/
while ((psopr = TAILQ_FIRST(&pmp->pmp_sopreqs)) != NULL) {
TAILQ_REMOVE(&pmp->pmp_sopreqs, psopr, psopr_entries);
@ -932,9 +963,21 @@ puffs_sop_thread(void *arg)
}
pmp->pmp_sopthrcount--;
cv_signal(&pmp->pmp_sopcv);
cv_broadcast(&pmp->pmp_sopcv);
mutex_exit(&pmp->pmp_sopmtx); /* not allowed to access fs after this */
/*
* If unmount was requested, we can now safely do it here, since
* our context is dead from the point-of-view of puffs_unmount()
* and we are just another thread. dounmount() makes internally
* sure that VFS_UNMOUNT() isn't called reentrantly and that it
* is eventually completed.
*/
if (unmountme) {
(void)dounmount(mp, MNT_FORCE, curlwp);
vfs_destroy(mp);
}
kthread_exit(0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_msgif.h,v 1.68 2009/10/17 23:22:04 pooka Exp $ */
/* $NetBSD: puffs_msgif.h,v 1.69 2010/01/07 22:45:31 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@ -52,6 +52,7 @@
#define PUFFSOP_ERROR 0x04 /* only kernel-> */
#define PUFFSOP_FLUSH 0x05 /* ->kernel */
#define PUFFSOP_SUSPEND 0x06 /* ->kernel */
#define PUFFSOP_UNMOUNT 0x07 /* ->kernel */
#define PUFFSOPFLAG_FAF 0x10 /* fire-and-forget */
#define PUFFSOPFLAG_ISRESPONSE 0x20 /* req is actually a resp */

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_sys.h,v 1.73 2009/12/07 20:57:55 pooka Exp $ */
/* $NetBSD: puffs_sys.h,v 1.74 2010/01/07 22:45:31 pooka Exp $ */
/*
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
@ -101,6 +101,7 @@ struct puffs_newcookie {
enum puffs_sopreqtype {
PUFFS_SOPREQ_EXIT,
PUFFS_SOPREQ_FLUSH,
PUFFS_SOPREQ_UNMOUNT,
};
struct puffs_sopreq {