xref: /original-bsd/sys/nfs/nfs_node.c (revision 3b6250d9)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)nfs_node.c	7.39 (Berkeley) 05/15/92
11  */
12 
13 #include "param.h"
14 #include "systm.h"
15 #include "proc.h"
16 #include "mount.h"
17 #include "namei.h"
18 #include "vnode.h"
19 #include "kernel.h"
20 #include "malloc.h"
21 
22 #include "rpcv2.h"
23 #include "nfsv2.h"
24 #include "nfs.h"
25 #include "nfsnode.h"
26 #include "nfsmount.h"
27 #include "nqnfs.h"
28 
29 /* The request list head */
30 extern struct nfsreq nfsreqh;
31 
32 #define	NFSNOHSZ	512
33 #if	((NFSNOHSZ&(NFSNOHSZ-1)) == 0)
34 #define	NFSNOHASH(fhsum)	((fhsum)&(NFSNOHSZ-1))
35 #else
36 #define	NFSNOHASH(fhsum)	(((unsigned)(fhsum))%NFSNOHSZ)
37 #endif
38 
39 union nhead {
40 	union  nhead *nh_head[2];
41 	struct nfsnode *nh_chain[2];
42 } nhead[NFSNOHSZ];
43 
44 #define TRUE	1
45 #define	FALSE	0
46 
47 /*
48  * Initialize hash links for nfsnodes
49  * and build nfsnode free list.
50  */
51 nfs_nhinit()
52 {
53 	register int i;
54 	register union  nhead *nh = nhead;
55 
56 #ifndef lint
57 	if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode))
58 		printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode));
59 #endif /* not lint */
60 	for (i = NFSNOHSZ; --i >= 0; nh++) {
61 		nh->nh_head[0] = nh;
62 		nh->nh_head[1] = nh;
63 	}
64 }
65 
66 /*
67  * Compute an entry in the NFS hash table structure
68  */
69 union nhead *
70 nfs_hash(fhp)
71 	register nfsv2fh_t *fhp;
72 {
73 	register u_char *fhpp;
74 	register u_long fhsum;
75 	int i;
76 
77 	fhpp = &fhp->fh_bytes[0];
78 	fhsum = 0;
79 	for (i = 0; i < NFSX_FH; i++)
80 		fhsum += *fhpp++;
81 	return (&nhead[NFSNOHASH(fhsum)]);
82 }
83 
84 /*
85  * Look up a vnode/nfsnode by file handle.
86  * Callers must check for mount points!!
87  * In all cases, a pointer to a
88  * nfsnode structure is returned.
89  */
90 nfs_nget(mntp, fhp, npp)
91 	struct mount *mntp;
92 	register nfsv2fh_t *fhp;
93 	struct nfsnode **npp;
94 {
95 	register struct nfsnode *np;
96 	register struct vnode *vp;
97 	extern int (**nfsv2_vnodeop_p)();
98 	struct vnode *nvp;
99 	union nhead *nh;
100 	int error;
101 
102 	nh = nfs_hash(fhp);
103 loop:
104 	for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) {
105 		if (mntp != NFSTOV(np)->v_mount ||
106 		    bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
107 			continue;
108 		vp = NFSTOV(np);
109 		if (vget(vp))
110 			goto loop;
111 		*npp = np;
112 		return(0);
113 	}
114 	if (error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp)) {
115 		*npp = 0;
116 		return (error);
117 	}
118 	vp = nvp;
119 	MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
120 	vp->v_data = np;
121 	np->n_vnode = vp;
122 	/*
123 	 * Insert the nfsnode in the hash queue for its new file handle
124 	 */
125 	np->n_flag = 0;
126 	insque(np, nh);
127 	bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
128 	np->n_attrstamp = 0;
129 	np->n_direofoffset = 0;
130 	np->n_sillyrename = (struct sillyrename *)0;
131 	np->n_size = 0;
132 	if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
133 		ZEROQUAD(np->n_brev);
134 		ZEROQUAD(np->n_lrev);
135 		np->n_expiry = (time_t)0;
136 		np->n_tnext = (struct nfsnode *)0;
137 	} else
138 		np->n_mtime = 0;
139 	*npp = np;
140 	return (0);
141 }
142 
143 nfs_inactive (ap)
144 	struct vop_inactive_args *ap;
145 {
146 	register struct nfsnode *np;
147 	register struct sillyrename *sp;
148 	extern int prtactive;
149 
150 	np = VTONFS(ap->a_vp);
151 	if (prtactive && ap->a_vp->v_usecount != 0)
152 		vprint("nfs_inactive: pushing active", ap->a_vp);
153 	sp = np->n_sillyrename;
154 	np->n_sillyrename = (struct sillyrename *)0;
155 	if (sp) {
156 		/*
157 		 * Remove the silly file that was rename'd earlier
158 		 */
159 		nfs_removeit(sp, ap->a_p);
160 		crfree(sp->s_cred);
161 		vrele(sp->s_dvp);
162 #ifdef SILLYSEPARATE
163 		free((caddr_t)sp, M_NFSREQ);
164 #endif
165 	}
166 	np->n_flag &= NMODIFIED;
167 	return (0);
168 }
169 
170 /*
171  * Reclaim an nfsnode so that it can be used for other purposes.
172  */
173 nfs_reclaim (ap)
174 	struct vop_reclaim_args *ap;
175 {
176 	register struct nfsnode *np = VTONFS(ap->a_vp);
177 	register struct nfsmount *nmp = VFSTONFS(ap->a_vp->v_mount);
178 	extern int prtactive;
179 
180 	if (prtactive && ap->a_vp->v_usecount != 0)
181 		vprint("nfs_reclaim: pushing active", ap->a_vp);
182 	/*
183 	 * Remove the nfsnode from its hash chain.
184 	 */
185 	remque(np);
186 
187 	/*
188 	 * For nqnfs, take it off the timer queue as required.
189 	 */
190 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) {
191 		if (np->n_tnext == (struct nfsnode *)nmp)
192 			nmp->nm_tprev = np->n_tprev;
193 		else
194 			np->n_tnext->n_tprev = np->n_tprev;
195 		if (np->n_tprev == (struct nfsnode *)nmp)
196 			nmp->nm_tnext = np->n_tnext;
197 		else
198 			np->n_tprev->n_tnext = np->n_tnext;
199 	}
200 	cache_purge(ap->a_vp);
201 	FREE(ap->a_vp->v_data, M_NFSNODE);
202 	ap->a_vp->v_data = (void *)0;
203 	return (0);
204 }
205 
206 /*
207  * Lock an nfsnode
208  */
209 nfs_lock (ap)
210 	struct vop_lock_args *ap;
211 {
212 
213 	return (0);
214 }
215 
216 /*
217  * Unlock an nfsnode
218  */
219 nfs_unlock (ap)
220 	struct vop_unlock_args *ap;
221 {
222 
223 	return (0);
224 }
225 
226 /*
227  * Check for a locked nfsnode
228  */
229 nfs_islocked (ap)
230 	struct vop_islocked_args *ap;
231 {
232 
233 	return (0);
234 }
235 
236 /*
237  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
238  * done. Currently nothing to do.
239  */
240 /* ARGSUSED */
241 int
242 nfs_abortop (ap)
243 	struct vop_abortop_args *ap;
244 {
245 
246 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
247 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
248 	return (0);
249 }
250