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