Annotation of src/sys/nfs/nfs_node.c, Revision 1.80
1.80 ! yamt 1: /* $NetBSD$ */
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.
1.70 agc 18: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
1.16 fvdl 34: * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
1.1 cgd 35: */
1.47 lukem 36:
37: #include <sys/cdefs.h>
1.80 ! yamt 38: __KERNEL_RCSID(0, "$NetBSD$");
1.1 cgd 39:
1.35 bjh21 40: #include "opt_nfs.h"
1.16 fvdl 41:
1.4 mycroft 42: #include <sys/param.h>
43: #include <sys/systm.h>
44: #include <sys/proc.h>
45: #include <sys/mount.h>
46: #include <sys/namei.h>
47: #include <sys/vnode.h>
48: #include <sys/kernel.h>
49: #include <sys/malloc.h>
1.28 thorpej 50: #include <sys/pool.h>
1.22 fvdl 51: #include <sys/lock.h>
1.48 lukem 52: #include <sys/hash.h>
1.1 cgd 53:
1.9 mycroft 54: #include <nfs/rpcv2.h>
1.16 fvdl 55: #include <nfs/nfsproto.h>
1.4 mycroft 56: #include <nfs/nfs.h>
57: #include <nfs/nfsnode.h>
58: #include <nfs/nfsmount.h>
1.9 mycroft 59: #include <nfs/nqnfs.h>
1.15 christos 60: #include <nfs/nfs_var.h>
1.1 cgd 61:
1.56 matt 62: struct nfsnodehashhead *nfsnodehashtbl;
1.13 mycroft 63: u_long nfsnodehash;
1.22 fvdl 64: struct lock nfs_hashlock;
1.1 cgd 65:
1.77 simonb 66: POOL_INIT(nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl",
67: &pool_allocator_nointr);
68: POOL_INIT(nfs_vattr_pool, sizeof(struct vattr), 0, 0, 0, "nfsvapl",
69: &pool_allocator_nointr);
1.57 thorpej 70:
71: MALLOC_DEFINE(M_NFSBIGFH, "NFS bigfh", "NFS big filehandle");
72: MALLOC_DEFINE(M_NFSNODE, "NFS node", "NFS vnode private part");
1.28 thorpej 73:
1.41 tsutsui 74: extern int prtactive;
1.1 cgd 75:
1.48 lukem 76: #define nfs_hash(x,y) hash32_buf((x), (y), HASH32_BUF_INIT)
77:
1.61 perseant 78: void nfs_gop_size(struct vnode *, off_t, off_t *, int);
1.46 chs 79: int nfs_gop_alloc(struct vnode *, off_t, off_t, int, struct ucred *);
1.53 chs 80: int nfs_gop_write(struct vnode *, struct vm_page **, int, int);
1.46 chs 81:
1.80 ! yamt 82: static const struct genfs_ops nfs_genfsops = {
! 83: .gop_size = nfs_gop_size,
! 84: .gop_alloc = nfs_gop_alloc,
! 85: .gop_write = nfs_gop_write,
1.46 chs 86: };
87:
1.1 cgd 88: /*
89: * Initialize hash links for nfsnodes
90: * and build nfsnode free list.
91: */
1.15 christos 92: void
1.1 cgd 93: nfs_nhinit()
94: {
95:
1.37 ad 96: nfsnodehashtbl = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE,
97: M_WAITOK, &nfsnodehash);
1.22 fvdl 98: lockinit(&nfs_hashlock, PINOD, "nfs_hashlock", 0, 0);
1.31 jdolecek 99: }
100:
101: /*
1.45 chs 102: * Reinitialize inode hash table.
103: */
104:
105: void
106: nfs_nhreinit()
107: {
108: struct nfsnode *np;
109: struct nfsnodehashhead *oldhash, *hash;
110: u_long oldmask, mask, val;
111: int i;
112:
113: hash = hashinit(desiredvnodes, HASH_LIST, M_NFSNODE, M_WAITOK,
114: &mask);
1.79 perry 115:
1.45 chs 116: lockmgr(&nfs_hashlock, LK_EXCLUSIVE, NULL);
117: oldhash = nfsnodehashtbl;
118: oldmask = nfsnodehash;
119: nfsnodehashtbl = hash;
120: nfsnodehash = mask;
121: for (i = 0; i <= oldmask; i++) {
122: while ((np = LIST_FIRST(&oldhash[i])) != NULL) {
123: LIST_REMOVE(np, n_hash);
124: val = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
125: LIST_INSERT_HEAD(&hash[val], np, n_hash);
126: }
127: }
128: lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
129: hashdone(oldhash, M_NFSNODE);
130: }
131:
132: /*
1.31 jdolecek 133: * Free resources previoslu allocated in nfs_nhinit().
134: */
135: void
136: nfs_nhdone()
137: {
138: hashdone(nfsnodehashtbl, M_NFSNODE);
139: pool_destroy(&nfs_node_pool);
140: pool_destroy(&nfs_vattr_pool);
1.1 cgd 141: }
142:
143: /*
144: * Look up a vnode/nfsnode by file handle.
145: * Callers must check for mount points!!
146: * In all cases, a pointer to a
147: * nfsnode structure is returned.
148: */
1.15 christos 149: int
1.75 yamt 150: nfs_nget1(mntp, fhp, fhsize, npp, lkflags)
1.1 cgd 151: struct mount *mntp;
1.33 augustss 152: nfsfh_t *fhp;
1.16 fvdl 153: int fhsize;
1.1 cgd 154: struct nfsnode **npp;
1.75 yamt 155: int lkflags;
1.1 cgd 156: {
1.33 augustss 157: struct nfsnode *np;
1.13 mycroft 158: struct nfsnodehashhead *nhpp;
1.33 augustss 159: struct vnode *vp;
1.1 cgd 160: int error;
161:
1.45 chs 162: nhpp = &nfsnodehashtbl[NFSNOHASH(nfs_hash(fhp, fhsize))];
1.1 cgd 163: loop:
1.45 chs 164: LIST_FOREACH(np, nhpp, n_hash) {
1.16 fvdl 165: if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
1.38 chs 166: memcmp(fhp, np->n_fhp, fhsize))
1.1 cgd 167: continue;
168: vp = NFSTOV(np);
1.75 yamt 169: error = vget(vp, LK_EXCLUSIVE | lkflags);
170: if (error == EBUSY)
171: return error;
172: if (error)
1.1 cgd 173: goto loop;
174: *npp = np;
175: return(0);
176: }
1.26 fvdl 177: if (lockmgr(&nfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0))
1.22 fvdl 178: goto loop;
1.73 yamt 179: error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &vp);
1.15 christos 180: if (error) {
1.1 cgd 181: *npp = 0;
1.26 fvdl 182: lockmgr(&nfs_hashlock, LK_RELEASE, 0);
1.1 cgd 183: return (error);
184: }
1.28 thorpej 185: np = pool_get(&nfs_node_pool, PR_WAITOK);
1.38 chs 186: memset(np, 0, sizeof *np);
1.9 mycroft 187: vp->v_data = np;
1.1 cgd 188: np->n_vnode = vp;
1.46 chs 189: genfs_node_init(vp, &nfs_genfsops);
1.38 chs 190:
1.1 cgd 191: /*
192: * Insert the nfsnode in the hash queue for its new file handle
193: */
1.46 chs 194:
1.13 mycroft 195: LIST_INSERT_HEAD(nhpp, np, n_hash);
1.16 fvdl 196: if (fhsize > NFS_SMALLFH) {
1.34 thorpej 197: np->n_fhp = malloc(fhsize, M_NFSBIGFH, M_WAITOK);
1.16 fvdl 198: } else
199: np->n_fhp = &np->n_fh;
1.38 chs 200: memcpy(np->n_fhp, fhp, fhsize);
1.16 fvdl 201: np->n_fhsize = fhsize;
1.30 fvdl 202: np->n_accstamp = -1;
1.28 thorpej 203: np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK);
1.71 fvdl 204:
205: /*
206: * Initalize read/write creds to useful values. VOP_OPEN will
207: * overwrite these.
208: */
209: np->n_rcred = curproc->p_ucred;
210: crhold(np->n_rcred);
211: np->n_wcred = curproc->p_ucred;
212: crhold(np->n_wcred);
1.45 chs 213: lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
1.46 chs 214: lockmgr(&nfs_hashlock, LK_RELEASE, NULL);
1.74 yamt 215: NFS_INVALIDATE_ATTRCACHE(np);
216: uvm_vnp_setsize(vp, 0);
1.1 cgd 217: *npp = np;
218: return (0);
219: }
220:
1.15 christos 221: int
222: nfs_inactive(v)
223: void *v;
224: {
1.9 mycroft 225: struct vop_inactive_args /* {
226: struct vnode *a_vp;
1.68 fvdl 227: struct proc *a_p;
1.15 christos 228: } */ *ap = v;
1.33 augustss 229: struct nfsnode *np;
230: struct sillyrename *sp;
1.68 fvdl 231: struct proc *p = ap->a_p;
1.40 fvdl 232: struct vnode *vp = ap->a_vp;
1.59 fvdl 233: struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1.69 yamt 234: boolean_t removed;
1.72 wrstuden 235: int err;
1.1 cgd 236:
1.40 fvdl 237: np = VTONFS(vp);
238: if (prtactive && vp->v_usecount != 0)
239: vprint("nfs_inactive: pushing active", vp);
240: if (vp->v_type != VDIR) {
1.16 fvdl 241: sp = np->n_sillyrename;
1.18 fvdl 242: np->n_sillyrename = (struct sillyrename *)0;
243: } else
1.44 fvdl 244: sp = NULL;
245: if (sp != NULL)
1.68 fvdl 246: nfs_vinvalbuf(vp, 0, sp->s_cred, p, 1);
1.69 yamt 247: removed = (np->n_flag & NREMOVED) != 0;
1.44 fvdl 248: np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
1.78 yamt 249: NQNFSNONCACHE | NQNFSWRITE | NEOFVALID);
1.76 yamt 250:
251: if ((nmp->nm_flag & NFSMNT_NQNFS) && CIRCLEQ_NEXT(np, n_timer) != 0) {
252: CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
253: }
254:
255: if (vp->v_type == VDIR && np->n_dircache)
1.78 yamt 256: nfs_invaldircache(vp,
257: NFS_INVALDIRCACHE_FORCE | NFS_INVALDIRCACHE_KEEPEOF);
1.76 yamt 258:
1.44 fvdl 259: VOP_UNLOCK(vp, 0);
1.76 yamt 260:
261: /* XXXMP only kernel_lock protects vp */
262: if (removed)
263: vrecycle(vp, NULL, p);
264:
1.44 fvdl 265: if (sp != NULL) {
1.19 fvdl 266:
267: /*
1.1 cgd 268: * Remove the silly file that was rename'd earlier
1.72 wrstuden 269: *
270: * Just in case our thread also has the parent node locked,
271: * we let vn_lock() fail.
1.1 cgd 272: */
1.40 fvdl 273:
1.72 wrstuden 274: err = vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_RETRY
275: | LK_RECURSEFAIL);
1.9 mycroft 276: nfs_removeit(sp);
1.1 cgd 277: crfree(sp->s_cred);
1.72 wrstuden 278: if (err != EDEADLK)
279: vput(sp->s_dvp);
280: else
281: vrele(sp->s_dvp);
1.38 chs 282: FREE(sp, M_NFSREQ);
1.1 cgd 283: }
1.59 fvdl 284:
1.1 cgd 285: return (0);
286: }
287:
288: /*
289: * Reclaim an nfsnode so that it can be used for other purposes.
290: */
1.15 christos 291: int
292: nfs_reclaim(v)
293: void *v;
294: {
1.9 mycroft 295: struct vop_reclaim_args /* {
296: struct vnode *a_vp;
1.15 christos 297: } */ *ap = v;
1.33 augustss 298: struct vnode *vp = ap->a_vp;
299: struct nfsnode *np = VTONFS(vp);
1.1 cgd 300:
301: if (prtactive && vp->v_usecount != 0)
302: vprint("nfs_reclaim: pushing active", vp);
1.60 drochner 303:
304: LIST_REMOVE(np, n_hash);
1.16 fvdl 305:
306: /*
307: * Free up any directory cookie structures and
308: * large file handle structures that might be associated with
309: * this nfs node.
310: */
1.59 fvdl 311: if (vp->v_type == VDIR && np->n_dircache)
1.63 yamt 312: hashdone(np->n_dircache, M_NFSDIROFF);
1.65 yamt 313: KASSERT(np->n_dirgens == NULL);
1.59 fvdl 314:
315: if (np->n_fhsize > NFS_SMALLFH)
1.38 chs 316: free(np->n_fhp, M_NFSBIGFH);
1.16 fvdl 317:
1.28 thorpej 318: pool_put(&nfs_vattr_pool, np->n_vattr);
1.59 fvdl 319: if (np->n_rcred)
1.38 chs 320: crfree(np->n_rcred);
1.59 fvdl 321:
322: if (np->n_wcred)
1.38 chs 323: crfree(np->n_wcred);
1.59 fvdl 324:
1.1 cgd 325: cache_purge(vp);
1.28 thorpej 326: pool_put(&nfs_node_pool, vp->v_data);
1.38 chs 327: vp->v_data = NULL;
1.1 cgd 328: return (0);
1.46 chs 329: }
330:
331: void
1.61 perseant 332: nfs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
1.46 chs 333: {
1.61 perseant 334: KASSERT(flags & (GOP_SIZE_READ | GOP_SIZE_WRITE));
335: KASSERT((flags & (GOP_SIZE_READ | GOP_SIZE_WRITE))
336: != (GOP_SIZE_READ | GOP_SIZE_WRITE));
1.46 chs 337: *eobp = MAX(size, vp->v_size);
338: }
339:
340: int
341: nfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags,
342: struct ucred *cred)
343: {
344: return 0;
1.53 chs 345: }
346:
347: int
348: nfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags)
349: {
350: int i;
351:
352: for (i = 0; i < npages; i++) {
353: pmap_page_protect(pgs[i], VM_PROT_READ);
354: }
355: return genfs_gop_write(vp, pgs, npages, flags);
1.1 cgd 356: }
CVSweb <webmaster@jp.NetBSD.org>