Kill suspend support. It was never implemented correctly:

* it depended on the biglock (in a very cruel way)
  * it was attached to userspace transactions rather than logical
    fs operations

(If someone wants to revisit it some day, most of the stuff can be
reused from cvs history)
This commit is contained in:
pooka 2009-11-05 19:42:44 +00:00
parent 1f5ddb4eb6
commit 1d8c6c1718
5 changed files with 25 additions and 317 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_msgif.c,v 1.73 2009/03/18 10:22:42 cegger Exp $ */
/* $NetBSD: puffs_msgif.c,v 1.74 2009/11/05 19:42:44 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@ -30,11 +30,10 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.73 2009/03/18 10:22:42 cegger Exp $");
__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.74 2009/11/05 19:42:44 pooka Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
#include <sys/fstrans.h>
#include <sys/kmem.h>
#include <sys/kthread.h>
#include <sys/lock.h>
@ -366,38 +365,7 @@ puffs_msg_enqueue(struct puffs_mount *pmp, struct puffs_msgpark *park)
}
}
/*
* test for suspension lock.
*
* Note that we *DO NOT* keep the lock, since that might block
* lock acquiring PLUS it would give userlandia control over
* the lock. The operation queue enforces a strict ordering:
* when the fs server gets in the op stream, it knows things
* are in order. The kernel locks can't guarantee that for
* userspace, in any case.
*
* BUT: this presents a problem for ops which have a consistency
* clause based on more than one operation. Unfortunately such
* operations (read, write) do not reliably work yet.
*
* Ya, Ya, it's wrong wong wrong, me be fixink this someday.
*
* XXX: and there is one more problem. We sometimes need to
* take a lazy lock in case the fs is suspending and we are
* executing as the fs server context. This might happen
* e.g. in the case that the user server triggers a reclaim
* in the kernel while the fs is suspending. It's not a very
* likely event, but it needs to be fixed some day.
*/
/*
* MOREXXX: once PUFFS_WCACHEINFO is enabled, we can't take
* the mutex here, since getpages() might be called locked.
*/
fstrans_start(mp, FSTRANS_NORMAL);
mutex_enter(&pmp->pmp_lock);
fstrans_done(mp);
if (pmp->pmp_status != PUFFSTAT_RUNNING) {
mutex_exit(&pmp->pmp_lock);
park->park_flags |= PARKFLAG_HASERROR;
@ -432,7 +400,6 @@ int
puffs_msg_wait(struct puffs_mount *pmp, struct puffs_msgpark *park)
{
struct puffs_req *preq = park->park_preq; /* XXX: hmmm */
struct mount *mp = PMPTOMP(pmp);
int error = 0;
int rv;
@ -504,20 +471,6 @@ puffs_msg_wait(struct puffs_mount *pmp, struct puffs_msgpark *park)
mutex_exit(&park->park_mtx);
}
/*
* retake the lock and release. This makes sure (haha,
* I'm humorous) that we don't process the same vnode in
* multiple threads due to the locks hacks we have in
* puffs_lock(). In reality this is well protected by
* the biglock, but once that's gone, well, hopefully
* this will be fixed for real. (and when you read this
* comment in 2017 and subsequently barf, my condolences ;).
*/
if (rv == 0 && !fstrans_is_owner(mp)) {
fstrans_start(mp, FSTRANS_NORMAL);
fstrans_done(mp);
}
skipwait:
mutex_enter(&pmp->pmp_lock);
puffs_mp_release(pmp);
@ -799,63 +752,6 @@ puffsop_msg(void *this, struct puffs_req *preq)
puffs_msgpark_release1(park, 2);
}
/*
* helpers
*/
static void
dosuspendresume(void *arg)
{
struct puffs_mount *pmp = arg;
struct mount *mp;
int rv;
mp = PMPTOMP(pmp);
/*
* XXX? does this really do any good or is it just
* paranoid stupidity? or stupid paranoia?
*/
if (mp->mnt_iflag & IMNT_UNMOUNT) {
printf("puffs dosuspendresume(): detected suspend on "
"unmounting fs\n");
goto out;
}
/* Do the dance. Allow only one concurrent suspend */
rv = vfs_suspend(PMPTOMP(pmp), 1);
if (rv == 0)
vfs_resume(PMPTOMP(pmp));
out:
mutex_enter(&pmp->pmp_lock);
KASSERT(pmp->pmp_suspend == 1);
pmp->pmp_suspend = 0;
puffs_mp_release(pmp);
mutex_exit(&pmp->pmp_lock);
kthread_exit(0);
}
static void
puffsop_suspend(struct puffs_mount *pmp)
{
int rv = 0;
mutex_enter(&pmp->pmp_lock);
if (pmp->pmp_suspend || pmp->pmp_status != PUFFSTAT_RUNNING) {
rv = EBUSY;
} else {
puffs_mp_reference(pmp);
pmp->pmp_suspend = 1;
}
mutex_exit(&pmp->pmp_lock);
if (rv)
return;
rv = kthread_create(PRI_NONE, 0, NULL, dosuspendresume,
pmp, NULL, "puffsusp");
/* XXX: "return" rv */
}
static void
puffsop_flush(struct puffs_mount *pmp, struct puffs_flush *pf)
{
@ -949,6 +845,7 @@ puffs_msgif_dispatch(void *this, struct putter_hdr *pth)
{
struct puffs_mount *pmp = this;
struct puffs_req *preq = (struct puffs_req *)pth;
int rv = 0;
/* XXX: need to send error to userspace */
if (pth->pth_framelen < sizeof(struct puffs_req)) {
@ -968,7 +865,7 @@ puffs_msgif_dispatch(void *this, struct putter_hdr *pth)
break;
case PUFFSOP_SUSPEND:
DPRINTF(("dispatch: suspend\n"));
puffsop_suspend(pmp);
rv = EOPNOTSUPP;
break;
default:
DPRINTF(("dispatch: invalid class 0x%x\n", preq->preq_opclass));
@ -976,7 +873,7 @@ puffs_msgif_dispatch(void *this, struct putter_hdr *pth)
break;
}
return 0;
return rv;
}
int

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_node.c,v 1.14 2009/09/30 18:19:17 pooka Exp $ */
/* $NetBSD: puffs_node.c,v 1.15 2009/11/05 19:42:44 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_node.c,v 1.14 2009/09/30 18:19:17 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.15 2009/11/05 19:42:44 pooka Exp $");
#include <sys/param.h>
#include <sys/hash.h>
@ -93,7 +93,6 @@ puffs_getvnode(struct mount *mp, puffs_cookie_t ck, enum vtype type,
error = getnewvnode(VT_PUFFS, mp, puffs_vnodeop_p, &vp);
if (error)
goto bad;
vp->v_vnlock = NULL;
vp->v_type = type;
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_sys.h,v 1.71 2009/11/05 19:22:57 pooka Exp $ */
/* $NetBSD: puffs_sys.h,v 1.72 2009/11/05 19:42:44 pooka Exp $ */
/*
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
@ -153,7 +153,7 @@ struct puffs_mount {
#define PNODE_NOREFS 0x01 /* no backend reference */
#define PNODE_DYING 0x02 /* NOREFS + inactive */
#define PNODE_SUSPEND 0x04 /* issue all operations as FAF */
#define PNODE_FAF 0x04 /* issue all operations as FAF */
#define PNODE_DOINACT 0x08 /* if inactive-on-demand, call inactive */
#define PNODE_METACACHE_ATIME 0x10 /* cache atime metadata */

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_vfsops.c,v 1.82 2009/03/18 10:22:42 cegger Exp $ */
/* $NetBSD: puffs_vfsops.c,v 1.83 2009/11/05 19:42:44 pooka Exp $ */
/*
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.82 2009/03/18 10:22:42 cegger Exp $");
__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.83 2009/11/05 19:42:44 pooka Exp $");
#include <sys/param.h>
#include <sys/mount.h>
@ -40,7 +40,6 @@ __KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.82 2009/03/18 10:22:42 cegger Exp
#include <sys/vnode.h>
#include <sys/dirent.h>
#include <sys/kauth.h>
#include <sys/fstrans.h>
#include <sys/proc.h>
#include <sys/module.h>
@ -109,9 +108,6 @@ puffs_vfsop_mount(struct mount *mp, const char *path, void *data,
if (!data)
return EINVAL;
error = fstrans_mount(mp);
if (error)
return error;
args = (struct puffs_kargs *)data;
/* devel phase */
@ -224,7 +220,6 @@ puffs_vfsop_mount(struct mount *mp, const char *path, void *data,
mp->mnt_dev_bshift = DEV_BSHIFT;
mp->mnt_flag &= ~MNT_LOCAL; /* we don't really know, so ... */
mp->mnt_data = pmp;
mp->mnt_iflag |= IMNT_HAS_TRANS;
pmp->pmp_status = PUFFSTAT_MOUNTING;
pmp->pmp_mp = mp;
@ -267,8 +262,6 @@ puffs_vfsop_mount(struct mount *mp, const char *path, void *data,
vfs_getnewfsid(mp);
out:
if (error)
fstrans_unmount(mp);
if (error && pmp && pmp->pmp_pnodehash)
kmem_free(pmp->pmp_pnodehash, BUCKETALLOC(pmp->pmp_npnodehash));
if (error && pmp)
@ -365,7 +358,6 @@ puffs_vfsop_unmount(struct mount *mp, int mntflags)
cv_destroy(&pmp->pmp_msg_waiter_cv);
mutex_destroy(&pmp->pmp_lock);
fstrans_unmount(mp);
kmem_free(pmp->pmp_pnodehash, BUCKETALLOC(pmp->pmp_npnodehash));
kmem_free(pmp, sizeof(struct puffs_mount));
error = 0;
@ -436,17 +428,12 @@ puffs_vfsop_statvfs(struct mount *mp, struct statvfs *sbp)
}
static int
pageflush(struct mount *mp, kauth_cred_t cred, int waitfor, int suspending)
pageflush(struct mount *mp, kauth_cred_t cred, int waitfor)
{
struct puffs_node *pn;
struct vnode *vp, *mvp;
int error, rv;
KASSERT(((waitfor == MNT_WAIT) && suspending) == 0);
KASSERT((suspending == 0)
|| (fstrans_is_owner(mp)
&& fstrans_getstate(mp) == FSTRANS_SUSPENDING));
error = 0;
/* Allocate a marker vnode. */
@ -489,9 +476,6 @@ pageflush(struct mount *mp, kauth_cred_t cred, int waitfor, int suspending)
* dounmount(), when we are wait-flushing all the dirty
* vnodes through other routes in any case. So there,
* sync() doesn't actually sync. Happy now?
*
* NOTE: if we're suspending, vget() does NOT lock.
* See puffs_lock() for details.
*/
rv = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
if (rv) {
@ -503,36 +487,16 @@ pageflush(struct mount *mp, kauth_cred_t cred, int waitfor, int suspending)
continue;
}
/*
* Thread information to puffs_strategy() through the
* pnode flags: we want to issue the putpages operations
* as FAF if we're suspending, since it's very probable
* that our execution context is that of the userspace
* daemon. We can do this because:
* + we send the "going to suspend" prior to this part
* + if any of the writes fails in userspace, it's the
* file system server's problem to decide if this was a
* failed snapshot when it gets the "snapshot complete"
* notification.
* + if any of the writes fail in the kernel already, we
* immediately fail *and* notify the user server of
* failure.
*
* We also do FAFs if we're called from the syncer. This
* is just general optimization for trickle sync: no need
* to really guarantee that the stuff ended on backing
* storage.
* TODO: Maybe also hint the user server of this twist?
*/
if (suspending || waitfor == MNT_LAZY) {
/* hmm.. is the FAF thing entirely sensible? */
if (waitfor == MNT_LAZY) {
mutex_enter(&vp->v_interlock);
pn->pn_stat |= PNODE_SUSPEND;
pn->pn_stat |= PNODE_FAF;
mutex_exit(&vp->v_interlock);
}
rv = VOP_FSYNC(vp, cred, waitfor, 0, 0);
if (suspending || waitfor == MNT_LAZY) {
if (waitfor == MNT_LAZY) {
mutex_enter(&vp->v_interlock);
pn->pn_stat &= ~PNODE_SUSPEND;
pn->pn_stat &= ~PNODE_FAF;
mutex_exit(&vp->v_interlock);
}
if (rv)
@ -553,7 +517,7 @@ puffs_vfsop_sync(struct mount *mp, int waitfor, struct kauth_cred *cred)
struct puffs_mount *pmp = MPTOPUFFSMP(mp);
int error, rv;
error = pageflush(mp, cred, waitfor, 0);
error = pageflush(mp, cred, waitfor);
/* sync fs */
PUFFS_MSG_ALLOC(vfs, sync);
@ -732,79 +696,6 @@ puffs_vfsop_snapshot(struct mount *mp, struct vnode *vp, struct timespec *ts)
return EOPNOTSUPP;
}
int
puffs_vfsop_suspendctl(struct mount *mp, int cmd)
{
PUFFS_MSG_VARS(vfs, suspend);
struct puffs_mount *pmp;
int error;
pmp = MPTOPUFFSMP(mp);
switch (cmd) {
case SUSPEND_SUSPEND:
DPRINTF(("puffs_suspendctl: suspending\n"));
if ((error = fstrans_setstate(mp, FSTRANS_SUSPENDING)) != 0)
break;
PUFFS_MSG_ALLOC(vfs, suspend);
puffs_msg_setfaf(park_suspend);
suspend_msg->pvfsr_status = PUFFS_SUSPEND_START;
puffs_msg_setinfo(park_suspend, PUFFSOP_VFS,
PUFFS_VFS_SUSPEND, NULL);
puffs_msg_enqueue(pmp, park_suspend);
PUFFS_MSG_RELEASE(suspend);
error = pageflush(mp, FSCRED, 0, 1);
if (error == 0)
error = fstrans_setstate(mp, FSTRANS_SUSPENDED);
if (error != 0) {
PUFFS_MSG_ALLOC(vfs, suspend);
puffs_msg_setfaf(park_suspend);
suspend_msg->pvfsr_status = PUFFS_SUSPEND_ERROR;
puffs_msg_setinfo(park_suspend, PUFFSOP_VFS,
PUFFS_VFS_SUSPEND, NULL);
puffs_msg_enqueue(pmp, park_suspend);
PUFFS_MSG_RELEASE(suspend);
(void) fstrans_setstate(mp, FSTRANS_NORMAL);
break;
}
PUFFS_MSG_ALLOC(vfs, suspend);
puffs_msg_setfaf(park_suspend);
suspend_msg->pvfsr_status = PUFFS_SUSPEND_SUSPENDED;
puffs_msg_setinfo(park_suspend, PUFFSOP_VFS,
PUFFS_VFS_SUSPEND, NULL);
puffs_msg_enqueue(pmp, park_suspend);
PUFFS_MSG_RELEASE(suspend);
break;
case SUSPEND_RESUME:
DPRINTF(("puffs_suspendctl: resume\n"));
error = 0;
(void) fstrans_setstate(mp, FSTRANS_NORMAL);
PUFFS_MSG_ALLOC(vfs, suspend);
puffs_msg_setfaf(park_suspend);
suspend_msg->pvfsr_status = PUFFS_SUSPEND_RESUME;
puffs_msg_setinfo(park_suspend, PUFFSOP_VFS,
PUFFS_VFS_SUSPEND, NULL);
puffs_msg_enqueue(pmp, park_suspend);
PUFFS_MSG_RELEASE(suspend);
break;
default:
error = EINVAL;
break;
}
DPRINTF(("puffs_suspendctl: return %d\n", error));
return error;
}
const struct vnodeopv_desc * const puffs_vnodeopv_descs[] = {
&puffs_vnodeop_opv_desc,
&puffs_specop_opv_desc,
@ -832,7 +723,7 @@ struct vfsops puffs_vfsops = {
NULL, /* mountroot */
puffs_vfsop_snapshot, /* snapshot */
vfs_stdextattrctl, /* extattrctl */
puffs_vfsop_suspendctl, /* suspendctl */
(void *)eopnotsupp, /* suspendctl */
genfs_renamelock_enter,
genfs_renamelock_exit,
(void *)eopnotsupp,

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_vnops.c,v 1.137 2009/11/05 19:22:57 pooka Exp $ */
/* $NetBSD: puffs_vnops.c,v 1.138 2009/11/05 19:42:44 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@ -30,11 +30,10 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.137 2009/11/05 19:22:57 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.138 2009/11/05 19:42:44 pooka Exp $");
#include <sys/param.h>
#include <sys/buf.h>
#include <sys/fstrans.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/namei.h>
@ -91,16 +90,9 @@ int puffs_vnop_fifo_write(void *);
int puffs_vnop_checkop(void *);
#if 0
#define puffs_lock genfs_lock
#define puffs_unlock genfs_unlock
#define puffs_islocked genfs_islocked
#else
int puffs_vnop_lock(void *);
int puffs_vnop_unlock(void *);
int puffs_vnop_islocked(void *);
#endif
#define puffs_vnop_lock genfs_lock
#define puffs_vnop_unlock genfs_unlock
#define puffs_vnop_islocked genfs_islocked
int (**puffs_vnodeop_p)(void *);
const struct vnodeopv_entry_desc puffs_vnodeop_entries[] = {
@ -2198,7 +2190,7 @@ puffs_vnop_strategy(void *v)
mutex_enter(&vp->v_interlock);
if (vp->v_iflag & VI_XLOCK)
dofaf = 1;
if (pn->pn_stat & PNODE_SUSPEND)
if (pn->pn_stat & PNODE_FAF)
dofaf = 1;
mutex_exit(&vp->v_interlock);
}
@ -2557,77 +2549,6 @@ puffs_vnop_getpages(void *v)
return error;
}
int
puffs_vnop_lock(void *v)
{
struct vop_lock_args /* {
struct vnode *a_vp;
int a_flags;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct mount *mp = vp->v_mount;
int flags = ap->a_flags;
#if 0
DPRINTF(("puffs_lock: lock %p, args 0x%x\n", vp, ap->a_flags));
#endif
if (flags & LK_INTERLOCK) {
mutex_exit(&vp->v_interlock);
flags &= ~LK_INTERLOCK;
}
/*
* XXX: this avoids deadlocking when we're suspending.
* e.g. some ops holding the vnode lock might be blocked for
* the vfs transaction lock so we'd deadlock.
*
* Now once again this is skating on the thin ice of modern life,
* since we are breaking the consistency guarantee provided
* _to the user server_ by vnode locking. Hopefully this will
* get fixed soon enough by getting rid of the dependency on
* vnode locks alltogether.
*/
if (fstrans_is_owner(mp) && fstrans_getstate(mp) == FSTRANS_SUSPENDING){
return 0;
}
return vlockmgr(&vp->v_lock, flags);
}
int
puffs_vnop_unlock(void *v)
{
struct vop_unlock_args /* {
struct vnode *a_vp;
int a_flags;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct mount *mp = vp->v_mount;
#if 0
DPRINTF(("puffs_unlock: lock %p, args 0x%x\n", vp, ap->a_flags));
#endif
/* XXX: see puffs_lock() */
if (fstrans_is_owner(mp) && fstrans_getstate(mp) == FSTRANS_SUSPENDING){
return 0;
}
return vlockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE);
}
int
puffs_vnop_islocked(void *v)
{
struct vop_islocked_args *ap = v;
int rv;
rv = vlockstatus(&ap->a_vp->v_lock);
return rv;
}
/*
* spec & fifo. These call the miscfs spec and fifo vectors, but issue
* FAF update information for the puffs node first.