* Copyright (c) 1992 The Regents of the University of California
* Copyright (c) 1990, 1992 Jan-Simon Pendry
* This code is derived from software donated to Berkeley by
* %sccs.include.redist.c%
* @(#)lofs_subr.c 1.2 (Berkeley) 6/18/92
* $Id: lofs_subr.c,v 1.11 1992/05/30 10:05:43 jsp Exp jsp $
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NNULLNODECACHE 16
#define NULL_NHASH(vp) ((((u_long)vp)>>LOG2_SIZEVNODE) & (NNULLNODECACHE-1))
* Each cache entry holds a reference to the target vnode
* along with a pointer to the alias vnode. When an
* entry is added the target vnode is VREF'd. When the
* alias is removed the target vnode is vrele'd.
struct null_node
*ac_forw
;
struct null_node
*ac_back
;
static struct null_node_cache null_node_cache
[NNULLNODECACHE
];
* Initialise cache headers
struct null_node_cache
*ac
;
printf("nullfs_init\n"); /* printed during system boot */
for (ac
= null_node_cache
; ac
< null_node_cache
+ NNULLNODECACHE
; ac
++)
ac
->ac_forw
= ac
->ac_back
= (struct null_node
*) ac
;
* Compute hash list for given target vnode
static struct null_node_cache
*
return (&null_node_cache
[NULL_NHASH(targetvp
)]);
* Make a new null_node node.
* Vp is the alias vnode, lofsvp is the target vnode.
* Maintain a reference to (targetvp).
null_node_alloc(vp
, targetvp
)
struct null_node_cache
*hd
;
printf("null_node_alloc(%x, %x)\n", vp
, targetvp
);
MALLOC(a
, struct null_node
*, sizeof(struct null_node
), M_TEMP
, M_WAITOK
);
a
->null_lowervp
= targetvp
;
hd
= null_node_hash(targetvp
);
vprint("alloc targetvp", targetvp
);
struct null_node_cache
*ac
;
printf("null_node_flushmp (%x)\n", mp
);
roota
= VTONULLNODE(MOUNTTONULLMOUNT(mp
)->nullm_rootvp
);
for (ac
= null_node_cache
; ac
< null_node_cache
+ NNULLNODECACHE
; ac
++) {
struct null_node
*a
= ac
->ac_forw
;
while (a
!= (struct null_node
*) ac
) {
if (a
!= roota
&& a
->null_vnode
->v_mount
== mp
) {
struct vnode
*vp
= a
->null_lowervp
;
vprint("would vrele", vp
);
printf("null_node: vrele'd %d aliases\n", i
);
* Return alias for target vnode if already exists, else 0.
static struct null_node
*
null_node_find(mp
, targetvp
)
struct null_node_cache
*hd
;
printf("null_node_find(mp = %x, target = %x)\n", mp
, targetvp
);
* Find hash base, and then search the (two-way) linked
* list looking for a null_node structure which is referencing
* the target vnode. If found, the increment the null_node
* reference count (but NOT the target vnode's VREF counter).
hd
= null_node_hash(targetvp
);
for (a
= hd
->ac_forw
; a
!= (struct null_node
*) hd
; a
= a
->null_forw
) {
if (a
->null_lowervp
== targetvp
&& a
->null_vnode
->v_mount
== mp
) {
printf("null_node_find(%x): found (%x,%x)->%x\n",
targetvp
, mp
, a
->null_vnode
, targetvp
);
printf("null_node_find(%x, %x): NOT found\n", mp
, targetvp
);
null_node_alias(mp
, targetvp
, newvpp
)
if (targetvp
->v_type
!= VDIR
|| targetvp
->v_op
== null_vnodeop_p
) {
ap
= null_node_find(mp
, targetvp
);
* Take another reference to the alias vnode
vprint("null_node_alias: exists", ap
->null_vnode
);
aliasvp
= ap
->null_vnode
;
printf("null_node_alias: create new alias vnode\n");
if (error
= getnewvnode(VT_UFS
, mp
, null_vnodeop_p
, &aliasvp
))
return (error
); /* XXX: VT_LOFS above */
* Make new vnode reference the null_node.
null_node_alloc(aliasvp
, targetvp
);
* aliasvp is already VREF'd by getnewvnode()
vprint("null_node_alias alias", aliasvp
);
vprint("null_node_alias target", targetvp
);
* Try to find an existing null_node vnode refering
* to it, otherwise make a new null_node vnode which
* contains a reference to the target vnode.
printf("make_null_node(mp = %x, vp = %x\n", mp
, *vpp
);
* (targetvp) is locked at this point.
panic("make_null_node: null vp");
* Try to find an existing reference to the target vnodes.
return (null_node_alias(mp
, targetvp
, vpp
));
null_checkvp(vp
, fil
, lno
)
struct null_node
*a
= VTONULLNODE(vp
);
if (a
->null_lowervp
== 0) {
printf("vp = %x, ZERO ptr\n", vp
);
for (p
= (u_long
*) a
, i
= 0; i
< 8; i
++)
printf("aliasvp %x/%d -> %x/%d [%s, %d]\n",
a
->null_vnode
, a
->null_vnode
->v_usecount
,
a
->null_lowervp
, a
->null_lowervp
? a
->null_lowervp
->v_usecount
: -42,