1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-02-04 17:15:50 +00:00

Various cleanups towards make nullfs functional (it is still broken

at this point):

Replace all '#ifdef DEBUG' with '#ifdef NULLFS_DEBUG' and add NULLFSDEBUG
macro.

Protect nullfs hash table with lockmgr.

Use proper order of operations when freeing mnt_data.

Return correct fsid in the null_getattr().

Add null_open() function to catch MNT_NODEV (obtained from NetBSD).

Add null_rename() to catch cross-fs rename operations (submitted by
Ustimenko Semen <semen@iclub.nsu.ru>)

Remove duplicate $FreeBSD$ tags.
This commit is contained in:
Boris Popov 2000-09-05 09:02:07 +00:00
parent 82f257b197
commit 8da8066061
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=65467
8 changed files with 260 additions and 76 deletions

View File

@ -62,6 +62,7 @@ struct null_node {
#define NULLTOV(xp) ((xp)->null_vnode)
int nullfs_init(struct vfsconf *vfsp);
int nullfs_uninit(struct vfsconf *vfsp);
int null_node_create(struct mount *mp, struct vnode *target, struct vnode **vpp);
int null_bypass(struct vop_generic_args *ap);
@ -73,5 +74,16 @@ struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);
#endif
extern vop_t **null_vnodeop_p;
extern struct lock null_hashlock;
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_NULLFSNODE);
#endif
#ifdef NULLFS_DEBUG
#define NULLFSDEBUG(format, args...) printf(format ,## args)
#else
#define NULLFSDEBUG(format, args...)
#endif /* NULLFS_DEBUG */
#endif /* _KERNEL */

View File

