xref: /original-bsd/sys/nfs/nfs_node.c (revision 27393bdf)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  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	8.4 (Berkeley) 03/30/95
11  */
12 
13 
14 #include <sys/param.h>
15 #include <sys/systm.h>
16 #include <sys/proc.h>
17 #include <sys/mount.h>
18 #include <sys/namei.h>
19 #include <sys/vnode.h>
20 #include <sys/kernel.h>
21 #include <sys/malloc.h>
22 
23 #include <nfs/rpcv2.h>
24 #include <nfs/nfsproto.h>
25 #include <nfs/nfs.h>
26 #include <nfs/nfsnode.h>
27 #include <nfs/nfsmount.h>
28 #include <nfs/nqnfs.h>
29 
30 LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
31 u_long nfsnodehash;
32 
33 #define TRUE	1
34 #define	FALSE	0
35 
36 /*
37  * Initialize hash links for nfsnodes
38  * and build nfsnode free list.
39  */
40 void
41 nfs_nhinit()
42 {
43 
44 #ifndef lint
45 	if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode))
46 		printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode));
47 #endif /* not lint */
48 	nfsnodehashtbl = hashinit(desiredvnodes, M_NFSNODE, &nfsnodehash);
49 }
50 
51 /*
52  * Compute an entry in the NFS hash table structure
53  */
54 u_long
55 nfs_hash(fhp, fhsize)
56 	register nfsfh_t *fhp;
57 	int fhsize;
58 {
59 	register u_char *fhpp;
60 	register u_long fhsum;
61 	register int i;
62 
63 	fhpp = &fhp->fh_bytes[0];
64 	fhsum = 0;
65 	for (i = 0; i < fhsize; i++)
66 		fhsum += *fhpp++;
67 	return (fhsum);
68 }
69 
70 /*
71  * Look up a vnode/nfsnode by file handle.
72  * Callers must check for mount points!!
73  * In all cases, a pointer to a
74  * nfsnode structure is returned.
75  */
76 int
77 nfs_nget(mntp, fhp, fhsize, npp)
78 	struct mount *mntp;
79 	register nfsfh_t *fhp;
80 	int fhsize;
81 	struct nfsnode **npp;
82 {
83 	register struct nfsnode *np;
84 	struct nfsnodehashhead *nhpp;
85 	register struct vnode *vp;
86 	extern int (**nfsv2_vnodeop_p)();
87 	struct vnode *nvp;
88 	int error;
89 
90 	nhpp = NFSNOHASH(nfs_hash(fhp, fhsize));
91 loop:
92 	for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
93 		if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
94 		    bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
95 			continue;
96 		vp = NFSTOV(np);
97 		if (vget(vp, 1))
98 			goto loop;
99 		*npp = np;
100 		return(0);
101 	}
102 	error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
103 	if (error) {
104 		*npp = 0;
105 		return (error);
106 	}
107 	vp = nvp;
108 	MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
109 	bzero((caddr_t)np, sizeof *np);
110 	vp->v_data = np;
111 	np->n_vnode = vp;
112 	/*
113 	 * Insert the nfsnode in the hash queue for its new file handle
114 	 */
115 	LIST_INSERT_HEAD(nhpp, np, n_hash);
116 	if (fhsize > NFS_SMALLFH) {
117 		MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK);
118 	} else
119 		np->n_fhp = &np->n_fh;
120 	bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
121 	np->n_fhsize = fhsize;
122 	*npp = np;
123 	return (0);
124 }
125 
126 int
127 nfs_inactive(ap)
128 	struct vop_inactive_args /* {
129 		struct vnode *a_vp;
130 	} */ *ap;
131 {
132 	register struct nfsnode *np;
133 	register struct sillyrename *sp;
134 	struct proc *p = curproc;	/* XXX */
135 	extern int prtactive;
136 
137 	np = VTONFS(ap->a_vp);
138 	if (prtactive && ap->a_vp->v_usecount != 0)
139 		vprint("nfs_inactive: pushing active", ap->a_vp);
140 	if (ap->a_vp->v_type != VDIR)
141 		sp = np->n_sillyrename;
142 	else
143 		sp = (struct sillyrename *)0;
144 	np->n_sillyrename = (struct sillyrename *)0;
145 	if (sp) {
146 		/*
147 		 * Remove the silly file that was rename'd earlier
148 		 */
149 		(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
150 		nfs_removeit(sp);
151 		crfree(sp->s_cred);
152 		vrele(sp->s_dvp);
153 		FREE((caddr_t)sp, M_NFSREQ);
154 	}
155 	np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
156 		NQNFSNONCACHE | NQNFSWRITE);
157 	return (0);
158 }
159 
160 /*
161  * Reclaim an nfsnode so that it can be used for other purposes.
162  */
163 int
164 nfs_reclaim(ap)
165 	struct vop_reclaim_args /* {
166 		struct vnode *a_vp;
167 	} */ *ap;
168 {
169 	register struct vnode *vp = ap->a_vp;
170 	register struct nfsnode *np = VTONFS(vp);
171 	register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
172 	register struct nfsdmap *dp, *dp2;
173 	extern int prtactive;
174 
175 	if (prtactive && vp->v_usecount != 0)
176 		vprint("nfs_reclaim: pushing active", vp);
177 
178 	LIST_REMOVE(np, n_hash);
179 
180 	/*
181 	 * For nqnfs, take it off the timer queue as required.
182 	 */
183 	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
184 		CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
185 	}
186 
187 	/*
188 	 * Free up any directory cookie structures and
189 	 * large file handle structures that might be associated with
190 	 * this nfs node.
191 	 */
192 	if (vp->v_type == VDIR) {
193 		dp = np->n_cookies.lh_first;
194 		while (dp) {
195 			dp2 = dp;
196 			dp = dp->ndm_list.le_next;
197 			FREE((caddr_t)dp2, M_NFSDIROFF);
198 		}
199 	}
200 	if (np->n_fhsize > NFS_SMALLFH) {
201 		FREE((caddr_t)np->n_fhp, M_NFSBIGFH);
202 	}
203 
204 	cache_purge(vp);
205 	FREE(vp->v_data, M_NFSNODE);
206 	vp->v_data = (void *)0;
207 	return (0);
208 }
209 
210 /*
211  * Lock an nfsnode
212  */
213 int
214 nfs_lock(ap)
215 	struct vop_lock_args /* {
216 		struct vnode *a_vp;
217 	} */ *ap;
218 {
219 	register struct vnode *vp = ap->a_vp;
220 
221 	/*
222 	 * Ugh, another place where interruptible mounts will get hung.
223 	 * If you make this sleep interruptible, then you have to fix all
224 	 * the VOP_LOCK() calls to expect interruptibility.
225 	 */
226 	while (vp->v_flag & VXLOCK) {
227 		vp->v_flag |= VXWANT;
228 		(void) tsleep((caddr_t)vp, PINOD, "nfslck", 0);
229 	}
230 	if (vp->v_tag == VT_NON)
231 		return (ENOENT);
232 	return (0);
233 }
234 
235 /*
236  * Unlock an nfsnode
237  */
238 int
239 nfs_unlock(ap)
240 	struct vop_unlock_args /* {
241 		struct vnode *a_vp;
242 	} */ *ap;
243 {
244 
245 	return (0);
246 }
247 
248 /*
249  * Check for a locked nfsnode
250  */
251 int
252 nfs_islocked(ap)
253 	struct vop_islocked_args /* {
254 		struct vnode *a_vp;
255 	} */ *ap;
256 {
257 
258 	return (0);
259 }
260 
261 /*
262  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
263  * done. Currently nothing to do.
264  */
265 /* ARGSUSED */
266 int
267 nfs_abortop(ap)
268 	struct vop_abortop_args /* {
269 		struct vnode *a_dvp;
270 		struct componentname *a_cnp;
271 	} */ *ap;
272 {
273 
274 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
275 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
276 	return (0);
277 }
278