Annotation of src/sys/nfs/nfs_node.c, Revision 1.56
1.56 ! matt 1: /* $NetBSD: nfs_node.c,v 1.55 2002/10/01 14:59:21 christos Exp $ */
1.12 cgd 2:
1.1 cgd 3: /*
1.9 mycroft 4: * Copyright (c) 1989, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * This code is derived from software contributed to Berkeley by
8: * Rick Macklem at The University of Guelph.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the University of
21: * California, Berkeley and its contributors.
22: * 4. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: *
1.16 fvdl 38: * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
1.1 cgd 39: */
1.47 lukem 40:
41: #include <sys/cdefs.h>
1.56 ! matt 42: __KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.55 2002/10/01 14:59:21 christos Exp $");
1.1 cgd 43:
1.35 bjh21 44: #include "opt_nfs.h"
1.16 fvdl 45:
1.4 mycroft 46: #include <sys/param.h>
47: #include <sys/systm.h>
48: #include <sys/proc.h>
49: #include <sys/mount.h>
50: #include <sys/namei.h>
51: #include <sys/vnode.h>
52: #include <sys/kernel.h>
53: #include <sys/malloc.h>
1.28 thorpej 54: #include <sys/pool.h>
1.22 fvdl 55: #include <sys/lock.h>
1.48 lukem 56: #include <sys/hash.h>
1.1 cgd 57:
1.9 mycroft 58: #include <nfs/rpcv2.h>
1.16 fvdl 59: #include <nfs/nfsproto.h>
1.4 mycroft 60: #include <nfs/nfs.h>
61: #include <nfs/nfsnode.h>
62: #include <nfs/nfsmount.h>
1.9 mycroft 63: #include <nfs/nqnfs.h>
1.15 christos 64: #include <nfs/nfs_var.h>
1.1 cgd 65:
1.56 ! matt 66: struct nfsnodehashhead *nfsnodehashtbl;
1.13 mycroft 67: u_long nfsnodehash;
1.22 fvdl 68: struct lock nfs_hashlock;
1.1 cgd 69:
1.28 thorpej 70: struct pool nfs_node_pool; /* memory pool for nfs nodes */
71: struct pool nfs_vattr_pool; /* memory pool for nfs vattrs */
72:
1.41 tsutsui 73: extern int prtactive;
74:
1.1 cgd 75: #define TRUE 1
76: #define FALSE 0
77:
1.48 lukem 78: #define nfs_hash(x,y) hash32_buf((x), (y), HASH32_BUF_INIT)
79:
1.46 chs 80: void nfs_gop_size(struct vnode *, off_t, off_t *);
81: int nfs_gop_alloc(struct vnode *, off_t, off_t, int, struct ucred *);
1.53 chs 82: int nfs_gop_write(struct vnode *, struct vm_page **, int, int);
1.46 chs 83:
84: struct genfs_ops nfs_genfsops = {
85: nfs_gop_size,
86: nfs_gop_alloc,
1.53 chs 87: nfs_gop_write,
1.46 chs 88: };
89:
1.1 cgd 90: /*
91: * Initialize hash links for nfsnodes
92: * and build nfsnode free list.
93: */
1.15 christos 94: void
1.1 cgd 95: nfs_nhinit()
96: {
97:
1.37 ad 98: nfsnodehashtbl = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE,
99: M_WAITOK, &nfsnodehash);
1.22 fvdl 100: lockinit(&nfs_hashlock, PINOD, "nfs_hashlock", 0, 0);
1.28 thorpej 101:
102: pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl",
1.52 thorpej 103: &pool_allocator_nointr);
1.28 thorpej 104: pool_init(&nfs_vattr_pool, sizeof(struct vattr), 0, 0, 0, "nfsvapl",
1.52 thorpej 105: &pool_allocator_nointr);
1.31 jdolecek 106: }
107:
108: /*
1.45 chs 109: * Reinitialize inode hash table.
110: */
111:
112: void
113: nfs_nhreinit()
114: {
115: struct nfsnode *np;
116: struct nfsnodehashhead *oldhash, *hash;
117: u_long oldmask, mask, val;
118: int i;
119:
120: hash = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE, M_WAITOK,
121: &mask);
122:
123: lockmgr(&nfs_hashlock, LK_EXCLUSIVE, NULL);
124: oldhash = nfsnodehashtbl;
125: oldmask = nfsnodehash;
126: nfsnodehashtbl = hash;
127: nfsnodehash = mask;
128: for (i = 0; i <= oldmask; i++) {
129: while ((np = LIST_FIRST(&oldhash[i])) != NULL) {
130: LIST_REMOVE(np, n_hash);
131: val = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
132: LIST_INSERT_HEAD(&hash[val], np, n_hash);
133: }
134: }
135: lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
136: hashdone(oldhash, M_NFSNODE);
137: }
138:
139: /*
1.31 jdolecek 140: * Free resources previoslu allocated in nfs_nhinit().
141: */
142: void
143: nfs_nhdone()
144: {
145: hashdone(nfsnodehashtbl, M_NFSNODE);
146: pool_destroy(&nfs_node_pool);
147: pool_destroy(&nfs_vattr_pool);
1.1 cgd 148: }
149:
150: /*
151: * Look up a vnode/nfsnode by file handle.
152: * Callers must check for mount points!!
153: * In all cases, a pointer to a
154: * nfsnode structure is returned.
155: */
1.15 christos 156: int
1.16 fvdl 157: nfs_nget(mntp, fhp, fhsize, npp)
1.1 cgd 158: struct mount *mntp;
1.33 augustss 159: nfsfh_t *fhp;
1.16 fvdl 160: int fhsize;
1.1 cgd 161: struct nfsnode **npp;
162: {
1.33 augustss 163: struct nfsnode *np;
1.13 mycroft 164: struct nfsnodehashhead *nhpp;
1.33 augustss 165: struct vnode *vp;
1.1 cgd 166: struct vnode *nvp;
167: int error;
168:
1.45 chs 169: nhpp = &nfsnodehashtbl[NFSNOHASH(nfs_hash(fhp, fhsize))];
1.1 cgd 170: loop:
1.45 chs 171: LIST_FOREACH(np, nhpp, n_hash) {
1.16 fvdl 172: if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
1.38 chs 173: memcmp(fhp, np->n_fhp, fhsize))
1.1 cgd 174: continue;
175: vp = NFSTOV(np);
1.26 fvdl 176: if (vget(vp, LK_EXCLUSIVE))
1.1 cgd 177: goto loop;
178: *npp = np;
179: return(0);
180: }
1.26 fvdl 181: if (lockmgr(&nfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0))
1.22 fvdl 182: goto loop;
1.15 christos 183: error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
184: if (error) {
1.1 cgd 185: *npp = 0;
1.26 fvdl 186: lockmgr(&nfs_hashlock, LK_RELEASE, 0);
1.1 cgd 187: return (error);
188: }
189: vp = nvp;
1.28 thorpej 190: np = pool_get(&nfs_node_pool, PR_WAITOK);
1.38 chs 191: memset(np, 0, sizeof *np);
1.36 fvdl 192: lockinit(&np->n_commitlock, PINOD, "nfsclock", 0, 0);
1.9 mycroft 193: vp->v_data = np;
1.1 cgd 194: np->n_vnode = vp;
1.46 chs 195: genfs_node_init(vp, &nfs_genfsops);
1.38 chs 196:
1.1 cgd 197: /*
198: * Insert the nfsnode in the hash queue for its new file handle
199: */
1.46 chs 200:
1.13 mycroft 201: LIST_INSERT_HEAD(nhpp, np, n_hash);
1.16 fvdl 202: if (fhsize > NFS_SMALLFH) {
1.34 thorpej 203: np->n_fhp = malloc(fhsize, M_NFSBIGFH, M_WAITOK);
1.16 fvdl 204: } else
205: np->n_fhp = &np->n_fh;
1.38 chs 206: memcpy(np->n_fhp, fhp, fhsize);
1.16 fvdl 207: np->n_fhsize = fhsize;
1.30 fvdl 208: np->n_accstamp = -1;
1.28 thorpej 209: np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK);
1.45 chs 210: lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
1.46 chs 211: lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
1.38 chs 212: error = VOP_GETATTR(vp, np->n_vattr, curproc->p_ucred, curproc);
213: if (error) {
1.50 fvdl 214: vput(vp);
1.38 chs 215: return error;
216: }
217: uvm_vnp_setsize(vp, np->n_vattr->va_size);
1.1 cgd 218: *npp = np;
219: return (0);
220: }
221:
1.15 christos 222: int
223: nfs_inactive(v)
224: void *v;
225: {
1.9 mycroft 226: struct vop_inactive_args /* {
227: struct vnode *a_vp;
1.16 fvdl 228: struct proc *a_p;
1.15 christos 229: } */ *ap = v;
1.33 augustss 230: struct nfsnode *np;
231: struct sillyrename *sp;
1.26 fvdl 232: struct proc *p = ap->a_p;
1.40 fvdl 233: struct vnode *vp = ap->a_vp;
1.1 cgd 234:
1.40 fvdl 235: np = VTONFS(vp);
236: if (prtactive && vp->v_usecount != 0)
237: vprint("nfs_inactive: pushing active", vp);
238: if (vp->v_type != VDIR) {
1.16 fvdl 239: sp = np->n_sillyrename;
1.18 fvdl 240: np->n_sillyrename = (struct sillyrename *)0;
241: } else
1.44 fvdl 242: sp = NULL;
243: if (sp != NULL)
1.40 fvdl 244: nfs_vinvalbuf(vp, 0, sp->s_cred, p, 1);
1.44 fvdl 245: np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
246: NQNFSNONCACHE | NQNFSWRITE);
247: VOP_UNLOCK(vp, 0);
248: if (sp != NULL) {
1.19 fvdl 249:
250: /*
1.1 cgd 251: * Remove the silly file that was rename'd earlier
252: */
1.40 fvdl 253:
1.39 fvdl 254: vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_RETRY);
1.9 mycroft 255: nfs_removeit(sp);
1.1 cgd 256: crfree(sp->s_cred);
1.39 fvdl 257: vput(sp->s_dvp);
1.38 chs 258: FREE(sp, M_NFSREQ);
1.1 cgd 259: }
260: return (0);
261: }
262:
263: /*
264: * Reclaim an nfsnode so that it can be used for other purposes.
265: */
1.15 christos 266: int
267: nfs_reclaim(v)
268: void *v;
269: {
1.9 mycroft 270: struct vop_reclaim_args /* {
271: struct vnode *a_vp;
1.15 christos 272: } */ *ap = v;
1.33 augustss 273: struct vnode *vp = ap->a_vp;
274: struct nfsnode *np = VTONFS(vp);
275: struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1.1 cgd 276:
277: if (prtactive && vp->v_usecount != 0)
278: vprint("nfs_reclaim: pushing active", vp);
1.16 fvdl 279:
1.13 mycroft 280: LIST_REMOVE(np, n_hash);
1.9 mycroft 281:
1.55 christos 282: if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
1.13 mycroft 283: CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
1.9 mycroft 284: }
1.16 fvdl 285:
286: /*
287: * Free up any directory cookie structures and
288: * large file handle structures that might be associated with
289: * this nfs node.
290: */
1.23 fvdl 291: if (vp->v_type == VDIR && np->n_dircache) {
1.24 fvdl 292: nfs_invaldircache(vp, 1);
1.23 fvdl 293: FREE(np->n_dircache, M_NFSDIROFF);
1.16 fvdl 294: }
295: if (np->n_fhsize > NFS_SMALLFH) {
1.38 chs 296: free(np->n_fhp, M_NFSBIGFH);
1.16 fvdl 297: }
298:
1.28 thorpej 299: pool_put(&nfs_vattr_pool, np->n_vattr);
1.38 chs 300: if (np->n_rcred) {
301: crfree(np->n_rcred);
302: }
303: if (np->n_wcred) {
304: crfree(np->n_wcred);
305: }
1.1 cgd 306: cache_purge(vp);
1.28 thorpej 307: pool_put(&nfs_node_pool, vp->v_data);
1.38 chs 308: vp->v_data = NULL;
1.1 cgd 309: return (0);
1.46 chs 310: }
311:
312: void
313: nfs_gop_size(struct vnode *vp, off_t size, off_t *eobp)
314: {
315: *eobp = MAX(size, vp->v_size);
316: }
317:
318: int
319: nfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
320: struct ucred *cred)
321: {
322: return 0;
1.53 chs 323: }
324:
325: int
326: nfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
327: {
328: int i;
329:
330: for (i = 0; i < npages; i++) {
331: pmap_page_protect(pgs[i], VM_PROT_READ);
332: }
333: return genfs_gop_write(vp, pgs, npages, flags);
1.1 cgd 334: }
CVSweb <webmaster@jp.NetBSD.org>