138415Smckusick /*
263233Sbostic * Copyright (c) 1989, 1993
363233Sbostic * The Regents of the University of California. All rights reserved.
438415Smckusick *
538415Smckusick * This code is derived from software contributed to Berkeley by
638415Smckusick * Rick Macklem at The University of Guelph.
738415Smckusick *
844509Sbostic * %sccs.include.redist.c%
938415Smckusick *
10*69607Smckusick * @(#)nfs_node.c 8.6 (Berkeley) 05/22/95
1138415Smckusick */
1238415Smckusick
1368653Smckusick
1456535Sbostic #include <sys/param.h>
1556535Sbostic #include <sys/systm.h>
1656535Sbostic #include <sys/proc.h>
1756535Sbostic #include <sys/mount.h>
1856535Sbostic #include <sys/namei.h>
1956535Sbostic #include <sys/vnode.h>
2056535Sbostic #include <sys/kernel.h>
2156535Sbostic #include <sys/malloc.h>
2247573Skarels
2356535Sbostic #include <nfs/rpcv2.h>
2468653Smckusick #include <nfs/nfsproto.h>
2556535Sbostic #include <nfs/nfs.h>
2656535Sbostic #include <nfs/nfsnode.h>
2756535Sbostic #include <nfs/nfsmount.h>
2856535Sbostic #include <nfs/nqnfs.h>
2938415Smckusick
LIST_HEAD(nfsnodehashhead,nfsnode)3067708Smckusick LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
3167708Smckusick u_long nfsnodehash;
3238415Smckusick
3338884Smacklem #define TRUE 1
3438884Smacklem #define FALSE 0
3538884Smacklem
3638415Smckusick /*
3738415Smckusick * Initialize hash links for nfsnodes
3838415Smckusick * and build nfsnode free list.
3938415Smckusick */
4068653Smckusick void
4138415Smckusick nfs_nhinit()
4238415Smckusick {
4338415Smckusick
4439494Smckusick #ifndef lint
4551985Smckusick if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode))
4651985Smckusick printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode));
4739494Smckusick #endif /* not lint */
4867708Smckusick nfsnodehashtbl = hashinit(desiredvnodes, M_NFSNODE, &nfsnodehash);
4938415Smckusick }
5038415Smckusick
5138415Smckusick /*
5239445Smckusick * Compute an entry in the NFS hash table structure
5339445Smckusick */
5468653Smckusick u_long
nfs_hash(fhp,fhsize)5568653Smckusick nfs_hash(fhp, fhsize)
5668653Smckusick register nfsfh_t *fhp;
5768653Smckusick int fhsize;
5839445Smckusick {
5939445Smckusick register u_char *fhpp;
6039445Smckusick register u_long fhsum;
6168653Smckusick register int i;
6239445Smckusick
6339445Smckusick fhpp = &fhp->fh_bytes[0];
6439445Smckusick fhsum = 0;
6568653Smckusick for (i = 0; i < fhsize; i++)
6639445Smckusick fhsum += *fhpp++;
6768653Smckusick return (fhsum);
6839445Smckusick }
6939445Smckusick
7039445Smckusick /*
7139395Smckusick * Look up a vnode/nfsnode by file handle.
7238415Smckusick * Callers must check for mount points!!
7338415Smckusick * In all cases, a pointer to a
7438415Smckusick * nfsnode structure is returned.
7538415Smckusick */
7668653Smckusick int
nfs_nget(mntp,fhp,fhsize,npp)7768653Smckusick nfs_nget(mntp, fhp, fhsize, npp)
7838415Smckusick struct mount *mntp;
7968653Smckusick register nfsfh_t *fhp;
8068653Smckusick int fhsize;
8138415Smckusick struct nfsnode **npp;
8238415Smckusick {
8369423Smckusick struct proc *p = curproc; /* XXX */
8469423Smckusick struct nfsnode *np;
8567708Smckusick struct nfsnodehashhead *nhpp;
8638415Smckusick register struct vnode *vp;
8753550Sheideman extern int (**nfsv2_vnodeop_p)();
8839395Smckusick struct vnode *nvp;
8939445Smckusick int error;
9038415Smckusick
9168653Smckusick nhpp = NFSNOHASH(nfs_hash(fhp, fhsize));
9238415Smckusick loop:
9367708Smckusick for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
9468653Smckusick if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
9568653Smckusick bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
9639395Smckusick continue;
9739395Smckusick vp = NFSTOV(np);
9869423Smckusick if (vget(vp, LK_EXCLUSIVE, p))
9939445Smckusick goto loop;
10039395Smckusick *npp = np;
10139395Smckusick return(0);
10238884Smacklem }
10368653Smckusick error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
10468653Smckusick if (error) {
10538415Smckusick *npp = 0;
10639395Smckusick return (error);
10738415Smckusick }
10839395Smckusick vp = nvp;
10951985Smckusick MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
11068653Smckusick bzero((caddr_t)np, sizeof *np);
11151985Smckusick vp->v_data = np;
11239395Smckusick np->n_vnode = vp;
11338415Smckusick /*
11438884Smacklem * Insert the nfsnode in the hash queue for its new file handle
11538884Smacklem */
11667708Smckusick LIST_INSERT_HEAD(nhpp, np, n_hash);
11768653Smckusick if (fhsize > NFS_SMALLFH) {
11868653Smckusick MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK);
11968653Smckusick } else
12068653Smckusick np->n_fhp = &np->n_fh;
12168653Smckusick bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
12268653Smckusick np->n_fhsize = fhsize;
12338415Smckusick *npp = np;
12438415Smckusick return (0);
12538415Smckusick }
12638415Smckusick
12768653Smckusick int
nfs_inactive(ap)12854666Smckusick nfs_inactive(ap)
12954666Smckusick struct vop_inactive_args /* {
13054666Smckusick struct vnode *a_vp;
131*69607Smckusick struct proc *a_p;
13254666Smckusick } */ *ap;
13338415Smckusick {
13438415Smckusick register struct nfsnode *np;
13538415Smckusick register struct sillyrename *sp;
13657784Smckusick struct proc *p = curproc; /* XXX */
13739575Smckusick extern int prtactive;
13838415Smckusick
13953599Sheideman np = VTONFS(ap->a_vp);
14053599Sheideman if (prtactive && ap->a_vp->v_usecount != 0)
14153599Sheideman vprint("nfs_inactive: pushing active", ap->a_vp);
14268653Smckusick if (ap->a_vp->v_type != VDIR)
14368653Smckusick sp = np->n_sillyrename;
14468653Smckusick else
14568653Smckusick sp = (struct sillyrename *)0;
14639395Smckusick np->n_sillyrename = (struct sillyrename *)0;
14739395Smckusick if (sp) {
14838415Smckusick /*
14939395Smckusick * Remove the silly file that was rename'd earlier
15038415Smckusick */
15157784Smckusick (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
15254447Smckusick nfs_removeit(sp);
15348364Smckusick crfree(sp->s_cred);
15448364Smckusick vrele(sp->s_dvp);
15568653Smckusick FREE((caddr_t)sp, M_NFSREQ);
15639395Smckusick }
15759705Smckusick np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
15859705Smckusick NQNFSNONCACHE | NQNFSWRITE);
159*69607Smckusick VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
16039395Smckusick return (0);
16139395Smckusick }
16239395Smckusick
16339395Smckusick /*
16439395Smckusick * Reclaim an nfsnode so that it can be used for other purposes.
16539395Smckusick */
16668653Smckusick int
nfs_reclaim(ap)16754666Smckusick nfs_reclaim(ap)
16854666Smckusick struct vop_reclaim_args /* {
16954666Smckusick struct vnode *a_vp;
17054666Smckusick } */ *ap;
17139395Smckusick {
17254666Smckusick register struct vnode *vp = ap->a_vp;
17354666Smckusick register struct nfsnode *np = VTONFS(vp);
17454666Smckusick register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
17568653Smckusick register struct nfsdmap *dp, *dp2;
17639575Smckusick extern int prtactive;
17739395Smckusick
17854666Smckusick if (prtactive && vp->v_usecount != 0)
17954666Smckusick vprint("nfs_reclaim: pushing active", vp);
18068653Smckusick
18167708Smckusick LIST_REMOVE(np, n_hash);
18252196Smckusick
18352196Smckusick /*
18452196Smckusick * For nqnfs, take it off the timer queue as required.
18552196Smckusick */
18668653Smckusick if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
18767708Smckusick CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
18868653Smckusick }
18968653Smckusick
19068653Smckusick /*
19168653Smckusick * Free up any directory cookie structures and
19268653Smckusick * large file handle structures that might be associated with
19368653Smckusick * this nfs node.
19468653Smckusick */
19568653Smckusick if (vp->v_type == VDIR) {
19668653Smckusick dp = np->n_cookies.lh_first;
19768653Smckusick while (dp) {
19868653Smckusick dp2 = dp;
19968653Smckusick dp = dp->ndm_list.le_next;
20068653Smckusick FREE((caddr_t)dp2, M_NFSDIROFF);
20168653Smckusick }
20268653Smckusick }
20368653Smckusick if (np->n_fhsize > NFS_SMALLFH) {
20468653Smckusick FREE((caddr_t)np->n_fhp, M_NFSBIGFH);
20568653Smckusick }
20668653Smckusick
20754666Smckusick cache_purge(vp);
20854666Smckusick FREE(vp->v_data, M_NFSNODE);
20954666Smckusick vp->v_data = (void *)0;
21038415Smckusick return (0);
21138415Smckusick }
21238415Smckusick
21338415Smckusick /*
21442467Smckusick * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
21542467Smckusick * done. Currently nothing to do.
21642467Smckusick */
21742467Smckusick /* ARGSUSED */
21852234Sheideman int
nfs_abortop(ap)21954666Smckusick nfs_abortop(ap)
22054666Smckusick struct vop_abortop_args /* {
22154666Smckusick struct vnode *a_dvp;
22254666Smckusick struct componentname *a_cnp;
22354666Smckusick } */ *ap;
22438415Smckusick {
22538415Smckusick
22653599Sheideman if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
22753599Sheideman FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
22842467Smckusick return (0);
22938415Smckusick }
230