xref: /original-bsd/sys/nfs/nfs_node.c (revision 155be1a3)
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.37 (Berkeley) 01/22/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 struct vnodeops nfsv2_vnodeops;
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_vnodeops, &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(vp, p)
144 	struct vnode *vp;
145 	struct proc *p;
146 {
147 	register struct nfsnode *np;
148 	register struct sillyrename *sp;
149 	extern int prtactive;
150 
151 	np = VTONFS(vp);
152 	if (prtactive && vp->v_usecount != 0)
153 		vprint("nfs_inactive: pushing active", vp);
154 	sp = np->n_sillyrename;
155 	np->n_sillyrename = (struct sillyrename *)0;
156 	if (sp) {
157 		/*
158 		 * Remove the silly file that was rename'd earlier
159 		 */
160 		nfs_removeit(sp, p);
161 		crfree(sp->s_cred);
162 		vrele(sp->s_dvp);
163 #ifdef SILLYSEPARATE
164 		free((caddr_t)sp, M_NFSREQ);
165 #endif
166 	}
167 	np->n_flag &= NMODIFIED;
168 	return (0);
169 }
170 
171 /*
172  * Reclaim an nfsnode so that it can be used for other purposes.
173  */
174 nfs_reclaim(vp)
175 	register struct vnode *vp;
176 {
177 	register struct nfsnode *np = VTONFS(vp);
178 	register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
179 	extern int prtactive;
180 
181 	if (prtactive && vp->v_usecount != 0)
182 		vprint("nfs_reclaim: pushing active", vp);
183 	/*
184 	 * Remove the nfsnode from its hash chain.
185 	 */
186 	remque(np);
187 
188 	/*
189 	 * For nqnfs, take it off the timer queue as required.
190 	 */
191 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_tnext) {
192 		if (np->n_tnext == (struct nfsnode *)nmp)
193 			nmp->nm_tprev = np->n_tprev;
194 		else
195 			np->n_tnext->n_tprev = np->n_tprev;
196 		if (np->n_tprev == (struct nfsnode *)nmp)
197 			nmp->nm_tnext = np->n_tnext;
198 		else
199 			np->n_tprev->n_tnext = np->n_tnext;
200 	}
201 	cache_purge(vp);
202 	FREE(vp->v_data, M_NFSNODE);
203 	vp->v_data = (void *)0;
204 	return (0);
205 }
206 
207 /*
208  * Lock an nfsnode
209  */
210 nfs_lock(vp)
211 	struct vnode *vp;
212 {
213 
214 	return (0);
215 }
216 
217 /*
218  * Unlock an nfsnode
219  */
220 nfs_unlock(vp)
221 	struct vnode *vp;
222 {
223 
224 	return (0);
225 }
226 
227 /*
228  * Check for a locked nfsnode
229  */
230 nfs_islocked(vp)
231 	struct vnode *vp;
232 {
233 
234 	return (0);
235 }
236 
237 /*
238  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
239  * done. Currently nothing to do.
240  */
241 /* ARGSUSED */
242 int
243 nfs_abortop(dvp, cnp)
244 	struct vnode *dvp;
245 	struct componentname *cnp;
246 {
247 
248 	if ((cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
249 		FREE(cnp->cn_pnbuf, M_NAMEI);
250 	return (0);
251 }
252