Annotation of src/sys/nfs/nfs_node.c, Revision 1.63
1.63 ! yamt 1: /* $NetBSD: nfs_node.c,v 1.62 2003/04/02 15:14:19 yamt 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.63 ! yamt 42: __KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.62 2003/04/02 15:14:19 yamt 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 */
1.57 thorpej 72:
73: MALLOC_DEFINE(M_NFSBIGFH, "NFS bigfh", "NFS big filehandle");
74: MALLOC_DEFINE(M_NFSNODE, "NFS node", "NFS vnode private part");
1.28 thorpej 75:
1.41 tsutsui 76: extern int prtactive;
77:
1.1 cgd 78: #define TRUE 1
79: #define FALSE 0
80:
1.48 lukem 81: #define nfs_hash(x,y) hash32_buf((x), (y), HASH32_BUF_INIT)
82:
1.61 perseant 83: void nfs_gop_size(struct vnode *, off_t, off_t *, int);
1.46 chs 84: int nfs_gop_alloc(struct vnode *, off_t, off_t, int, struct ucred *);
1.53 chs 85: int nfs_gop_write(struct vnode *, struct vm_page **, int, int);
1.46 chs 86:
87: struct genfs_ops nfs_genfsops = {
88: nfs_gop_size,
89: nfs_gop_alloc,
1.53 chs 90: nfs_gop_write,
1.46 chs 91: };
92:
1.1 cgd 93: /*
94: * Initialize hash links for nfsnodes
95: * and build nfsnode free list.
96: */
1.15 christos 97: void
1.1 cgd 98: nfs_nhinit()
99: {
100:
1.37 ad 101: nfsnodehashtbl = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE,
102: M_WAITOK, &nfsnodehash);
1.22 fvdl 103: lockinit(&nfs_hashlock, PINOD, "nfs_hashlock", 0, 0);
1.28 thorpej 104:
105: pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl",
1.52 thorpej 106: &pool_allocator_nointr);
1.28 thorpej 107: pool_init(&nfs_vattr_pool, sizeof(struct vattr), 0, 0, 0, "nfsvapl",
1.52 thorpej 108: &pool_allocator_nointr);
1.31 jdolecek 109: }
110:
111: /*
1.45 chs 112: * Reinitialize inode hash table.
113: */
114:
115: void
116: nfs_nhreinit()
117: {
118: struct nfsnode *np;
119: struct nfsnodehashhead *oldhash, *hash;
120: u_long oldmask, mask, val;
121: int i;
122:
123: hash = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE, M_WAITOK,
124: &mask);
125:
126: lockmgr(&nfs_hashlock, LK_EXCLUSIVE, NULL);
127: oldhash = nfsnodehashtbl;
128: oldmask = nfsnodehash;
129: nfsnodehashtbl = hash;
130: nfsnodehash = mask;
131: for (i = 0; i <= oldmask; i++) {
132: while ((np = LIST_FIRST(&oldhash[i])) != NULL) {
133: LIST_REMOVE(np, n_hash);
134: val = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
135: LIST_INSERT_HEAD(&hash[val], np, n_hash);
136: }
137: }
138: lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
139: hashdone(oldhash, M_NFSNODE);
140: }
141:
142: /*
1.31 jdolecek 143: * Free resources previoslu allocated in nfs_nhinit().
144: */
145: void
146: nfs_nhdone()
147: {
148: hashdone(nfsnodehashtbl, M_NFSNODE);
149: pool_destroy(&nfs_node_pool);
150: pool_destroy(&nfs_vattr_pool);
1.1 cgd 151: }
152:
153: /*
154: * Look up a vnode/nfsnode by file handle.
155: * Callers must check for mount points!!
156: * In all cases, a pointer to a
157: * nfsnode structure is returned.
158: */
1.15 christos 159: int
1.16 fvdl 160: nfs_nget(mntp, fhp, fhsize, npp)
1.1 cgd 161: struct mount *mntp;
1.33 augustss 162: nfsfh_t *fhp;
1.16 fvdl 163: int fhsize;
1.1 cgd 164: struct nfsnode **npp;
165: {
1.33 augustss 166: struct nfsnode *np;
1.13 mycroft 167: struct nfsnodehashhead *nhpp;
1.33 augustss 168: struct vnode *vp;
1.1 cgd 169: struct vnode *nvp;
170: int error;
171:
1.45 chs 172: nhpp = &nfsnodehashtbl[NFSNOHASH(nfs_hash(fhp, fhsize))];
1.1 cgd 173: loop:
1.45 chs 174: LIST_FOREACH(np, nhpp, n_hash) {
1.16 fvdl 175: if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
1.38 chs 176: memcmp(fhp, np->n_fhp, fhsize))
1.1 cgd 177: continue;
178: vp = NFSTOV(np);
1.26 fvdl 179: if (vget(vp, LK_EXCLUSIVE))
1.1 cgd 180: goto loop;
181: *npp = np;
182: return(0);
183: }
1.26 fvdl 184: if (lockmgr(&nfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0))
1.22 fvdl 185: goto loop;
1.15 christos 186: error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
187: if (error) {
1.1 cgd 188: *npp = 0;
1.26 fvdl 189: lockmgr(&nfs_hashlock, LK_RELEASE, 0);
1.1 cgd 190: return (error);
191: }
192: vp = nvp;
1.28 thorpej 193: np = pool_get(&nfs_node_pool, PR_WAITOK);
1.38 chs 194: memset(np, 0, sizeof *np);
1.36 fvdl 195: lockinit(&np->n_commitlock, PINOD, "nfsclock", 0, 0);
1.9 mycroft 196: vp->v_data = np;
1.1 cgd 197: np->n_vnode = vp;
1.46 chs 198: genfs_node_init(vp, &nfs_genfsops);
1.38 chs 199:
1.1 cgd 200: /*
201: * Insert the nfsnode in the hash queue for its new file handle
202: */
1.46 chs 203:
1.13 mycroft 204: LIST_INSERT_HEAD(nhpp, np, n_hash);
1.16 fvdl 205: if (fhsize > NFS_SMALLFH) {
1.34 thorpej 206: np->n_fhp = malloc(fhsize, M_NFSBIGFH, M_WAITOK);
1.16 fvdl 207: } else
208: np->n_fhp = &np->n_fh;
1.38 chs 209: memcpy(np->n_fhp, fhp, fhsize);
1.16 fvdl 210: np->n_fhsize = fhsize;
1.30 fvdl 211: np->n_accstamp = -1;
1.28 thorpej 212: np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK);
1.45 chs 213: lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
1.46 chs 214: lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
1.38 chs 215: error = VOP_GETATTR(vp, np->n_vattr, curproc->p_ucred, curproc);
216: if (error) {
1.50 fvdl 217: vput(vp);
1.38 chs 218: return error;
219: }
220: uvm_vnp_setsize(vp, np->n_vattr->va_size);
1.1 cgd 221: *npp = np;
222: return (0);
223: }
224:
1.15 christos 225: int
226: nfs_inactive(v)
227: void *v;
228: {
1.9 mycroft 229: struct vop_inactive_args /* {
230: struct vnode *a_vp;
1.16 fvdl 231: struct proc *a_p;
1.15 christos 232: } */ *ap = v;
1.33 augustss 233: struct nfsnode *np;
234: struct sillyrename *sp;
1.26 fvdl 235: struct proc *p = ap->a_p;
1.40 fvdl 236: struct vnode *vp = ap->a_vp;
1.59 fvdl 237: struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1.1 cgd 238:
1.40 fvdl 239: np = VTONFS(vp);
240: if (prtactive && vp->v_usecount != 0)
241: vprint("nfs_inactive: pushing active", vp);
242: if (vp->v_type != VDIR) {
1.16 fvdl 243: sp = np->n_sillyrename;
1.18 fvdl 244: np->n_sillyrename = (struct sillyrename *)0;
245: } else
1.44 fvdl 246: sp = NULL;
247: if (sp != NULL)
1.40 fvdl 248: nfs_vinvalbuf(vp, 0, sp->s_cred, p, 1);
1.44 fvdl 249: np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
250: NQNFSNONCACHE | NQNFSWRITE);
251: VOP_UNLOCK(vp, 0);
252: if (sp != NULL) {
1.19 fvdl 253:
254: /*
1.1 cgd 255: * Remove the silly file that was rename'd earlier
256: */
1.40 fvdl 257:
1.39 fvdl 258: vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_RETRY);
1.9 mycroft 259: nfs_removeit(sp);
1.1 cgd 260: crfree(sp->s_cred);
1.39 fvdl 261: vput(sp->s_dvp);
1.38 chs 262: FREE(sp, M_NFSREQ);
1.1 cgd 263: }
1.59 fvdl 264:
1.62 yamt 265: if ((nmp->nm_flag & NFSMNT_NQNFS) && CIRCLEQ_NEXT(np, n_timer) != 0) {
1.59 fvdl 266: CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
267: }
268:
269: if (vp->v_type == VDIR && np->n_dircache)
270: nfs_invaldircache(vp, 1);
271:
1.1 cgd 272: return (0);
273: }
274:
275: /*
276: * Reclaim an nfsnode so that it can be used for other purposes.
277: */
1.15 christos 278: int
279: nfs_reclaim(v)
280: void *v;
281: {
1.9 mycroft 282: struct vop_reclaim_args /* {
283: struct vnode *a_vp;
1.15 christos 284: } */ *ap = v;
1.33 augustss 285: struct vnode *vp = ap->a_vp;
286: struct nfsnode *np = VTONFS(vp);
1.1 cgd 287:
288: if (prtactive && vp->v_usecount != 0)
289: vprint("nfs_reclaim: pushing active", vp);
1.60 drochner 290:
291: LIST_REMOVE(np, n_hash);
1.16 fvdl 292:
293: /*
294: * Free up any directory cookie structures and
295: * large file handle structures that might be associated with
296: * this nfs node.
297: */
1.59 fvdl 298: if (vp->v_type == VDIR && np->n_dircache)
1.63 ! yamt 299: hashdone(np->n_dircache, M_NFSDIROFF);
1.59 fvdl 300:
301: if (np->n_fhsize > NFS_SMALLFH)
1.38 chs 302: free(np->n_fhp, M_NFSBIGFH);
1.16 fvdl 303:
1.28 thorpej 304: pool_put(&nfs_vattr_pool, np->n_vattr);
1.59 fvdl 305: if (np->n_rcred)
1.38 chs 306: crfree(np->n_rcred);
1.59 fvdl 307:
308: if (np->n_wcred)
1.38 chs 309: crfree(np->n_wcred);
1.59 fvdl 310:
1.1 cgd 311: cache_purge(vp);
1.28 thorpej 312: pool_put(&nfs_node_pool, vp->v_data);
1.38 chs 313: vp->v_data = NULL;
1.1 cgd 314: return (0);
1.46 chs 315: }
316:
317: void
1.61 perseant 318: nfs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
1.46 chs 319: {
1.61 perseant 320: KASSERT(flags & (GOP_SIZE_READ | GOP_SIZE_WRITE));
321: KASSERT((flags & (GOP_SIZE_READ | GOP_SIZE_WRITE))
322: != (GOP_SIZE_READ | GOP_SIZE_WRITE));
1.46 chs 323: *eobp = MAX(size, vp->v_size);
324: }
325:
326: int
327: nfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
328: struct ucred *cred)
329: {
330: return 0;
1.53 chs 331: }
332:
333: int
334: nfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
335: {
336: int i;
337:
338: for (i = 0; i < npages; i++) {
339: pmap_page_protect(pgs[i], VM_PROT_READ);
340: }
341: return genfs_gop_write(vp, pgs, npages, flags);
1.1 cgd 342: }
CVSweb <webmaster@jp.NetBSD.org>