@ -40,6 +40,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@ -59,8 +60,13 @@
#define NULL_NHASH(vp) \
(&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
static u_long null_node_hash;
struct lock null_hashlock;
static MALLOC_DEFINE(M_NULLFSHASH, "NULLFS hash", "NULLFS hash table");
MALLOC_DEFINE(M_NULLFSNODE, "NULLFS node", "NULLFS vnode private part");
static int null_node_alloc(struct mount *mp, struct vnode *lowervp,
struct vnode **vpp);
@ -75,10 +81,19 @@ nullfs_init(vfsp)
struct vfsconf *vfsp;
{
#ifdef DEBUG
printf("nullfs_init\n"); /* printed during system boot */
#endif
null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */
null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash);
lockinit(&null_hashlock, PVFS, "nullhs", 0, 0);
return (0);
}
int
nullfs_uninit(vfsp)
struct vfsconf *vfsp;
{
if (null_node_hashtbl)
free(null_node_hashtbl, M_NULLFSHASH);
return (0);
}
@ -103,9 +118,11 @@ null_node_find(mp, lowervp)
*/
hd = NULL_NHASH(lowervp);
loop:
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
vp = NULLTOV(a);
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
/*
* We need vget for the VXLOCK
* stuff, but we don't want to lock
@ -118,6 +135,7 @@ loop:
return (vp);
}
}
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
return NULLVP;
}
@ -134,6 +152,7 @@ null_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
struct proc *p = curproc; /* XXX */
struct null_node_hashhead *hd;
struct null_node *xp;
struct vnode *othervp, *vp;
@ -144,11 +163,12 @@ null_node_alloc(mp, lowervp, vpp)
* might cause a bogus v_data pointer to get dereferenced
* elsewhere if MALLOC should block.
*/
MALLOC(xp, struct null_node *, sizeof(struct null_node), M_TEMP, M_WAITOK);
MALLOC(xp, struct null_node *, sizeof(struct null_node),
M_NULLFSNODE, M_WAITOK);
error = getnewvnode(VT_NULL, mp, null_vnodeop_p, vpp);
if (error) {
FREE(xp, M_TEMP);
FREE(xp, M_NULLFSNODE);
return (error);
}
vp = *vpp;
@ -164,15 +184,17 @@ null_node_alloc(mp, lowervp, vpp)
*/
othervp = null_node_find(mp, lowervp);
if (othervp) {
FREE(xp, M_TEMP);
FREE(xp, M_NULLFSNODE);
vp->v_type = VBAD; /* node is discarded */
vp->v_usecount = 0; /* XXX */
*vpp = othervp;
return 0;
};
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
hd = NULL_NHASH(lowervp);
LIST_INSERT_HEAD(hd, xp, null_hash);
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
return 0;
}
@ -196,7 +218,7 @@ null_node_create(mp, lowervp, newvpp)
* null_node_find has taken another reference
* to the alias vnode.
*/
#ifdef DEBUG
#ifdef NULLFS_DEBUG
vprint("null_node_create: exists", aliasvp);
#endif
/* VREF(aliasvp); --- done in null_node_find */
@ -206,9 +228,7 @@ null_node_create(mp, lowervp, newvpp)
/*
* Get new vnode.
*/
#ifdef DEBUG
printf("null_node_create: create new alias vnode\n");
#endif
NULLFSDEBUG("null_node_create: create new alias vnode\n");
/*
* Make new vnode reference the null_node.
@ -233,7 +253,7 @@ null_node_create(mp, lowervp, newvpp)
};
#endif
#ifdef DEBUG
#ifdef NULLFS_DEBUG
vprint("null_node_create: alias", aliasvp);
vprint("null_node_create: lower", lowervp);
#endif

View File

@ -93,9 +93,7 @@ nullfs_mount(mp, path, data, ndp, p)
u_int size;
int isvnunlocked = 0;
#ifdef DEBUG
printf("nullfs_mount(mp = %p)\n", (void *)mp);
#endif
NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
/*
* Update is a no-op
@ -149,9 +147,7 @@ nullfs_mount(mp, path, data, ndp, p)
* Check multi null mount to avoid `lock against myself' panic.
*/
if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
#ifdef DEBUG
printf("nullfs_mount: multi null mount?\n");
#endif
NULLFSDEBUG("nullfs_mount: multi null mount?\n");
return (EDEADLK);
}
@ -199,10 +195,8 @@ nullfs_mount(mp, path, data, ndp, p)
&size);
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
(void)nullfs_statfs(mp, &mp->mnt_stat, p);
#ifdef DEBUG
printf("nullfs_mount: lower %s, alias at %s\n",
NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
#endif
return (0);
}
@ -231,12 +225,11 @@ nullfs_unmount(mp, mntflags, p)
struct proc *p;
{
struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
void *mntdata;
int error;
int flags = 0;
#ifdef DEBUG
printf("nullfs_unmount(mp = %p)\n", (void *)mp);
#endif
NULLFSDEBUG("nullfs_unmount: mp = %p\n", (void *)mp);
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
@ -257,7 +250,7 @@ nullfs_unmount(mp, mntflags, p)
if (error)
return (error);
#ifdef DEBUG
#ifdef NULLFS_DEBUG
vprint("alias root of lower", nullm_rootvp);
#endif
/*
@ -271,8 +264,9 @@ nullfs_unmount(mp, mntflags, p)
/*
* Finally, throw away the null_mount structure
*/
free(mp->mnt_data, M_NULLFSMNT); /* XXX */
mntdata = mp->mnt_data;
mp->mnt_data = 0;
free(mntdata, M_NULLFSMNT); /* XXX */
return 0;
}
@ -284,29 +278,27 @@ nullfs_root(mp, vpp)
struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef DEBUG
printf("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
NULLFSDEBUG("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
#endif
/*
* Return locked reference to root.
*/
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
VREF(vp);
#ifdef NULLFS_DEBUG
if (VOP_ISLOCKED(vp, NULL)) {
/*
* XXX
* Should we check type of node?
*/
#ifdef DEBUG
printf("nullfs_root: multi null mount?\n");
#endif
vrele(vp);
return (EDEADLK);
} else
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
}
#endif
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return 0;
}
@ -331,11 +323,9 @@ nullfs_statfs(mp, sbp, p)
int error;
struct statfs mstat;
#ifdef DEBUG
printf("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
#endif
bzero(&mstat, sizeof(mstat));
@ -440,7 +430,7 @@ static struct vfsops null_vfsops = {
nullfs_checkexp,
nullfs_vptofh,
nullfs_init,
vfs_stduninit,
nullfs_uninit,
nullfs_extattrctl,
};

View File

@ -37,7 +37,6 @@
*
* Ancestors:
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
* $FreeBSD$
* ...and...
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
*
@ -193,8 +192,10 @@ static int null_getattr(struct vop_getattr_args *ap);
static int null_inactive(struct vop_inactive_args *ap);
static int null_lock(struct vop_lock_args *ap);
static int null_lookup(struct vop_lookup_args *ap);
static int null_open(struct vop_open_args *ap);
static int null_print(struct vop_print_args *ap);
static int null_reclaim(struct vop_reclaim_args *ap);
static int null_rename(struct vop_rename_args *ap);
static int null_setattr(struct vop_setattr_args *ap);
static int null_unlock(struct vop_unlock_args *ap);
@ -448,6 +449,8 @@ null_getattr(ap)
if ((error = null_bypass((struct vop_generic_args *)ap)) != 0)
return (error);
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
return (0);
}
@ -483,6 +486,66 @@ null_access(ap)
return (null_bypass((struct vop_generic_args *)ap));
}
/*
* We must handle open to be able to catch MNT_NODEV and friends.
*/
static int
null_open(ap)
struct vop_open_args /* {
struct vnode *a_vp;
int a_mode;
struct ucred *a_cred;
struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct vnode *lvp = NULLVPTOLOWERVP(ap->a_vp);
if ((vp->v_mount->mnt_flag & MNT_NODEV) &&
(lvp->v_type == VBLK || lvp->v_type == VCHR))
return ENXIO;
return (null_bypass((struct vop_generic_args *)ap));
}
/*
* We handle this to eliminate null FS to lower FS
* file moving. Don't know why we don't allow this,
* possibly we should.
*/
static int
null_rename(ap)
struct vop_rename_args /* {
struct vnode *a_fdvp;
struct vnode *a_fvp;
struct componentname *a_fcnp;
struct vnode *a_tdvp;
struct vnode *a_tvp;
struct componentname *a_tcnp;
} */ *ap;
{
struct vnode *tdvp = ap->a_tdvp;
struct vnode *fvp = ap->a_fvp;
struct vnode *fdvp = ap->a_fdvp;
struct vnode *tvp = ap->a_tvp;
/* Check for cross-device rename. */
if ((fvp->v_mount != tdvp->v_mount) ||
(tvp && (fvp->v_mount != tvp->v_mount))) {
if (tdvp == tvp)
vrele(tdvp);
else
vput(tdvp);
if (tvp)
vput(tvp);
vrele(fdvp);
vrele(fvp);
return (EXDEV);
}
return (null_bypass((struct vop_generic_args *)ap));
}
/*
* We need to process our own vnode lock and then clear the
* interlock flag as it applies only to our vnode, not the
@ -568,7 +631,9 @@ null_reclaim(ap)
*/
/* After this assignment, this node will not be re-used. */
xp->null_lowervp = NULLVP;
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, ap->a_p);
LIST_REMOVE(xp, null_hash);
lockmgr(&null_hashlock, LK_RELEASE, NULL, ap->a_p);
FREE(vp->v_data, M_TEMP);
vp->v_data = NULL;
vrele (lowervp);
@ -593,13 +658,18 @@ vop_t **null_vnodeop_p;
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *) null_bypass },
{ &vop_access_desc, (vop_t *) null_access },
{ &vop_bmap_desc, (vop_t *) vop_eopnotsupp },
{ &vop_getattr_desc, (vop_t *) null_getattr },
{ &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount},
{ &vop_inactive_desc, (vop_t *) null_inactive },
{ &vop_lock_desc, (vop_t *) null_lock },
{ &vop_lookup_desc, (vop_t *) null_lookup },
{ &vop_open_desc, (vop_t *) null_open },
{ &vop_print_desc, (vop_t *) null_print },
{ &vop_reclaim_desc, (vop_t *) null_reclaim },
{ &vop_rename_desc, (vop_t *) null_rename },
{ &vop_setattr_desc, (vop_t *) null_setattr },
{ &vop_strategy_desc, (vop_t *) vop_eopnotsupp },
{ &vop_unlock_desc, (vop_t *) null_unlock },
{ NULL, NULL }
};

