Locking a layer vnode is racy as it may become reclaimed before
calling the operation on the lower vnode. Replace vi_lock with a rw_obj and change layered file systems to share the lock with the lower vnode. Layered file systems now use genfs_lock()/_unlock/_islocked(). Welcome to 7.99.67
This commit is contained in:
parent
799c5cfefa
commit
d0dc55acf0
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_vnode.c,v 1.80 2017/03/30 09:15:51 hannken Exp $ */
|
||||
/* $NetBSD: vfs_vnode.c,v 1.81 2017/03/30 09:16:52 hannken Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
|
||||
@ -156,7 +156,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.80 2017/03/30 09:15:51 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.81 2017/03/30 09:16:52 hannken Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -415,6 +415,21 @@ vnis_marker(vnode_t *vp)
|
||||
return (VNODE_TO_VIMPL(vp)->vi_state == VS_MARKER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set vnode to share another vnodes lock.
|
||||
*/
|
||||
void
|
||||
vshare_lock(vnode_t *vp, vnode_t *src_vp)
|
||||
{
|
||||
vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
|
||||
vnode_impl_t *src_vip = VNODE_TO_VIMPL(src_vp);
|
||||
krwlock_t *oldlock = vip->vi_lock;
|
||||
|
||||
rw_obj_hold(src_vip->vi_lock);
|
||||
vip->vi_lock = src_vip->vi_lock;
|
||||
rw_obj_free(oldlock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the lru list this node should be on.
|
||||
*/
|
||||
@ -1066,7 +1081,7 @@ vcache_alloc(void)
|
||||
vip = pool_cache_get(vcache_pool, PR_WAITOK);
|
||||
memset(vip, 0, sizeof(*vip));
|
||||
|
||||
rw_init(&vip->vi_lock);
|
||||
vip->vi_lock = rw_obj_alloc();
|
||||
/* SLIST_INIT(&vip->vi_hash); */
|
||||
/* LIST_INIT(&vip->vi_nclist); */
|
||||
/* LIST_INIT(&vip->vi_dnclist); */
|
||||
@ -1128,7 +1143,7 @@ vcache_free(vnode_impl_t *vip)
|
||||
if (vp->v_type == VBLK || vp->v_type == VCHR)
|
||||
spec_node_destroy(vp);
|
||||
|
||||
rw_destroy(&vip->vi_lock);
|
||||
rw_obj_free(vip->vi_lock);
|
||||
uvm_obj_destroy(&vp->v_uobj, true);
|
||||
cv_destroy(&vp->v_cv);
|
||||
pool_cache_put(vcache_pool, vip);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: genfs_vnops.c,v 1.193 2017/01/11 09:08:59 hannken Exp $ */
|
||||
/* $NetBSD: genfs_vnops.c,v 1.194 2017/03/30 09:16:52 hannken Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -57,7 +57,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.193 2017/01/11 09:08:59 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.194 2017/03/30 09:16:52 hannken Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -295,7 +295,7 @@ genfs_deadlock(void *v)
|
||||
|
||||
op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
|
||||
if (ISSET(flags, LK_NOWAIT)) {
|
||||
if (! rw_tryenter(&vip->vi_lock, op))
|
||||
if (! rw_tryenter(vip->vi_lock, op))
|
||||
return EBUSY;
|
||||
if (mutex_tryenter(vp->v_interlock)) {
|
||||
error = vdead_check(vp, VDEAD_NOWAIT);
|
||||
@ -305,25 +305,25 @@ genfs_deadlock(void *v)
|
||||
} else
|
||||
error = EBUSY;
|
||||
if (error)
|
||||
rw_exit(&vip->vi_lock);
|
||||
rw_exit(vip->vi_lock);
|
||||
return error;
|
||||
}
|
||||
|
||||
rw_enter(&vip->vi_lock, op);
|
||||
rw_enter(vip->vi_lock, op);
|
||||
mutex_enter(vp->v_interlock);
|
||||
error = vdead_check(vp, VDEAD_NOWAIT);
|
||||
if (error == EBUSY) {
|
||||
rw_exit(&vip->vi_lock);
|
||||
rw_exit(vip->vi_lock);
|
||||
error = vdead_check(vp, 0);
|
||||
KASSERT(error == ENOENT);
|
||||
mutex_exit(vp->v_interlock);
|
||||
rw_enter(&vip->vi_lock, op);
|
||||
rw_enter(vip->vi_lock, op);
|
||||
mutex_enter(vp->v_interlock);
|
||||
}
|
||||
KASSERT(error == ENOENT);
|
||||
mutex_exit(vp->v_interlock);
|
||||
if (! ISSET(flags, LK_RETRY)) {
|
||||
rw_exit(&vip->vi_lock);
|
||||
rw_exit(vip->vi_lock);
|
||||
return ENOENT;
|
||||
}
|
||||
return 0;
|
||||
@ -341,7 +341,7 @@ genfs_deadunlock(void *v)
|
||||
vnode_t *vp = ap->a_vp;
|
||||
vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
|
||||
|
||||
rw_exit(&vip->vi_lock);
|
||||
rw_exit(vip->vi_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -367,7 +367,7 @@ genfs_lock(void *v)
|
||||
if (ISSET(flags, LK_NOWAIT)) {
|
||||
if (fstrans_start_nowait(mp, FSTRANS_SHARED))
|
||||
return EBUSY;
|
||||
if (! rw_tryenter(&vip->vi_lock, op)) {
|
||||
if (! rw_tryenter(vip->vi_lock, op)) {
|
||||
fstrans_done(mp);
|
||||
return EBUSY;
|
||||
}
|
||||
@ -377,18 +377,18 @@ genfs_lock(void *v)
|
||||
} else
|
||||
error = EBUSY;
|
||||
if (error) {
|
||||
rw_exit(&vip->vi_lock);
|
||||
rw_exit(vip->vi_lock);
|
||||
fstrans_done(mp);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
fstrans_start(mp, FSTRANS_SHARED);
|
||||
rw_enter(&vip->vi_lock, op);
|
||||
rw_enter(vip->vi_lock, op);
|
||||
mutex_enter(vp->v_interlock);
|
||||
error = vdead_check(vp, VDEAD_NOWAIT);
|
||||
if (error) {
|
||||
rw_exit(&vip->vi_lock);
|
||||
rw_exit(vip->vi_lock);
|
||||
fstrans_done(mp);
|
||||
error = vdead_check(vp, 0);
|
||||
KASSERT(error == ENOENT);
|
||||
@ -410,7 +410,7 @@ genfs_unlock(void *v)
|
||||
vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
|
||||
struct mount *mp = vp->v_mount;
|
||||
|
||||
rw_exit(&vip->vi_lock);
|
||||
rw_exit(vip->vi_lock);
|
||||
fstrans_done(mp);
|
||||
|
||||
return 0;
|
||||
@ -428,10 +428,10 @@ genfs_islocked(void *v)
|
||||
vnode_t *vp = ap->a_vp;
|
||||
vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
|
||||
|
||||
if (rw_write_held(&vip->vi_lock))
|
||||
if (rw_write_held(vip->vi_lock))
|
||||
return LK_EXCLUSIVE;
|
||||
|
||||
if (rw_read_held(&vip->vi_lock))
|
||||
if (rw_read_held(vip->vi_lock))
|
||||
return LK_SHARED;
|
||||
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: layer_extern.h,v 1.38 2017/02/17 08:31:25 hannken Exp $ */
|
||||
/* $NetBSD: layer_extern.h,v 1.39 2017/03/30 09:16:52 hannken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 National Aeronautics & Space Administration
|
||||
@ -99,7 +99,6 @@ int layer_bypass(void *);
|
||||
int layer_getattr(void *);
|
||||
int layer_inactive(void *);
|
||||
int layer_reclaim(void *);
|
||||
int layer_lock(void *);
|
||||
int layer_print(void *);
|
||||
int layer_bmap(void *);
|
||||
int layer_fsync(void *);
|
||||
@ -114,5 +113,8 @@ int layer_revoke(void *);
|
||||
int layer_rmdir(void *);
|
||||
int layer_getpages(void *);
|
||||
int layer_putpages(void *);
|
||||
#define layer_lock genfs_lock
|
||||
#define layer_unlock genfs_unlock
|
||||
#define layer_islocked genfs_islocked
|
||||
|
||||
#endif /* _MISCFS_GENFS_LAYER_EXTERN_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: layer_vfsops.c,v 1.47 2017/02/17 08:31:25 hannken Exp $ */
|
||||
/* $NetBSD: layer_vfsops.c,v 1.48 2017/03/30 09:16:52 hannken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 National Aeronautics & Space Administration
|
||||
@ -74,7 +74,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.47 2017/02/17 08:31:25 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.48 2017/03/30 09:16:52 hannken Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -223,6 +223,9 @@ layerfs_loadvnode(struct mount *mp, struct vnode *vp,
|
||||
mutex_obj_hold(lowervp->v_interlock);
|
||||
uvm_obj_setlock(&vp->v_uobj, lowervp->v_interlock);
|
||||
|
||||
/* Share the lock with the lower node. */
|
||||
vshare_lock(vp, lowervp);
|
||||
|
||||
vp->v_tag = lmp->layerm_tag;
|
||||
vp->v_type = lowervp->v_type;
|
||||
vp->v_op = lmp->layerm_vnodeop_p;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: layer_vnops.c,v 1.60 2017/01/27 10:47:13 hannken Exp $ */
|
||||
/* $NetBSD: layer_vnops.c,v 1.61 2017/03/30 09:16:52 hannken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 National Aeronautics & Space Administration
|
||||
@ -170,7 +170,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.60 2017/01/27 10:47:13 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: layer_vnops.c,v 1.61 2017/03/30 09:16:52 hannken Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -743,48 +743,6 @@ layer_reclaim(void *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
layer_lock(void *v)
|
||||
{
|
||||
struct vop_lock_args /* {
|
||||
struct vnode *a_vp;
|
||||
int a_flags;
|
||||
} */ *ap = v;
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct vnode *lowervp = LAYERVPTOLOWERVP(vp);
|
||||
int flags = ap->a_flags;
|
||||
int error;
|
||||
|
||||
if (ISSET(flags, LK_NOWAIT)) {
|
||||
error = VOP_LOCK(lowervp, flags);
|
||||
if (error)
|
||||
return error;
|
||||
if (mutex_tryenter(vp->v_interlock)) {
|
||||
error = vdead_check(vp, VDEAD_NOWAIT);
|
||||
mutex_exit(vp->v_interlock);
|
||||
} else
|
||||
error = EBUSY;
|
||||
if (error)
|
||||
VOP_UNLOCK(lowervp);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = VOP_LOCK(lowervp, flags);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
mutex_enter(vp->v_interlock);
|
||||
error = vdead_check(vp, VDEAD_NOWAIT);
|
||||
if (error) {
|
||||
VOP_UNLOCK(lowervp);
|
||||
error = vdead_check(vp, 0);
|
||||
KASSERT(error == ENOENT);
|
||||
}
|
||||
mutex_exit(vp->v_interlock);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* We just feed the returned vnode up to the caller - there's no need
|
||||
* to build a layer node on top of the node on which we're going to do
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: null_vnops.c,v 1.40 2017/01/27 10:47:13 hannken Exp $ */
|
||||
/* $NetBSD: null_vnops.c,v 1.41 2017/03/30 09:16:52 hannken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 National Aeronautics & Space Administration
|
||||
@ -80,7 +80,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.40 2017/01/27 10:47:13 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: null_vnops.c,v 1.41 2017/03/30 09:16:52 hannken Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -107,6 +107,8 @@ const struct vnodeopv_entry_desc null_vnodeop_entries[] = {
|
||||
{ &vop_inactive_desc, layer_inactive },
|
||||
{ &vop_reclaim_desc, layer_reclaim },
|
||||
{ &vop_lock_desc, layer_lock },
|
||||
{ &vop_unlock_desc, layer_unlock },
|
||||
{ &vop_islocked_desc, layer_islocked },
|
||||
{ &vop_print_desc, layer_print },
|
||||
{ &vop_remove_desc, layer_remove },
|
||||
{ &vop_rename_desc, layer_rename },
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: overlay_vnops.c,v 1.22 2017/01/27 10:47:13 hannken Exp $ */
|
||||
/* $NetBSD: overlay_vnops.c,v 1.23 2017/03/30 09:16:52 hannken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999, 2000 National Aeronautics & Space Administration
|
||||
@ -67,7 +67,7 @@
|
||||
*
|
||||
* Ancestors:
|
||||
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
|
||||
* $Id: overlay_vnops.c,v 1.22 2017/01/27 10:47:13 hannken Exp $
|
||||
* $Id: overlay_vnops.c,v 1.23 2017/03/30 09:16:52 hannken Exp $
|
||||
* ...and...
|
||||
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
|
||||
*/
|
||||
@ -126,7 +126,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: overlay_vnops.c,v 1.22 2017/01/27 10:47:13 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: overlay_vnops.c,v 1.23 2017/03/30 09:16:52 hannken Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -155,6 +155,8 @@ const struct vnodeopv_entry_desc overlay_vnodeop_entries[] = {
|
||||
{ &vop_inactive_desc, layer_inactive },
|
||||
{ &vop_reclaim_desc, layer_reclaim },
|
||||
{ &vop_lock_desc, layer_lock },
|
||||
{ &vop_unlock_desc, layer_unlock },
|
||||
{ &vop_islocked_desc, layer_islocked },
|
||||
{ &vop_print_desc, layer_print },
|
||||
{ &vop_remove_desc, layer_remove },
|
||||
{ &vop_rename_desc, layer_rename },
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: umap_vnops.c,v 1.58 2017/01/27 10:47:13 hannken Exp $ */
|
||||
/* $NetBSD: umap_vnops.c,v 1.59 2017/03/30 09:16:53 hannken Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: umap_vnops.c,v 1.58 2017/01/27 10:47:13 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: umap_vnops.c,v 1.59 2017/03/30 09:16:53 hannken Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -89,6 +89,8 @@ const struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
|
||||
{ &vop_inactive_desc, layer_inactive },
|
||||
{ &vop_reclaim_desc, layer_reclaim },
|
||||
{ &vop_lock_desc, layer_lock },
|
||||
{ &vop_unlock_desc, layer_unlock },
|
||||
{ &vop_islocked_desc, layer_islocked },
|
||||
{ &vop_open_desc, layer_open },
|
||||
{ &vop_close_desc, layer_close },
|
||||
{ &vop_setattr_desc, layer_setattr },
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: param.h,v 1.533 2017/03/14 09:04:16 ozaki-r Exp $ */
|
||||
/* $NetBSD: param.h,v 1.534 2017/03/30 09:16:53 hannken Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -67,7 +67,7 @@
|
||||
* 2.99.9 (299000900)
|
||||
*/
|
||||
|
||||
#define __NetBSD_Version__ 799006600 /* NetBSD 7.99.66 */
|
||||
#define __NetBSD_Version__ 799006700 /* NetBSD 7.99.67 */
|
||||
|
||||
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
|
||||
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vnode.h,v 1.274 2017/02/17 08:30:00 hannken Exp $ */
|
||||
/* $NetBSD: vnode.h,v 1.275 2017/03/30 09:16:53 hannken Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -516,6 +516,7 @@ bool vrecycle(struct vnode *);
|
||||
void vrele(struct vnode *);
|
||||
void vrele_async(struct vnode *);
|
||||
void vrele_flush(struct mount *);
|
||||
void vshare_lock(vnode_t *, vnode_t *);
|
||||
int vtruncbuf(struct vnode *, daddr_t, bool, int);
|
||||
void vwakeup(struct buf *);
|
||||
int vdead_check(struct vnode *, int);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vnode_impl.h,v 1.12 2017/03/18 05:55:12 riastradh Exp $ */
|
||||
/* $NetBSD: vnode_impl.h,v 1.13 2017/03/30 09:16:53 hannken Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 The NetBSD Foundation, Inc.
|
||||
@ -76,7 +76,7 @@ struct vnode_impl {
|
||||
TAILQ_ENTRY(vnode_impl) vi_synclist; /* s: vnodes with dirty bufs */
|
||||
TAILQ_ENTRY(vnode_impl) vi_mntvnodes; /* m: vnodes for mount point */
|
||||
SLIST_ENTRY(vnode_impl) vi_hash; /* c: vnode cache list */
|
||||
krwlock_t vi_lock; /* -: lock for this vnode */
|
||||
krwlock_t *vi_lock; /* -: lock for this vnode */
|
||||
struct vcache_key vi_key; /* c: vnode cache key */
|
||||
};
|
||||
typedef struct vnode_impl vnode_impl_t;
|
||||
|
Loading…
Reference in New Issue
Block a user