nfs_node.c (83366) | nfs_node.c (83651) |
---|---|
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 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95 | 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 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95 |
37 * $FreeBSD: head/sys/nfsclient/nfs_node.c 83366 2001-09-12 08:38:13Z julian $ | |
38 */ 39 | 37 */ 38 |
39#include <sys/cdefs.h> 40__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_node.c 83651 2001-09-18 23:32:09Z peter $"); |
|
40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/fnv_hash.h> 44#include <sys/lock.h> 45#include <sys/malloc.h> 46#include <sys/mount.h> 47#include <sys/namei.h> 48#include <sys/proc.h> 49#include <sys/socket.h> 50#include <sys/sysctl.h> 51#include <sys/vnode.h> 52 53#include <vm/vm_zone.h> 54 55#include <nfs/rpcv2.h> 56#include <nfs/nfsproto.h> | 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/fnv_hash.h> 45#include <sys/lock.h> 46#include <sys/malloc.h> 47#include <sys/mount.h> 48#include <sys/namei.h> 49#include <sys/proc.h> 50#include <sys/socket.h> 51#include <sys/sysctl.h> 52#include <sys/vnode.h> 53 54#include <vm/vm_zone.h> 55 56#include <nfs/rpcv2.h> 57#include <nfs/nfsproto.h> |
57#include 58#include 59#include | 58#include <nfsclient/nfs.h> 59#include <nfsclient/nfsnode.h> 60#include <nfsclient/nfsmount.h> |
60 61static vm_zone_t nfsnode_zone; 62static LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl; 63static u_long nfsnodehash; | 61 62static vm_zone_t nfsnode_zone; 63static LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl; 64static u_long nfsnodehash; |
65static int nfs_node_hash_lock; |
|
64 65#define TRUE 1 66#define FALSE 0 67 | 66 67#define TRUE 1 68#define FALSE 0 69 |
70SYSCTL_DECL(_debug_hashstat); 71 |
|
68/* 69 * Grab an atomic snapshot of the nfsnode hash chain lengths 70 */ | 72/* 73 * Grab an atomic snapshot of the nfsnode hash chain lengths 74 */ |
71SYSCTL_DECL(_debug_hashstat); | |
72static int 73sysctl_debug_hashstat_rawnfsnode(SYSCTL_HANDLER_ARGS) 74{ 75 int error; 76 struct nfsnodehashhead *nnpp; 77 struct nfsnode *nnp; 78 int n_nfsnode; 79 int count; --- 9 unchanged lines hidden (view full) --- 89 count++; 90 } 91 error = SYSCTL_OUT(req, (caddr_t)&count, sizeof(count)); 92 if (error) 93 return (error); 94 } 95 return (0); 96} | 75static int 76sysctl_debug_hashstat_rawnfsnode(SYSCTL_HANDLER_ARGS) 77{ 78 int error; 79 struct nfsnodehashhead *nnpp; 80 struct nfsnode *nnp; 81 int n_nfsnode; 82 int count; --- 9 unchanged lines hidden (view full) --- 92 count++; 93 } 94 error = SYSCTL_OUT(req, (caddr_t)&count, sizeof(count)); 95 if (error) 96 return (error); 97 } 98 return (0); 99} |
97SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnfsnode, CTLTYPE_INT|CTLFLAG_RD, 98 0, 0, sysctl_debug_hashstat_rawnfsnode, "S,int", "nfsnode chain lengths"); | 100SYSCTL_PROC(_debug_hashstat, OID_AUTO, rawnfsnode, CTLTYPE_INT|CTLFLAG_RD, 0, 0, 101 sysctl_debug_hashstat_rawnfsnode, "S,int", "nfsnode chain lengths"); |
99 100static int 101sysctl_debug_hashstat_nfsnode(SYSCTL_HANDLER_ARGS) 102{ 103 int error; 104 struct nfsnodehashhead *nnpp; 105 struct nfsnode *nnp; 106 int n_nfsnode; --- 36 unchanged lines hidden (view full) --- 143SYSCTL_PROC(_debug_hashstat, OID_AUTO, nfsnode, CTLTYPE_INT|CTLFLAG_RD, 144 0, 0, sysctl_debug_hashstat_nfsnode, "I", "nfsnode chain lengths"); 145 146/* 147 * Initialize hash links for nfsnodes 148 * and build nfsnode free list. 149 */ 150void | 102 103static int 104sysctl_debug_hashstat_nfsnode(SYSCTL_HANDLER_ARGS) 105{ 106 int error; 107 struct nfsnodehashhead *nnpp; 108 struct nfsnode *nnp; 109 int n_nfsnode; --- 36 unchanged lines hidden (view full) --- 146SYSCTL_PROC(_debug_hashstat, OID_AUTO, nfsnode, CTLTYPE_INT|CTLFLAG_RD, 147 0, 0, sysctl_debug_hashstat_nfsnode, "I", "nfsnode chain lengths"); 148 149/* 150 * Initialize hash links for nfsnodes 151 * and build nfsnode free list. 152 */ 153void |
151nfs_nhinit() | 154nfs_nhinit(void) |
152{ | 155{ |
156 |
|
153 nfsnode_zone = zinit("NFSNODE", sizeof(struct nfsnode), 0, 0, 1); 154 nfsnodehashtbl = hashinit(desiredvnodes, M_NFSHASH, &nfsnodehash); 155} 156 157/* 158 * Look up a vnode/nfsnode by file handle. 159 * Callers must check for mount points!! 160 * In all cases, a pointer to a 161 * nfsnode structure is returned. 162 */ | 157 nfsnode_zone = zinit("NFSNODE", sizeof(struct nfsnode), 0, 0, 1); 158 nfsnodehashtbl = hashinit(desiredvnodes, M_NFSHASH, &nfsnodehash); 159} 160 161/* 162 * Look up a vnode/nfsnode by file handle. 163 * Callers must check for mount points!! 164 * In all cases, a pointer to a 165 * nfsnode structure is returned. 166 */ |
163static int nfs_node_hash_lock; 164 | |
165int | 167int |
166nfs_nget(mntp, fhp, fhsize, npp) 167 struct mount *mntp; 168 register nfsfh_t *fhp; 169 int fhsize; 170 struct nfsnode **npp; | 168nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp) |
171{ 172 struct thread *td = curthread; /* XXX */ 173 struct nfsnode *np, *np2; 174 struct nfsnodehashhead *nhpp; | 169{ 170 struct thread *td = curthread; /* XXX */ 171 struct nfsnode *np, *np2; 172 struct nfsnodehashhead *nhpp; |
175 register struct vnode *vp; | 173 struct vnode *vp; |
176 struct vnode *nvp; 177 int error; 178 int rsflags; 179 struct nfsmount *nmp; 180 181 /* 182 * Calculate nfs mount point and figure out whether the rslock should 183 * be interruptable or not. 184 */ 185 nmp = VFSTONFS(mntp); 186 if (nmp->nm_flag & NFSMNT_INT) 187 rsflags = PCATCH; 188 else 189 rsflags = 0; 190 191retry: 192 nhpp = NFSNOHASH(fnv_32_buf(fhp->fh_bytes, fhsize, FNV1_32_INIT)); 193loop: | 174 struct vnode *nvp; 175 int error; 176 int rsflags; 177 struct nfsmount *nmp; 178 179 /* 180 * Calculate nfs mount point and figure out whether the rslock should 181 * be interruptable or not. 182 */ 183 nmp = VFSTONFS(mntp); 184 if (nmp->nm_flag & NFSMNT_INT) 185 rsflags = PCATCH; 186 else 187 rsflags = 0; 188 189retry: 190 nhpp = NFSNOHASH(fnv_32_buf(fhp->fh_bytes, fhsize, FNV1_32_INIT)); 191loop: |
194 for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { | 192 LIST_FOREACH(np, nhpp, n_hash) { |
195 if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 196 bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 197 continue; 198 vp = NFSTOV(np); 199 if (vget(vp, LK_EXCLUSIVE, td)) 200 goto loop; 201 *npp = np; 202 return(0); --- 12 unchanged lines hidden (view full) --- 215 nfs_node_hash_lock = 1; 216 217 /* 218 * Allocate before getnewvnode since doing so afterward 219 * might cause a bogus v_data pointer to get dereferenced 220 * elsewhere if zalloc should block. 221 */ 222 np = zalloc(nfsnode_zone); | 193 if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 194 bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 195 continue; 196 vp = NFSTOV(np); 197 if (vget(vp, LK_EXCLUSIVE, td)) 198 goto loop; 199 *npp = np; 200 return(0); --- 12 unchanged lines hidden (view full) --- 213 nfs_node_hash_lock = 1; 214 215 /* 216 * Allocate before getnewvnode since doing so afterward 217 * might cause a bogus v_data pointer to get dereferenced 218 * elsewhere if zalloc should block. 219 */ 220 np = zalloc(nfsnode_zone); |
223 | 221 |
224 error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 225 if (error) { 226 if (nfs_node_hash_lock < 0) 227 wakeup(&nfs_node_hash_lock); 228 nfs_node_hash_lock = 0; 229 *npp = 0; 230 zfree(nfsnode_zone, np); 231 return (error); 232 } 233 vp = nvp; 234 bzero((caddr_t)np, sizeof *np); 235 vp->v_data = np; 236 np->n_vnode = vp; 237 /* 238 * Insert the nfsnode in the hash queue for its new file handle 239 */ | 222 error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 223 if (error) { 224 if (nfs_node_hash_lock < 0) 225 wakeup(&nfs_node_hash_lock); 226 nfs_node_hash_lock = 0; 227 *npp = 0; 228 zfree(nfsnode_zone, np); 229 return (error); 230 } 231 vp = nvp; 232 bzero((caddr_t)np, sizeof *np); 233 vp->v_data = np; 234 np->n_vnode = vp; 235 /* 236 * Insert the nfsnode in the hash queue for its new file handle 237 */ |
240 for (np2 = nhpp->lh_first; np2 != 0; np2 = np2->n_hash.le_next) { | 238 LIST_FOREACH(np2, nhpp, n_hash) { |
241 if (mntp != NFSTOV(np2)->v_mount || np2->n_fhsize != fhsize || 242 bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize)) 243 continue; 244 vrele(vp); 245 if (nfs_node_hash_lock < 0) 246 wakeup(&nfs_node_hash_lock); 247 nfs_node_hash_lock = 0; 248 zfree(nfsnode_zone, np); --- 18 unchanged lines hidden (view full) --- 267 * Lock the new nfsnode. 268 */ 269 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 270 271 return (0); 272} 273 274int | 239 if (mntp != NFSTOV(np2)->v_mount || np2->n_fhsize != fhsize || 240 bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize)) 241 continue; 242 vrele(vp); 243 if (nfs_node_hash_lock < 0) 244 wakeup(&nfs_node_hash_lock); 245 nfs_node_hash_lock = 0; 246 zfree(nfsnode_zone, np); --- 18 unchanged lines hidden (view full) --- 265 * Lock the new nfsnode. 266 */ 267 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 268 269 return (0); 270} 271 272int |
275nfs_inactive(ap) 276 struct vop_inactive_args /* { 277 struct vnode *a_vp; 278 struct thread *a_td; 279 } */ *ap; | 273nfs_inactive(struct vop_inactive_args *ap) |
280{ | 274{ |
281 register struct nfsnode *np; 282 register struct sillyrename *sp; | 275 struct nfsnode *np; 276 struct sillyrename *sp; |
283 struct thread *td = curthread; /* XXX */ 284 285 np = VTONFS(ap->a_vp); 286 if (prtactive && ap->a_vp->v_usecount != 0) 287 vprint("nfs_inactive: pushing active", ap->a_vp); 288 if (ap->a_vp->v_type != VDIR) { 289 sp = np->n_sillyrename; 290 np->n_sillyrename = (struct sillyrename *)0; --- 18 unchanged lines hidden (view full) --- 309 /* 310 * Remove the silly file that was rename'd earlier 311 */ 312 nfs_removeit(sp); 313 crfree(sp->s_cred); 314 vrele(sp->s_dvp); 315 FREE((caddr_t)sp, M_NFSREQ); 316 } | 277 struct thread *td = curthread; /* XXX */ 278 279 np = VTONFS(ap->a_vp); 280 if (prtactive && ap->a_vp->v_usecount != 0) 281 vprint("nfs_inactive: pushing active", ap->a_vp); 282 if (ap->a_vp->v_type != VDIR) { 283 sp = np->n_sillyrename; 284 np->n_sillyrename = (struct sillyrename *)0; --- 18 unchanged lines hidden (view full) --- 303 /* 304 * Remove the silly file that was rename'd earlier 305 */ 306 nfs_removeit(sp); 307 crfree(sp->s_cred); 308 vrele(sp->s_dvp); 309 FREE((caddr_t)sp, M_NFSREQ); 310 } |
317 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 318 NQNFSNONCACHE | NQNFSWRITE); | 311 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT); |
319 VOP_UNLOCK(ap->a_vp, 0, ap->a_td); 320 return (0); 321} 322 323/* 324 * Reclaim an nfsnode so that it can be used for other purposes. 325 */ 326int | 312 VOP_UNLOCK(ap->a_vp, 0, ap->a_td); 313 return (0); 314} 315 316/* 317 * Reclaim an nfsnode so that it can be used for other purposes. 318 */ 319int |
327nfs_reclaim(ap) 328 struct vop_reclaim_args /* { 329 struct vnode *a_vp; 330 } */ *ap; | 320nfs_reclaim(struct vop_reclaim_args *ap) |
331{ | 321{ |
332 register struct vnode *vp = ap->a_vp; 333 register struct nfsnode *np = VTONFS(vp); 334 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 335 register struct nfsdmap *dp, *dp2; | 322 struct vnode *vp = ap->a_vp; 323 struct nfsnode *np = VTONFS(vp); 324 struct nfsdmap *dp, *dp2; |
336 337 if (prtactive && vp->v_usecount != 0) 338 vprint("nfs_reclaim: pushing active", vp); 339 | 325 326 if (prtactive && vp->v_usecount != 0) 327 vprint("nfs_reclaim: pushing active", vp); 328 |
340 if (np->n_hash.le_prev != NULL) | 329 if (np->n_hash.le_prev != NULL) /* XXX beware */ |
341 LIST_REMOVE(np, n_hash); 342 343 /* | 330 LIST_REMOVE(np, n_hash); 331 332 /* |
344 * For nqnfs, take it off the timer queue as required. 345 */ 346 if ((nmp->nm_flag & NFSMNT_NQNFS) && TAILQ_NEXT(np, n_timer) != 0) { 347 TAILQ_REMOVE(&nmp->nm_timerhead, np, n_timer); 348 } 349 350 /* | |
351 * Free up any directory cookie structures and 352 * large file handle structures that might be associated with 353 * this nfs node. 354 */ 355 if (vp->v_type == VDIR) { | 333 * Free up any directory cookie structures and 334 * large file handle structures that might be associated with 335 * this nfs node. 336 */ 337 if (vp->v_type == VDIR) { |
356 dp = np->n_cookies.lh_first; | 338 dp = LIST_FIRST(&np->n_cookies); |
357 while (dp) { 358 dp2 = dp; | 339 while (dp) { 340 dp2 = dp; |
359 dp = dp->ndm_list.le_next; | 341 dp = LIST_NEXT(dp, ndm_list); |
360 FREE((caddr_t)dp2, M_NFSDIROFF); 361 } 362 } 363 if (np->n_fhsize > NFS_SMALLFH) { 364 FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 365 } 366 367 lockdestroy(&np->n_rslock); --- 4 unchanged lines hidden (view full) --- 372 return (0); 373} 374 375#if 0 376/* 377 * Lock an nfsnode 378 */ 379int | 342 FREE((caddr_t)dp2, M_NFSDIROFF); 343 } 344 } 345 if (np->n_fhsize > NFS_SMALLFH) { 346 FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 347 } 348 349 lockdestroy(&np->n_rslock); --- 4 unchanged lines hidden (view full) --- 354 return (0); 355} 356 357#if 0 358/* 359 * Lock an nfsnode 360 */ 361int |
380nfs_lock(ap) 381 struct vop_lock_args /* { 382 struct vnode *a_vp; 383 } */ *ap; | 362nfs_lock(struct vop_lock_args *ap) |
384{ | 363{ |
385 register struct vnode *vp = ap->a_vp; | 364 struct vnode *vp = ap->a_vp; |
386 387 /* 388 * Ugh, another place where interruptible mounts will get hung. 389 * If you make this sleep interruptible, then you have to fix all 390 * the VOP_LOCK() calls to expect interruptibility. 391 */ 392 while (vp->v_flag & VXLOCK) { 393 vp->v_flag |= VXWANT; --- 30 unchanged lines hidden (view full) --- 424 425 return (0); 426} 427 428/* 429 * Unlock an nfsnode 430 */ 431int | 365 366 /* 367 * Ugh, another place where interruptible mounts will get hung. 368 * If you make this sleep interruptible, then you have to fix all 369 * the VOP_LOCK() calls to expect interruptibility. 370 */ 371 while (vp->v_flag & VXLOCK) { 372 vp->v_flag |= VXWANT; --- 30 unchanged lines hidden (view full) --- 403 404 return (0); 405} 406 407/* 408 * Unlock an nfsnode 409 */ 410int |
432nfs_unlock(ap) 433 struct vop_unlock_args /* { 434 struct vnode *a_vp; 435 } */ *ap; | 411nfs_unlock(struct vop_unlock_args *ap) |
436{ 437#if 0 438 struct vnode* vp = ap->a_vp; 439 struct nfsnode* np = VTONFS(vp); 440 441 if (vp->v_type == VREG || vp->v_type == VNON) { 442 if (!(np->n_flag & NLOCKED)) 443 panic("nfs_unlock: nfsnode not locked"); --- 7 unchanged lines hidden (view full) --- 451 452 return (0); 453} 454 455/* 456 * Check for a locked nfsnode 457 */ 458int | 412{ 413#if 0 414 struct vnode* vp = ap->a_vp; 415 struct nfsnode* np = VTONFS(vp); 416 417 if (vp->v_type == VREG || vp->v_type == VNON) { 418 if (!(np->n_flag & NLOCKED)) 419 panic("nfs_unlock: nfsnode not locked"); --- 7 unchanged lines hidden (view full) --- 427 428 return (0); 429} 430 431/* 432 * Check for a locked nfsnode 433 */ 434int |
459nfs_islocked(ap) 460 struct vop_islocked_args /* { 461 struct vnode *a_vp; 462 struct thread *a_td; 463 } */ *ap; | 435nfs_islocked(struct vop_islocked_args *ap) |
464{ | 436{ |
437 |
|
465 return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0; 466} 467#endif 468 | 438 return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0; 439} 440#endif 441 |