* Copyright (c) 1989 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
* %sccs.include.redist.c%
* @(#)nfs_node.c 7.47 (Berkeley) %G%
#include <nfs/nfsmount.h>
struct nfsnode
**nheadhashtbl
;
#define NFSNOHASH(fhsum) ((fhsum)&nheadhash)
* Initialize hash links for nfsnodes
* and build nfsnode free list.
if ((sizeof(struct nfsnode
) - 1) & sizeof(struct nfsnode
))
printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode
));
nheadhashtbl
= hashinit(desiredvnodes
, M_NFSNODE
, &nheadhash
);
* Compute an entry in the NFS hash table structure
fhpp
= &fhp
->fh_bytes
[0];
for (i
= 0; i
< NFSX_FH
; i
++)
return (&nheadhashtbl
[NFSNOHASH(fhsum
)]);
* Look up a vnode/nfsnode by file handle.
* Callers must check for mount points!!
* In all cases, a pointer to a
* nfsnode structure is returned.
register struct nfsnode
*np
, *nq
, **nhpp
;
register struct vnode
*vp
;
extern int (**nfsv2_vnodeop_p
)();
for (np
= *nhpp
; np
; np
= np
->n_forw
) {
if (mntp
!= NFSTOV(np
)->v_mount
||
bcmp((caddr_t
)fhp
, (caddr_t
)&np
->n_fh
, NFSX_FH
))
if (error
= getnewvnode(VT_NFS
, mntp
, nfsv2_vnodeop_p
, &nvp
)) {
MALLOC(np
, struct nfsnode
*, sizeof *np
, M_NFSNODE
, M_WAITOK
);
* Insert the nfsnode in the hash queue for its new file handle
nq
->n_back
= &np
->n_forw
;
bcopy((caddr_t
)fhp
, (caddr_t
)&np
->n_fh
, NFSX_FH
);
np
->n_sillyrename
= (struct sillyrename
*)0;
if (VFSTONFS(mntp
)->nm_flag
& NFSMNT_NQNFS
) {
np
->n_expiry
= (time_t)0;
np
->n_tnext
= (struct nfsnode
*)0;
struct vop_inactive_args
/* {
register struct nfsnode
*np
;
register struct sillyrename
*sp
;
struct proc
*p
= curproc
; /* XXX */
if (prtactive
&& ap
->a_vp
->v_usecount
!= 0)
vprint("nfs_inactive: pushing active", ap
->a_vp
);
np
->n_sillyrename
= (struct sillyrename
*)0;
* Remove the silly file that was rename'd earlier
(void) nfs_vinvalbuf(ap
->a_vp
, 0, sp
->s_cred
, p
, 1);
free((caddr_t
)sp
, M_NFSREQ
);
np
->n_flag
&= (NMODIFIED
| NFLUSHINPROG
| NFLUSHWANT
| NQNFSEVICTED
);
* Reclaim an nfsnode so that it can be used for other purposes.
struct vop_reclaim_args
/* {
register struct vnode
*vp
= ap
->a_vp
;
register struct nfsnode
*np
= VTONFS(vp
);
register struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
register struct nfsnode
*nq
;
if (prtactive
&& vp
->v_usecount
!= 0)
vprint("nfs_reclaim: pushing active", vp
);
* Remove the nfsnode from its hash chain.
* For nqnfs, take it off the timer queue as required.
if ((nmp
->nm_flag
& NFSMNT_NQNFS
) && np
->n_tnext
) {
if (np
->n_tnext
== (struct nfsnode
*)nmp
)
nmp
->nm_tprev
= np
->n_tprev
;
np
->n_tnext
->n_tprev
= np
->n_tprev
;
if (np
->n_tprev
== (struct nfsnode
*)nmp
)
nmp
->nm_tnext
= np
->n_tnext
;
np
->n_tprev
->n_tnext
= np
->n_tnext
;
FREE(vp
->v_data
, M_NFSNODE
);
struct vop_lock_args
/* {
register struct vnode
*vp
= ap
->a_vp
;
* Ugh, another place where interruptible mounts will get hung.
* If you make this sleep interruptible, then you have to fix all
* the VOP_LOCK() calls to expect interruptibility.
while (vp
->v_flag
& VXLOCK
) {
sleep((caddr_t
)vp
, PINOD
);
struct vop_unlock_args
/* {
* Check for a locked nfsnode
struct vop_islocked_args
/* {
* Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
* done. Currently nothing to do.
struct vop_abortop_args
/* {
struct componentname *a_cnp;
if ((ap
->a_cnp
->cn_flags
& (HASBUF
| SAVESTART
)) == HASBUF
)
FREE(ap
->a_cnp
->cn_pnbuf
, M_NAMEI
);