View File

@ -62,6 +62,7 @@ struct null_node {
#define NULLTOV(xp) ((xp)->null_vnode)
int nullfs_init(struct vfsconf *vfsp);
int nullfs_uninit(struct vfsconf *vfsp);
int null_node_create(struct mount *mp, struct vnode *target, struct vnode **vpp);
int null_bypass(struct vop_generic_args *ap);
@ -73,5 +74,16 @@ struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);
#endif
extern vop_t **null_vnodeop_p;
extern struct lock null_hashlock;
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_NULLFSNODE);
#endif
#ifdef NULLFS_DEBUG
#define NULLFSDEBUG(format, args...) printf(format ,## args)
#else
#define NULLFSDEBUG(format, args...)
#endif /* NULLFS_DEBUG */
#endif /* _KERNEL */

View File

@ -40,6 +40,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@ -59,8 +60,13 @@
#define NULL_NHASH(vp) \
(&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
static u_long null_node_hash;
struct lock null_hashlock;
static MALLOC_DEFINE(M_NULLFSHASH, "NULLFS hash", "NULLFS hash table");
MALLOC_DEFINE(M_NULLFSNODE, "NULLFS node", "NULLFS vnode private part");
static int null_node_alloc(struct mount *mp, struct vnode *lowervp,
struct vnode **vpp);
@ -75,10 +81,19 @@ nullfs_init(vfsp)
struct vfsconf *vfsp;
{
#ifdef DEBUG
printf("nullfs_init\n"); /* printed during system boot */
#endif
null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */
null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash);
lockinit(&null_hashlock, PVFS, "nullhs", 0, 0);
return (0);
}
int
nullfs_uninit(vfsp)
struct vfsconf *vfsp;
{
if (null_node_hashtbl)
free(null_node_hashtbl, M_NULLFSHASH);
return (0);
}
@ -103,9 +118,11 @@ null_node_find(mp, lowervp)
*/
hd = NULL_NHASH(lowervp);
loop:
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
vp = NULLTOV(a);
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
/*
* We need vget for the VXLOCK
* stuff, but we don't want to lock
@ -118,6 +135,7 @@ loop:
return (vp);
}
}
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
return NULLVP;
}
@ -134,6 +152,7 @@ null_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
struct proc *p = curproc; /* XXX */
struct null_node_hashhead *hd;
struct null_node *xp;
struct vnode *othervp, *vp;
@ -144,11 +163,12 @@ null_node_alloc(mp, lowervp, vpp)
* might cause a bogus v_data pointer to get dereferenced
* elsewhere if MALLOC should block.
*/
MALLOC(xp, struct null_node *, sizeof(struct null_node), M_TEMP, M_WAITOK);
MALLOC(xp, struct null_node *, sizeof(struct null_node),
M_NULLFSNODE, M_WAITOK);
error = getnewvnode(VT_NULL, mp, null_vnodeop_p, vpp);
if (error) {
FREE(xp, M_TEMP);
FREE(xp, M_NULLFSNODE);
return (error);
}
vp = *vpp;
@ -164,15 +184,17 @@ null_node_alloc(mp, lowervp, vpp)
*/
othervp = null_node_find(mp, lowervp);
if (othervp) {
FREE(xp, M_TEMP);
FREE(xp, M_NULLFSNODE);
vp->v_type = VBAD; /* node is discarded */
vp->v_usecount = 0; /* XXX */
*vpp = othervp;
return 0;
};
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
hd = NULL_NHASH(lowervp);
LIST_INSERT_HEAD(hd, xp, null_hash);
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
return 0;
}
@ -196,7 +218,7 @@ null_node_create(mp, lowervp, newvpp)
* null_node_find has taken another reference
* to the alias vnode.
*/
#ifdef DEBUG
#ifdef NULLFS_DEBUG
vprint("null_node_create: exists", aliasvp);
#endif
/* VREF(aliasvp); --- done in null_node_find */
@ -206,9 +228,7 @@ null_node_create(mp, lowervp, newvpp)
/*
* Get new vnode.
*/
#ifdef DEBUG
printf("null_node_create: create new alias vnode\n");
#endif
NULLFSDEBUG("null_node_create: create new alias vnode\n");
/*
* Make new vnode reference the null_node.
@ -233,7 +253,7 @@ null_node_create(mp, lowervp, newvpp)
};
#endif
#ifdef DEBUG
#ifdef NULLFS_DEBUG
vprint("null_node_create: alias", aliasvp);
vprint("null_node_create: lower", lowervp);
#endif

View File

@ -93,9 +93,7 @@ nullfs_mount(mp, path, data, ndp, p)
u_int size;
int isvnunlocked = 0;
#ifdef DEBUG
printf("nullfs_mount(mp = %p)\n", (void *)mp);
#endif
NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
/*
* Update is a no-op
@ -149,9 +147,7 @@ nullfs_mount(mp, path, data, ndp, p)
* Check multi null mount to avoid `lock against myself' panic.
*/
if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
#ifdef DEBUG
printf("nullfs_mount: multi null mount?\n");
#endif
NULLFSDEBUG("nullfs_mount: multi null mount?\n");
return (EDEADLK);
}
@ -199,10 +195,8 @@ nullfs_mount(mp, path, data, ndp, p)
&size);
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
(void)nullfs_statfs(mp, &mp->mnt_stat, p);
#ifdef DEBUG
printf("nullfs_mount: lower %s, alias at %s\n",
NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
#endif
return (0);
}
@ -231,12 +225,11 @@ nullfs_unmount(mp, mntflags, p)
struct proc *p;
{
struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
void *mntdata;
int error;
int flags = 0;
#ifdef DEBUG
printf("nullfs_unmount(mp = %p)\n", (void *)mp);
#endif
NULLFSDEBUG("nullfs_unmount: mp = %p\n", (void *)mp);
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
@ -257,7 +250,7 @@ nullfs_unmount(mp, mntflags, p)
if (error)
return (error);
#ifdef DEBUG
#ifdef NULLFS_DEBUG
vprint("alias root of lower", nullm_rootvp);
#endif
/*
@ -271,8 +264,9 @@ nullfs_unmount(mp, mntflags, p)
/*
* Finally, throw away the null_mount structure
*/
free(mp->mnt_data, M_NULLFSMNT); /* XXX */
mntdata = mp->mnt_data;
mp->mnt_data = 0;
free(mntdata, M_NULLFSMNT); /* XXX */
return 0;
}
@ -284,29 +278,27 @@ nullfs_root(mp, vpp)
struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef DEBUG
printf("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
NULLFSDEBUG("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
#endif
/*
* Return locked reference to root.
*/
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
VREF(vp);
#ifdef NULLFS_DEBUG
if (VOP_ISLOCKED(vp, NULL)) {
/*
* XXX
* Should we check type of node?
*/
#ifdef DEBUG
printf("nullfs_root: multi null mount?\n");
#endif
vrele(vp);
return (EDEADLK);
} else
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
}
#endif
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return 0;
}
@ -331,11 +323,9 @@ nullfs_statfs(mp, sbp, p)
int error;
struct statfs mstat;
#ifdef DEBUG
printf("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
#endif
bzero(&mstat, sizeof(mstat));
@ -440,7 +430,7 @@ static struct vfsops null_vfsops = {
nullfs_checkexp,
nullfs_vptofh,
nullfs_init,
vfs_stduninit,
nullfs_uninit,
nullfs_extattrctl,
};

View File

@ -37,7 +37,6 @@
*
* Ancestors:
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
* $FreeBSD$
* ...and...
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
*
@ -193,8 +192,10 @@ static int null_getattr(struct vop_getattr_args *ap);
static int null_inactive(struct vop_inactive_args *ap);
static int null_lock(struct vop_lock_args *ap);
static int null_lookup(struct vop_lookup_args *ap);
static int null_open(struct vop_open_args *ap);
static int null_print(struct vop_print_args *ap);
static int null_reclaim(struct vop_reclaim_args *ap);
static int null_rename(struct vop_rename_args *ap);
static int null_setattr(struct vop_setattr_args *ap);
static int null_unlock(struct vop_unlock_args *ap);
@ -448,6 +449,8 @@ null_getattr(ap)
if ((error = null_bypass((struct vop_generic_args *)ap)) != 0)
return (error);
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
return (0);
}
@ -483,6 +486,66 @@ null_access(ap)
return (null_bypass((struct vop_generic_args *)ap));
}
/*
* We must handle open to be able to catch MNT_NODEV and friends.
*/
static int
null_open(ap)
struct vop_open_args /* {
struct vnode *a_vp;
int a_mode;
struct ucred *a_cred;
struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct vnode *lvp = NULLVPTOLOWERVP(ap->a_vp);
if ((vp->v_mount->mnt_flag & MNT_NODEV) &&
(lvp->v_type == VBLK || lvp->v_type == VCHR))
return ENXIO;
return (null_bypass((struct vop_generic_args *)ap));
}
/*
* We handle this to eliminate null FS to lower FS
* file moving. Don't know why we don't allow this,
* possibly we should.
*/
static int
null_rename(ap)
struct vop_rename_args /* {
struct vnode *a_fdvp;
struct vnode *a_fvp;
struct componentname *a_fcnp;
struct vnode *a_tdvp;
struct vnode *a_tvp;
struct componentname *a_tcnp;
} */ *ap;
{
struct vnode *tdvp = ap->a_tdvp;
struct vnode *fvp = ap->a_fvp;
struct vnode *fdvp = ap->a_fdvp;
struct vnode *tvp = ap->a_tvp;
/* Check for cross-device rename. */
if ((fvp->v_mount != tdvp->v_mount) ||
(tvp && (fvp->v_mount != tvp->v_mount))) {
if (tdvp == tvp)
vrele(tdvp);
else
vput(tdvp);
if (tvp)
vput(tvp);
vrele(fdvp);
vrele(fvp);
return (EXDEV);
}
return (null_bypass((struct vop_generic_args *)ap));
}
/*
* We need to process our own vnode lock and then clear the
* interlock flag as it applies only to our vnode, not the
@ -568,7 +631,9 @@ null_reclaim(ap)
*/
/* After this assignment, this node will not be re-used. */
xp->null_lowervp = NULLVP;
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, ap->a_p);
LIST_REMOVE(xp, null_hash);
lockmgr(&null_hashlock, LK_RELEASE, NULL, ap->a_p);
FREE(vp->v_data, M_TEMP);
vp->v_data = NULL;
vrele (lowervp);
@ -593,13 +658,18 @@ vop_t **null_vnodeop_p;
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *) null_bypass },
{ &vop_access_desc, (vop_t *) null_access },
{ &vop_bmap_desc, (vop_t *) vop_eopnotsupp },
{ &vop_getattr_desc, (vop_t *) null_getattr },
{ &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount},
{ &vop_inactive_desc, (vop_t *) null_inactive },
{ &vop_lock_desc, (vop_t *) null_lock },
{ &vop_lookup_desc, (vop_t *) null_lookup },
{ &vop_open_desc, (vop_t *) null_open },
{ &vop_print_desc, (vop_t *) null_print },
{ &vop_reclaim_desc, (vop_t *) null_reclaim },
{ &vop_rename_desc, (vop_t *) null_rename },
{ &vop_setattr_desc, (vop_t *) null_setattr },
{ &vop_strategy_desc, (vop_t *) vop_eopnotsupp },
{ &vop_unlock_desc, (vop_t *) null_unlock },
{ NULL, NULL }
};