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:
parent
82f257b197
commit
8da8066061
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=65467
@ -62,6 +62,7 @@ struct null_node {
|
|||||||
#define NULLTOV(xp) ((xp)->null_vnode)
|
#define NULLTOV(xp) ((xp)->null_vnode)
|
||||||
|
|
||||||
int nullfs_init(struct vfsconf *vfsp);
|
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_node_create(struct mount *mp, struct vnode *target, struct vnode **vpp);
|
||||||
int null_bypass(struct vop_generic_args *ap);
|
int null_bypass(struct vop_generic_args *ap);
|
||||||
|
|
||||||
@ -73,5 +74,16 @@ struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern vop_t **null_vnodeop_p;
|
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 */
|
#endif /* _KERNEL */
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/vnode.h>
|
#include <sys/vnode.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
@ -59,8 +60,13 @@
|
|||||||
|
|
||||||
#define NULL_NHASH(vp) \
|
#define NULL_NHASH(vp) \
|
||||||
(&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
|
(&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
|
||||||
|
|
||||||
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
|
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
|
||||||
static u_long null_node_hash;
|
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,
|
static int null_node_alloc(struct mount *mp, struct vnode *lowervp,
|
||||||
struct vnode **vpp);
|
struct vnode **vpp);
|
||||||
@ -75,10 +81,19 @@ nullfs_init(vfsp)
|
|||||||
struct vfsconf *vfsp;
|
struct vfsconf *vfsp;
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */
|
||||||
printf("nullfs_init\n"); /* printed during system boot */
|
null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash);
|
||||||
#endif
|
lockinit(&null_hashlock, PVFS, "nullhs", 0, 0);
|
||||||
null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nullfs_uninit(vfsp)
|
||||||
|
struct vfsconf *vfsp;
|
||||||
|
{
|
||||||
|
|
||||||
|
if (null_node_hashtbl)
|
||||||
|
free(null_node_hashtbl, M_NULLFSHASH);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,9 +118,11 @@ null_node_find(mp, lowervp)
|
|||||||
*/
|
*/
|
||||||
hd = NULL_NHASH(lowervp);
|
hd = NULL_NHASH(lowervp);
|
||||||
loop:
|
loop:
|
||||||
|
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
|
||||||
for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
|
for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
|
||||||
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
|
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
|
||||||
vp = NULLTOV(a);
|
vp = NULLTOV(a);
|
||||||
|
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
|
||||||
/*
|
/*
|
||||||
* We need vget for the VXLOCK
|
* We need vget for the VXLOCK
|
||||||
* stuff, but we don't want to lock
|
* stuff, but we don't want to lock
|
||||||
@ -118,6 +135,7 @@ loop:
|
|||||||
return (vp);
|
return (vp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
|
||||||
|
|
||||||
return NULLVP;
|
return NULLVP;
|
||||||
}
|
}
|
||||||
@ -134,6 +152,7 @@ null_node_alloc(mp, lowervp, vpp)
|
|||||||
struct vnode *lowervp;
|
struct vnode *lowervp;
|
||||||
struct vnode **vpp;
|
struct vnode **vpp;
|
||||||
{
|
{
|
||||||
|
struct proc *p = curproc; /* XXX */
|
||||||
struct null_node_hashhead *hd;
|
struct null_node_hashhead *hd;
|
||||||
struct null_node *xp;
|
struct null_node *xp;
|
||||||
struct vnode *othervp, *vp;
|
struct vnode *othervp, *vp;
|
||||||
@ -144,11 +163,12 @@ null_node_alloc(mp, lowervp, vpp)
|
|||||||
* might cause a bogus v_data pointer to get dereferenced
|
* might cause a bogus v_data pointer to get dereferenced
|
||||||
* elsewhere if MALLOC should block.
|
* 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);
|
error = getnewvnode(VT_NULL, mp, null_vnodeop_p, vpp);
|
||||||
if (error) {
|
if (error) {
|
||||||
FREE(xp, M_TEMP);
|
FREE(xp, M_NULLFSNODE);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
vp = *vpp;
|
vp = *vpp;
|
||||||
@ -164,15 +184,17 @@ null_node_alloc(mp, lowervp, vpp)
|
|||||||
*/
|
*/
|
||||||
othervp = null_node_find(mp, lowervp);
|
othervp = null_node_find(mp, lowervp);
|
||||||
if (othervp) {
|
if (othervp) {
|
||||||
FREE(xp, M_TEMP);
|
FREE(xp, M_NULLFSNODE);
|
||||||
vp->v_type = VBAD; /* node is discarded */
|
vp->v_type = VBAD; /* node is discarded */
|
||||||
vp->v_usecount = 0; /* XXX */
|
vp->v_usecount = 0; /* XXX */
|
||||||
*vpp = othervp;
|
*vpp = othervp;
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
|
||||||
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
|
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
|
||||||
hd = NULL_NHASH(lowervp);
|
hd = NULL_NHASH(lowervp);
|
||||||
LIST_INSERT_HEAD(hd, xp, null_hash);
|
LIST_INSERT_HEAD(hd, xp, null_hash);
|
||||||
|
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +218,7 @@ null_node_create(mp, lowervp, newvpp)
|
|||||||
* null_node_find has taken another reference
|
* null_node_find has taken another reference
|
||||||
* to the alias vnode.
|
* to the alias vnode.
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
#ifdef NULLFS_DEBUG
|
||||||
vprint("null_node_create: exists", aliasvp);
|
vprint("null_node_create: exists", aliasvp);
|
||||||
#endif
|
#endif
|
||||||
/* VREF(aliasvp); --- done in null_node_find */
|
/* VREF(aliasvp); --- done in null_node_find */
|
||||||
@ -206,9 +228,7 @@ null_node_create(mp, lowervp, newvpp)
|
|||||||
/*
|
/*
|
||||||
* Get new vnode.
|
* Get new vnode.
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("null_node_create: create new alias vnode\n");
|
||||||
printf("null_node_create: create new alias vnode\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make new vnode reference the null_node.
|
* Make new vnode reference the null_node.
|
||||||
@ -233,7 +253,7 @@ null_node_create(mp, lowervp, newvpp)
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef NULLFS_DEBUG
|
||||||
vprint("null_node_create: alias", aliasvp);
|
vprint("null_node_create: alias", aliasvp);
|
||||||
vprint("null_node_create: lower", lowervp);
|
vprint("null_node_create: lower", lowervp);
|
||||||
#endif
|
#endif
|
||||||
|
@ -93,9 +93,7 @@ nullfs_mount(mp, path, data, ndp, p)
|
|||||||
u_int size;
|
u_int size;
|
||||||
int isvnunlocked = 0;
|
int isvnunlocked = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
|
||||||
printf("nullfs_mount(mp = %p)\n", (void *)mp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update is a no-op
|
* 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.
|
* Check multi null mount to avoid `lock against myself' panic.
|
||||||
*/
|
*/
|
||||||
if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
|
if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_mount: multi null mount?\n");
|
||||||
printf("nullfs_mount: multi null mount?\n");
|
|
||||||
#endif
|
|
||||||
return (EDEADLK);
|
return (EDEADLK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,10 +195,8 @@ nullfs_mount(mp, path, data, ndp, p)
|
|||||||
&size);
|
&size);
|
||||||
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
|
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
|
||||||
(void)nullfs_statfs(mp, &mp->mnt_stat, p);
|
(void)nullfs_statfs(mp, &mp->mnt_stat, p);
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
|
||||||
printf("nullfs_mount: lower %s, alias at %s\n",
|
|
||||||
mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
|
mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
|
||||||
#endif
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,12 +225,11 @@ nullfs_unmount(mp, mntflags, p)
|
|||||||
struct proc *p;
|
struct proc *p;
|
||||||
{
|
{
|
||||||
struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
||||||
|
void *mntdata;
|
||||||
int error;
|
int error;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_unmount: mp = %p\n", (void *)mp);
|
||||||
printf("nullfs_unmount(mp = %p)\n", (void *)mp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mntflags & MNT_FORCE)
|
if (mntflags & MNT_FORCE)
|
||||||
flags |= FORCECLOSE;
|
flags |= FORCECLOSE;
|
||||||
@ -257,7 +250,7 @@ nullfs_unmount(mp, mntflags, p)
|
|||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef NULLFS_DEBUG
|
||||||
vprint("alias root of lower", nullm_rootvp);
|
vprint("alias root of lower", nullm_rootvp);
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
@ -271,8 +264,9 @@ nullfs_unmount(mp, mntflags, p)
|
|||||||
/*
|
/*
|
||||||
* Finally, throw away the null_mount structure
|
* Finally, throw away the null_mount structure
|
||||||
*/
|
*/
|
||||||
free(mp->mnt_data, M_NULLFSMNT); /* XXX */
|
mntdata = mp->mnt_data;
|
||||||
mp->mnt_data = 0;
|
mp->mnt_data = 0;
|
||||||
|
free(mntdata, M_NULLFSMNT); /* XXX */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,29 +278,27 @@ nullfs_root(mp, vpp)
|
|||||||
struct proc *p = curproc; /* XXX */
|
struct proc *p = curproc; /* XXX */
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
|
||||||
printf("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
|
|
||||||
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
|
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
|
||||||
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
|
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return locked reference to root.
|
* Return locked reference to root.
|
||||||
*/
|
*/
|
||||||
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
||||||
VREF(vp);
|
VREF(vp);
|
||||||
|
#ifdef NULLFS_DEBUG
|
||||||
if (VOP_ISLOCKED(vp, NULL)) {
|
if (VOP_ISLOCKED(vp, NULL)) {
|
||||||
/*
|
/*
|
||||||
* XXX
|
* XXX
|
||||||
* Should we check type of node?
|
* Should we check type of node?
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
|
||||||
printf("nullfs_root: multi null mount?\n");
|
printf("nullfs_root: multi null mount?\n");
|
||||||
#endif
|
|
||||||
vrele(vp);
|
vrele(vp);
|
||||||
return (EDEADLK);
|
return (EDEADLK);
|
||||||
} else
|
}
|
||||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
#endif
|
||||||
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||||
*vpp = vp;
|
*vpp = vp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -331,11 +323,9 @@ nullfs_statfs(mp, sbp, p)
|
|||||||
int error;
|
int error;
|
||||||
struct statfs mstat;
|
struct statfs mstat;
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
|
||||||
printf("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
|
|
||||||
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
|
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
|
||||||
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
|
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
|
||||||
#endif
|
|
||||||
|
|
||||||
bzero(&mstat, sizeof(mstat));
|
bzero(&mstat, sizeof(mstat));
|
||||||
|
|
||||||
@ -440,7 +430,7 @@ static struct vfsops null_vfsops = {
|
|||||||
nullfs_checkexp,
|
nullfs_checkexp,
|
||||||
nullfs_vptofh,
|
nullfs_vptofh,
|
||||||
nullfs_init,
|
nullfs_init,
|
||||||
vfs_stduninit,
|
nullfs_uninit,
|
||||||
nullfs_extattrctl,
|
nullfs_extattrctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
*
|
*
|
||||||
* Ancestors:
|
* Ancestors:
|
||||||
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
|
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
|
||||||
* $FreeBSD$
|
|
||||||
* ...and...
|
* ...and...
|
||||||
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
|
* @(#)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_inactive(struct vop_inactive_args *ap);
|
||||||
static int null_lock(struct vop_lock_args *ap);
|
static int null_lock(struct vop_lock_args *ap);
|
||||||
static int null_lookup(struct vop_lookup_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_print(struct vop_print_args *ap);
|
||||||
static int null_reclaim(struct vop_reclaim_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_setattr(struct vop_setattr_args *ap);
|
||||||
static int null_unlock(struct vop_unlock_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)
|
if ((error = null_bypass((struct vop_generic_args *)ap)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,6 +486,66 @@ null_access(ap)
|
|||||||
return (null_bypass((struct vop_generic_args *)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
|
* We need to process our own vnode lock and then clear the
|
||||||
* interlock flag as it applies only to our vnode, not 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. */
|
/* After this assignment, this node will not be re-used. */
|
||||||
xp->null_lowervp = NULLVP;
|
xp->null_lowervp = NULLVP;
|
||||||
|
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, ap->a_p);
|
||||||
LIST_REMOVE(xp, null_hash);
|
LIST_REMOVE(xp, null_hash);
|
||||||
|
lockmgr(&null_hashlock, LK_RELEASE, NULL, ap->a_p);
|
||||||
FREE(vp->v_data, M_TEMP);
|
FREE(vp->v_data, M_TEMP);
|
||||||
vp->v_data = NULL;
|
vp->v_data = NULL;
|
||||||
vrele (lowervp);
|
vrele (lowervp);
|
||||||
@ -593,13 +658,18 @@ vop_t **null_vnodeop_p;
|
|||||||
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
|
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
|
||||||
{ &vop_default_desc, (vop_t *) null_bypass },
|
{ &vop_default_desc, (vop_t *) null_bypass },
|
||||||
{ &vop_access_desc, (vop_t *) null_access },
|
{ &vop_access_desc, (vop_t *) null_access },
|
||||||
|
{ &vop_bmap_desc, (vop_t *) vop_eopnotsupp },
|
||||||
{ &vop_getattr_desc, (vop_t *) null_getattr },
|
{ &vop_getattr_desc, (vop_t *) null_getattr },
|
||||||
|
{ &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount},
|
||||||
{ &vop_inactive_desc, (vop_t *) null_inactive },
|
{ &vop_inactive_desc, (vop_t *) null_inactive },
|
||||||
{ &vop_lock_desc, (vop_t *) null_lock },
|
{ &vop_lock_desc, (vop_t *) null_lock },
|
||||||
{ &vop_lookup_desc, (vop_t *) null_lookup },
|
{ &vop_lookup_desc, (vop_t *) null_lookup },
|
||||||
|
{ &vop_open_desc, (vop_t *) null_open },
|
||||||
{ &vop_print_desc, (vop_t *) null_print },
|
{ &vop_print_desc, (vop_t *) null_print },
|
||||||
{ &vop_reclaim_desc, (vop_t *) null_reclaim },
|
{ &vop_reclaim_desc, (vop_t *) null_reclaim },
|
||||||
|
{ &vop_rename_desc, (vop_t *) null_rename },
|
||||||
{ &vop_setattr_desc, (vop_t *) null_setattr },
|
{ &vop_setattr_desc, (vop_t *) null_setattr },
|
||||||
|
{ &vop_strategy_desc, (vop_t *) vop_eopnotsupp },
|
||||||
{ &vop_unlock_desc, (vop_t *) null_unlock },
|
{ &vop_unlock_desc, (vop_t *) null_unlock },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
@ -62,6 +62,7 @@ struct null_node {
|
|||||||
#define NULLTOV(xp) ((xp)->null_vnode)
|
#define NULLTOV(xp) ((xp)->null_vnode)
|
||||||
|
|
||||||
int nullfs_init(struct vfsconf *vfsp);
|
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_node_create(struct mount *mp, struct vnode *target, struct vnode **vpp);
|
||||||
int null_bypass(struct vop_generic_args *ap);
|
int null_bypass(struct vop_generic_args *ap);
|
||||||
|
|
||||||
@ -73,5 +74,16 @@ struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern vop_t **null_vnodeop_p;
|
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 */
|
#endif /* _KERNEL */
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/vnode.h>
|
#include <sys/vnode.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
@ -59,8 +60,13 @@
|
|||||||
|
|
||||||
#define NULL_NHASH(vp) \
|
#define NULL_NHASH(vp) \
|
||||||
(&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
|
(&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
|
||||||
|
|
||||||
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
|
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
|
||||||
static u_long null_node_hash;
|
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,
|
static int null_node_alloc(struct mount *mp, struct vnode *lowervp,
|
||||||
struct vnode **vpp);
|
struct vnode **vpp);
|
||||||
@ -75,10 +81,19 @@ nullfs_init(vfsp)
|
|||||||
struct vfsconf *vfsp;
|
struct vfsconf *vfsp;
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */
|
||||||
printf("nullfs_init\n"); /* printed during system boot */
|
null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash);
|
||||||
#endif
|
lockinit(&null_hashlock, PVFS, "nullhs", 0, 0);
|
||||||
null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nullfs_uninit(vfsp)
|
||||||
|
struct vfsconf *vfsp;
|
||||||
|
{
|
||||||
|
|
||||||
|
if (null_node_hashtbl)
|
||||||
|
free(null_node_hashtbl, M_NULLFSHASH);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,9 +118,11 @@ null_node_find(mp, lowervp)
|
|||||||
*/
|
*/
|
||||||
hd = NULL_NHASH(lowervp);
|
hd = NULL_NHASH(lowervp);
|
||||||
loop:
|
loop:
|
||||||
|
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
|
||||||
for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
|
for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
|
||||||
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
|
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
|
||||||
vp = NULLTOV(a);
|
vp = NULLTOV(a);
|
||||||
|
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
|
||||||
/*
|
/*
|
||||||
* We need vget for the VXLOCK
|
* We need vget for the VXLOCK
|
||||||
* stuff, but we don't want to lock
|
* stuff, but we don't want to lock
|
||||||
@ -118,6 +135,7 @@ loop:
|
|||||||
return (vp);
|
return (vp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
|
||||||
|
|
||||||
return NULLVP;
|
return NULLVP;
|
||||||
}
|
}
|
||||||
@ -134,6 +152,7 @@ null_node_alloc(mp, lowervp, vpp)
|
|||||||
struct vnode *lowervp;
|
struct vnode *lowervp;
|
||||||
struct vnode **vpp;
|
struct vnode **vpp;
|
||||||
{
|
{
|
||||||
|
struct proc *p = curproc; /* XXX */
|
||||||
struct null_node_hashhead *hd;
|
struct null_node_hashhead *hd;
|
||||||
struct null_node *xp;
|
struct null_node *xp;
|
||||||
struct vnode *othervp, *vp;
|
struct vnode *othervp, *vp;
|
||||||
@ -144,11 +163,12 @@ null_node_alloc(mp, lowervp, vpp)
|
|||||||
* might cause a bogus v_data pointer to get dereferenced
|
* might cause a bogus v_data pointer to get dereferenced
|
||||||
* elsewhere if MALLOC should block.
|
* 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);
|
error = getnewvnode(VT_NULL, mp, null_vnodeop_p, vpp);
|
||||||
if (error) {
|
if (error) {
|
||||||
FREE(xp, M_TEMP);
|
FREE(xp, M_NULLFSNODE);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
vp = *vpp;
|
vp = *vpp;
|
||||||
@ -164,15 +184,17 @@ null_node_alloc(mp, lowervp, vpp)
|
|||||||
*/
|
*/
|
||||||
othervp = null_node_find(mp, lowervp);
|
othervp = null_node_find(mp, lowervp);
|
||||||
if (othervp) {
|
if (othervp) {
|
||||||
FREE(xp, M_TEMP);
|
FREE(xp, M_NULLFSNODE);
|
||||||
vp->v_type = VBAD; /* node is discarded */
|
vp->v_type = VBAD; /* node is discarded */
|
||||||
vp->v_usecount = 0; /* XXX */
|
vp->v_usecount = 0; /* XXX */
|
||||||
*vpp = othervp;
|
*vpp = othervp;
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
|
||||||
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
|
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
|
||||||
hd = NULL_NHASH(lowervp);
|
hd = NULL_NHASH(lowervp);
|
||||||
LIST_INSERT_HEAD(hd, xp, null_hash);
|
LIST_INSERT_HEAD(hd, xp, null_hash);
|
||||||
|
lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +218,7 @@ null_node_create(mp, lowervp, newvpp)
|
|||||||
* null_node_find has taken another reference
|
* null_node_find has taken another reference
|
||||||
* to the alias vnode.
|
* to the alias vnode.
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
#ifdef NULLFS_DEBUG
|
||||||
vprint("null_node_create: exists", aliasvp);
|
vprint("null_node_create: exists", aliasvp);
|
||||||
#endif
|
#endif
|
||||||
/* VREF(aliasvp); --- done in null_node_find */
|
/* VREF(aliasvp); --- done in null_node_find */
|
||||||
@ -206,9 +228,7 @@ null_node_create(mp, lowervp, newvpp)
|
|||||||
/*
|
/*
|
||||||
* Get new vnode.
|
* Get new vnode.
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("null_node_create: create new alias vnode\n");
|
||||||
printf("null_node_create: create new alias vnode\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make new vnode reference the null_node.
|
* Make new vnode reference the null_node.
|
||||||
@ -233,7 +253,7 @@ null_node_create(mp, lowervp, newvpp)
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef NULLFS_DEBUG
|
||||||
vprint("null_node_create: alias", aliasvp);
|
vprint("null_node_create: alias", aliasvp);
|
||||||
vprint("null_node_create: lower", lowervp);
|
vprint("null_node_create: lower", lowervp);
|
||||||
#endif
|
#endif
|
||||||
|
@ -93,9 +93,7 @@ nullfs_mount(mp, path, data, ndp, p)
|
|||||||
u_int size;
|
u_int size;
|
||||||
int isvnunlocked = 0;
|
int isvnunlocked = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
|
||||||
printf("nullfs_mount(mp = %p)\n", (void *)mp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update is a no-op
|
* 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.
|
* Check multi null mount to avoid `lock against myself' panic.
|
||||||
*/
|
*/
|
||||||
if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
|
if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_mount: multi null mount?\n");
|
||||||
printf("nullfs_mount: multi null mount?\n");
|
|
||||||
#endif
|
|
||||||
return (EDEADLK);
|
return (EDEADLK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,10 +195,8 @@ nullfs_mount(mp, path, data, ndp, p)
|
|||||||
&size);
|
&size);
|
||||||
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
|
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
|
||||||
(void)nullfs_statfs(mp, &mp->mnt_stat, p);
|
(void)nullfs_statfs(mp, &mp->mnt_stat, p);
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
|
||||||
printf("nullfs_mount: lower %s, alias at %s\n",
|
|
||||||
mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
|
mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
|
||||||
#endif
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,12 +225,11 @@ nullfs_unmount(mp, mntflags, p)
|
|||||||
struct proc *p;
|
struct proc *p;
|
||||||
{
|
{
|
||||||
struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
||||||
|
void *mntdata;
|
||||||
int error;
|
int error;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_unmount: mp = %p\n", (void *)mp);
|
||||||
printf("nullfs_unmount(mp = %p)\n", (void *)mp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mntflags & MNT_FORCE)
|
if (mntflags & MNT_FORCE)
|
||||||
flags |= FORCECLOSE;
|
flags |= FORCECLOSE;
|
||||||
@ -257,7 +250,7 @@ nullfs_unmount(mp, mntflags, p)
|
|||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef NULLFS_DEBUG
|
||||||
vprint("alias root of lower", nullm_rootvp);
|
vprint("alias root of lower", nullm_rootvp);
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
@ -271,8 +264,9 @@ nullfs_unmount(mp, mntflags, p)
|
|||||||
/*
|
/*
|
||||||
* Finally, throw away the null_mount structure
|
* Finally, throw away the null_mount structure
|
||||||
*/
|
*/
|
||||||
free(mp->mnt_data, M_NULLFSMNT); /* XXX */
|
mntdata = mp->mnt_data;
|
||||||
mp->mnt_data = 0;
|
mp->mnt_data = 0;
|
||||||
|
free(mntdata, M_NULLFSMNT); /* XXX */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,29 +278,27 @@ nullfs_root(mp, vpp)
|
|||||||
struct proc *p = curproc; /* XXX */
|
struct proc *p = curproc; /* XXX */
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
|
||||||
printf("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
|
|
||||||
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
|
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
|
||||||
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
|
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return locked reference to root.
|
* Return locked reference to root.
|
||||||
*/
|
*/
|
||||||
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
|
||||||
VREF(vp);
|
VREF(vp);
|
||||||
|
#ifdef NULLFS_DEBUG
|
||||||
if (VOP_ISLOCKED(vp, NULL)) {
|
if (VOP_ISLOCKED(vp, NULL)) {
|
||||||
/*
|
/*
|
||||||
* XXX
|
* XXX
|
||||||
* Should we check type of node?
|
* Should we check type of node?
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG
|
|
||||||
printf("nullfs_root: multi null mount?\n");
|
printf("nullfs_root: multi null mount?\n");
|
||||||
#endif
|
|
||||||
vrele(vp);
|
vrele(vp);
|
||||||
return (EDEADLK);
|
return (EDEADLK);
|
||||||
} else
|
}
|
||||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
#endif
|
||||||
|
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
|
||||||
*vpp = vp;
|
*vpp = vp;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -331,11 +323,9 @@ nullfs_statfs(mp, sbp, p)
|
|||||||
int error;
|
int error;
|
||||||
struct statfs mstat;
|
struct statfs mstat;
|
||||||
|
|
||||||
#ifdef DEBUG
|
NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
|
||||||
printf("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
|
|
||||||
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
|
(void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
|
||||||
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
|
(void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
|
||||||
#endif
|
|
||||||
|
|
||||||
bzero(&mstat, sizeof(mstat));
|
bzero(&mstat, sizeof(mstat));
|
||||||
|
|
||||||
@ -440,7 +430,7 @@ static struct vfsops null_vfsops = {
|
|||||||
nullfs_checkexp,
|
nullfs_checkexp,
|
||||||
nullfs_vptofh,
|
nullfs_vptofh,
|
||||||
nullfs_init,
|
nullfs_init,
|
||||||
vfs_stduninit,
|
nullfs_uninit,
|
||||||
nullfs_extattrctl,
|
nullfs_extattrctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
*
|
*
|
||||||
* Ancestors:
|
* Ancestors:
|
||||||
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
|
* @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
|
||||||
* $FreeBSD$
|
|
||||||
* ...and...
|
* ...and...
|
||||||
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
|
* @(#)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_inactive(struct vop_inactive_args *ap);
|
||||||
static int null_lock(struct vop_lock_args *ap);
|
static int null_lock(struct vop_lock_args *ap);
|
||||||
static int null_lookup(struct vop_lookup_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_print(struct vop_print_args *ap);
|
||||||
static int null_reclaim(struct vop_reclaim_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_setattr(struct vop_setattr_args *ap);
|
||||||
static int null_unlock(struct vop_unlock_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)
|
if ((error = null_bypass((struct vop_generic_args *)ap)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,6 +486,66 @@ null_access(ap)
|
|||||||
return (null_bypass((struct vop_generic_args *)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
|
* We need to process our own vnode lock and then clear the
|
||||||
* interlock flag as it applies only to our vnode, not 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. */
|
/* After this assignment, this node will not be re-used. */
|
||||||
xp->null_lowervp = NULLVP;
|
xp->null_lowervp = NULLVP;
|
||||||
|
lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, ap->a_p);
|
||||||
LIST_REMOVE(xp, null_hash);
|
LIST_REMOVE(xp, null_hash);
|
||||||
|
lockmgr(&null_hashlock, LK_RELEASE, NULL, ap->a_p);
|
||||||
FREE(vp->v_data, M_TEMP);
|
FREE(vp->v_data, M_TEMP);
|
||||||
vp->v_data = NULL;
|
vp->v_data = NULL;
|
||||||
vrele (lowervp);
|
vrele (lowervp);
|
||||||
@ -593,13 +658,18 @@ vop_t **null_vnodeop_p;
|
|||||||
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
|
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
|
||||||
{ &vop_default_desc, (vop_t *) null_bypass },
|
{ &vop_default_desc, (vop_t *) null_bypass },
|
||||||
{ &vop_access_desc, (vop_t *) null_access },
|
{ &vop_access_desc, (vop_t *) null_access },
|
||||||
|
{ &vop_bmap_desc, (vop_t *) vop_eopnotsupp },
|
||||||
{ &vop_getattr_desc, (vop_t *) null_getattr },
|
{ &vop_getattr_desc, (vop_t *) null_getattr },
|
||||||
|
{ &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount},
|
||||||
{ &vop_inactive_desc, (vop_t *) null_inactive },
|
{ &vop_inactive_desc, (vop_t *) null_inactive },
|
||||||
{ &vop_lock_desc, (vop_t *) null_lock },
|
{ &vop_lock_desc, (vop_t *) null_lock },
|
||||||
{ &vop_lookup_desc, (vop_t *) null_lookup },
|
{ &vop_lookup_desc, (vop_t *) null_lookup },
|
||||||
|
{ &vop_open_desc, (vop_t *) null_open },
|
||||||
{ &vop_print_desc, (vop_t *) null_print },
|
{ &vop_print_desc, (vop_t *) null_print },
|
||||||
{ &vop_reclaim_desc, (vop_t *) null_reclaim },
|
{ &vop_reclaim_desc, (vop_t *) null_reclaim },
|
||||||
|
{ &vop_rename_desc, (vop_t *) null_rename },
|
||||||
{ &vop_setattr_desc, (vop_t *) null_setattr },
|
{ &vop_setattr_desc, (vop_t *) null_setattr },
|
||||||
|
{ &vop_strategy_desc, (vop_t *) vop_eopnotsupp },
|
||||||
{ &vop_unlock_desc, (vop_t *) null_unlock },
|
{ &vop_unlock_desc, (vop_t *) null_unlock },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user