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 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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
|
38 */ 39 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/proc.h> 44#include <sys/mount.h> 45#include <sys/namei.h> 46#include <sys/vnode.h> 47#include <sys/malloc.h> 48 49#include <vm/vm_zone.h> 50 51#include <nfs/rpcv2.h> 52#include <nfs/nfsproto.h> 53#include <nfs/nfs.h> 54#include <nfs/nfsnode.h> 55#include <nfs/nfsmount.h> 56 57static vm_zone_t nfsnode_zone; 58static LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl; 59static u_long nfsnodehash; 60 61#define TRUE 1 62#define FALSE 0 63 64/* 65 * Initialize hash links for nfsnodes 66 * and build nfsnode free list. 67 */ 68void 69nfs_nhinit() 70{ 71 nfsnode_zone = zinit("NFSNODE", sizeof(struct nfsnode), 0, 0, 1); 72 nfsnodehashtbl = hashinit(desiredvnodes, M_NFSHASH, &nfsnodehash); 73} 74 75/* 76 * Compute an entry in the NFS hash table structure 77 */ 78u_long 79nfs_hash(fhp, fhsize) 80 register nfsfh_t *fhp; 81 int fhsize; 82{ 83 register u_char *fhpp; 84 register u_long fhsum; 85 register int i; 86 87 fhpp = &fhp->fh_bytes[0]; 88 fhsum = 0; 89 for (i = 0; i < fhsize; i++) 90 fhsum += *fhpp++; 91 return (fhsum); 92} 93 94/* 95 * Look up a vnode/nfsnode by file handle. 96 * Callers must check for mount points!! 97 * In all cases, a pointer to a 98 * nfsnode structure is returned. 99 */ 100static int nfs_node_hash_lock; 101 102int 103nfs_nget(mntp, fhp, fhsize, npp) 104 struct mount *mntp; 105 register nfsfh_t *fhp; 106 int fhsize; 107 struct nfsnode **npp; 108{ 109 struct proc *p = curproc; /* XXX */ 110 struct nfsnode *np, *np2; 111 struct nfsnodehashhead *nhpp; 112 register struct vnode *vp; 113 struct vnode *nvp; 114 int error; 115 int rsflags; 116 struct nfsmount *nmp; 117 118 /* 119 * Calculate nfs mount point and figure out whether the rslock should 120 * be interruptable or not. 121 */ 122 nmp = VFSTONFS(mntp); 123 if (nmp->nm_flag & NFSMNT_INT) 124 rsflags = PCATCH; 125 else 126 rsflags = 0; 127 128retry: 129 nhpp = NFSNOHASH(nfs_hash(fhp, fhsize)); 130loop: 131 for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { 132 if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 133 bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 134 continue; 135 vp = NFSTOV(np); 136 if (vget(vp, LK_EXCLUSIVE, p)) 137 goto loop; 138 *npp = np; 139 return(0); 140 } 141 /* 142 * Obtain a lock to prevent a race condition if the getnewvnode() 143 * or MALLOC() below happens to block. 144 */ 145 if (nfs_node_hash_lock) { 146 while (nfs_node_hash_lock) { 147 nfs_node_hash_lock = -1; 148 tsleep(&nfs_node_hash_lock, PVM, "nfsngt", 0); 149 } 150 goto loop; 151 } 152 nfs_node_hash_lock = 1; 153 154 /* 155 * Allocate before getnewvnode since doing so afterward 156 * might cause a bogus v_data pointer to get dereferenced 157 * elsewhere if zalloc should block. 158 */ 159 np = zalloc(nfsnode_zone); 160 161 error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 162 if (error) { 163 if (nfs_node_hash_lock < 0) 164 wakeup(&nfs_node_hash_lock); 165 nfs_node_hash_lock = 0; 166 *npp = 0; 167 zfree(nfsnode_zone, np); 168 return (error); 169 } 170 vp = nvp; 171 bzero((caddr_t)np, sizeof *np); 172 vp->v_data = np; 173 np->n_vnode = vp; 174 /* 175 * Insert the nfsnode in the hash queue for its new file handle 176 */ 177 for (np2 = nhpp->lh_first; np2 != 0; np2 = np2->n_hash.le_next) { 178 if (mntp != NFSTOV(np2)->v_mount || np2->n_fhsize != fhsize || 179 bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize)) 180 continue; 181 vrele(vp); 182 if (nfs_node_hash_lock < 0) 183 wakeup(&nfs_node_hash_lock); 184 nfs_node_hash_lock = 0; 185 zfree(nfsnode_zone, np); 186 goto retry; 187 } 188 LIST_INSERT_HEAD(nhpp, np, n_hash); 189 if (fhsize > NFS_SMALLFH) { 190 MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK); 191 } else 192 np->n_fhp = &np->n_fh; 193 bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); 194 np->n_fhsize = fhsize; 195 lockinit(&np->n_rslock, PVFS | rsflags, "nfrslk", 0, LK_NOPAUSE); 196 *npp = np; 197 198 if (nfs_node_hash_lock < 0) 199 wakeup(&nfs_node_hash_lock); 200 nfs_node_hash_lock = 0; 201 202 /* 203 * Lock the new nfsnode. 204 */ 205 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 206 207 return (0); 208} 209 210int 211nfs_inactive(ap) 212 struct vop_inactive_args /* { 213 struct vnode *a_vp; 214 struct proc *a_p; 215 } */ *ap; 216{ 217 register struct nfsnode *np; 218 register struct sillyrename *sp; 219 struct proc *p = curproc; /* XXX */ 220 221 np = VTONFS(ap->a_vp); 222 if (prtactive && ap->a_vp->v_usecount != 0) 223 vprint("nfs_inactive: pushing active", ap->a_vp); 224 if (ap->a_vp->v_type != VDIR) { 225 sp = np->n_sillyrename; 226 np->n_sillyrename = (struct sillyrename *)0; 227 } else 228 sp = (struct sillyrename *)0; 229 if (sp) { 230 /* 231 * We need a reference to keep the vnode from being 232 * recycled by getnewvnode while we do the I/O 233 * associated with discarding the buffers unless we 234 * are being forcibly unmounted in which case we already 235 * have our own reference. 236 */ 237 if (ap->a_vp->v_usecount > 0) 238 (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 239 else if (vget(ap->a_vp, 0, p)) 240 panic("nfs_inactive: lost vnode"); 241 else { 242 (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 243 vrele(ap->a_vp); 244 } 245 /* 246 * Remove the silly file that was rename'd earlier 247 */ 248 nfs_removeit(sp); 249 crfree(sp->s_cred); 250 vrele(sp->s_dvp); 251 FREE((caddr_t)sp, M_NFSREQ); 252 } 253 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 254 NQNFSNONCACHE | NQNFSWRITE); 255 VOP_UNLOCK(ap->a_vp, 0, ap->a_p); 256 return (0); 257} 258 259/* 260 * Reclaim an nfsnode so that it can be used for other purposes. 261 */ 262int 263nfs_reclaim(ap) 264 struct vop_reclaim_args /* { 265 struct vnode *a_vp; 266 } */ *ap; 267{ 268 register struct vnode *vp = ap->a_vp; 269 register struct nfsnode *np = VTONFS(vp); 270 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 271 register struct nfsdmap *dp, *dp2; 272 273 if (prtactive && vp->v_usecount != 0) 274 vprint("nfs_reclaim: pushing active", vp); 275 276 if (np->n_hash.le_prev != NULL) 277 LIST_REMOVE(np, n_hash); 278 279 /* 280 * For nqnfs, take it off the timer queue as required. 281 */ 282 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) { 283 CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer); 284 } 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 */ 291 if (vp->v_type == VDIR) { 292 dp = np->n_cookies.lh_first; 293 while (dp) { 294 dp2 = dp; 295 dp = dp->ndm_list.le_next; 296 FREE((caddr_t)dp2, M_NFSDIROFF); 297 } 298 } 299 if (np->n_fhsize > NFS_SMALLFH) { 300 FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 301 } 302
| 38 */ 39 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/proc.h> 44#include <sys/mount.h> 45#include <sys/namei.h> 46#include <sys/vnode.h> 47#include <sys/malloc.h> 48 49#include <vm/vm_zone.h> 50 51#include <nfs/rpcv2.h> 52#include <nfs/nfsproto.h> 53#include <nfs/nfs.h> 54#include <nfs/nfsnode.h> 55#include <nfs/nfsmount.h> 56 57static vm_zone_t nfsnode_zone; 58static LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl; 59static u_long nfsnodehash; 60 61#define TRUE 1 62#define FALSE 0 63 64/* 65 * Initialize hash links for nfsnodes 66 * and build nfsnode free list. 67 */ 68void 69nfs_nhinit() 70{ 71 nfsnode_zone = zinit("NFSNODE", sizeof(struct nfsnode), 0, 0, 1); 72 nfsnodehashtbl = hashinit(desiredvnodes, M_NFSHASH, &nfsnodehash); 73} 74 75/* 76 * Compute an entry in the NFS hash table structure 77 */ 78u_long 79nfs_hash(fhp, fhsize) 80 register nfsfh_t *fhp; 81 int fhsize; 82{ 83 register u_char *fhpp; 84 register u_long fhsum; 85 register int i; 86 87 fhpp = &fhp->fh_bytes[0]; 88 fhsum = 0; 89 for (i = 0; i < fhsize; i++) 90 fhsum += *fhpp++; 91 return (fhsum); 92} 93 94/* 95 * Look up a vnode/nfsnode by file handle. 96 * Callers must check for mount points!! 97 * In all cases, a pointer to a 98 * nfsnode structure is returned. 99 */ 100static int nfs_node_hash_lock; 101 102int 103nfs_nget(mntp, fhp, fhsize, npp) 104 struct mount *mntp; 105 register nfsfh_t *fhp; 106 int fhsize; 107 struct nfsnode **npp; 108{ 109 struct proc *p = curproc; /* XXX */ 110 struct nfsnode *np, *np2; 111 struct nfsnodehashhead *nhpp; 112 register struct vnode *vp; 113 struct vnode *nvp; 114 int error; 115 int rsflags; 116 struct nfsmount *nmp; 117 118 /* 119 * Calculate nfs mount point and figure out whether the rslock should 120 * be interruptable or not. 121 */ 122 nmp = VFSTONFS(mntp); 123 if (nmp->nm_flag & NFSMNT_INT) 124 rsflags = PCATCH; 125 else 126 rsflags = 0; 127 128retry: 129 nhpp = NFSNOHASH(nfs_hash(fhp, fhsize)); 130loop: 131 for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) { 132 if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize || 133 bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize)) 134 continue; 135 vp = NFSTOV(np); 136 if (vget(vp, LK_EXCLUSIVE, p)) 137 goto loop; 138 *npp = np; 139 return(0); 140 } 141 /* 142 * Obtain a lock to prevent a race condition if the getnewvnode() 143 * or MALLOC() below happens to block. 144 */ 145 if (nfs_node_hash_lock) { 146 while (nfs_node_hash_lock) { 147 nfs_node_hash_lock = -1; 148 tsleep(&nfs_node_hash_lock, PVM, "nfsngt", 0); 149 } 150 goto loop; 151 } 152 nfs_node_hash_lock = 1; 153 154 /* 155 * Allocate before getnewvnode since doing so afterward 156 * might cause a bogus v_data pointer to get dereferenced 157 * elsewhere if zalloc should block. 158 */ 159 np = zalloc(nfsnode_zone); 160 161 error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp); 162 if (error) { 163 if (nfs_node_hash_lock < 0) 164 wakeup(&nfs_node_hash_lock); 165 nfs_node_hash_lock = 0; 166 *npp = 0; 167 zfree(nfsnode_zone, np); 168 return (error); 169 } 170 vp = nvp; 171 bzero((caddr_t)np, sizeof *np); 172 vp->v_data = np; 173 np->n_vnode = vp; 174 /* 175 * Insert the nfsnode in the hash queue for its new file handle 176 */ 177 for (np2 = nhpp->lh_first; np2 != 0; np2 = np2->n_hash.le_next) { 178 if (mntp != NFSTOV(np2)->v_mount || np2->n_fhsize != fhsize || 179 bcmp((caddr_t)fhp, (caddr_t)np2->n_fhp, fhsize)) 180 continue; 181 vrele(vp); 182 if (nfs_node_hash_lock < 0) 183 wakeup(&nfs_node_hash_lock); 184 nfs_node_hash_lock = 0; 185 zfree(nfsnode_zone, np); 186 goto retry; 187 } 188 LIST_INSERT_HEAD(nhpp, np, n_hash); 189 if (fhsize > NFS_SMALLFH) { 190 MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK); 191 } else 192 np->n_fhp = &np->n_fh; 193 bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize); 194 np->n_fhsize = fhsize; 195 lockinit(&np->n_rslock, PVFS | rsflags, "nfrslk", 0, LK_NOPAUSE); 196 *npp = np; 197 198 if (nfs_node_hash_lock < 0) 199 wakeup(&nfs_node_hash_lock); 200 nfs_node_hash_lock = 0; 201 202 /* 203 * Lock the new nfsnode. 204 */ 205 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 206 207 return (0); 208} 209 210int 211nfs_inactive(ap) 212 struct vop_inactive_args /* { 213 struct vnode *a_vp; 214 struct proc *a_p; 215 } */ *ap; 216{ 217 register struct nfsnode *np; 218 register struct sillyrename *sp; 219 struct proc *p = curproc; /* XXX */ 220 221 np = VTONFS(ap->a_vp); 222 if (prtactive && ap->a_vp->v_usecount != 0) 223 vprint("nfs_inactive: pushing active", ap->a_vp); 224 if (ap->a_vp->v_type != VDIR) { 225 sp = np->n_sillyrename; 226 np->n_sillyrename = (struct sillyrename *)0; 227 } else 228 sp = (struct sillyrename *)0; 229 if (sp) { 230 /* 231 * We need a reference to keep the vnode from being 232 * recycled by getnewvnode while we do the I/O 233 * associated with discarding the buffers unless we 234 * are being forcibly unmounted in which case we already 235 * have our own reference. 236 */ 237 if (ap->a_vp->v_usecount > 0) 238 (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 239 else if (vget(ap->a_vp, 0, p)) 240 panic("nfs_inactive: lost vnode"); 241 else { 242 (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1); 243 vrele(ap->a_vp); 244 } 245 /* 246 * Remove the silly file that was rename'd earlier 247 */ 248 nfs_removeit(sp); 249 crfree(sp->s_cred); 250 vrele(sp->s_dvp); 251 FREE((caddr_t)sp, M_NFSREQ); 252 } 253 np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED | 254 NQNFSNONCACHE | NQNFSWRITE); 255 VOP_UNLOCK(ap->a_vp, 0, ap->a_p); 256 return (0); 257} 258 259/* 260 * Reclaim an nfsnode so that it can be used for other purposes. 261 */ 262int 263nfs_reclaim(ap) 264 struct vop_reclaim_args /* { 265 struct vnode *a_vp; 266 } */ *ap; 267{ 268 register struct vnode *vp = ap->a_vp; 269 register struct nfsnode *np = VTONFS(vp); 270 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 271 register struct nfsdmap *dp, *dp2; 272 273 if (prtactive && vp->v_usecount != 0) 274 vprint("nfs_reclaim: pushing active", vp); 275 276 if (np->n_hash.le_prev != NULL) 277 LIST_REMOVE(np, n_hash); 278 279 /* 280 * For nqnfs, take it off the timer queue as required. 281 */ 282 if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) { 283 CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer); 284 } 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 */ 291 if (vp->v_type == VDIR) { 292 dp = np->n_cookies.lh_first; 293 while (dp) { 294 dp2 = dp; 295 dp = dp->ndm_list.le_next; 296 FREE((caddr_t)dp2, M_NFSDIROFF); 297 } 298 } 299 if (np->n_fhsize > NFS_SMALLFH) { 300 FREE((caddr_t)np->n_fhp, M_NFSBIGFH); 301 } 302
|
303 cache_purge(vp); 304 zfree(nfsnode_zone, vp->v_data); 305 vp->v_data = (void *)0; 306 return (0); 307} 308 309#if 0 310/* 311 * Lock an nfsnode 312 */ 313int 314nfs_lock(ap) 315 struct vop_lock_args /* { 316 struct vnode *a_vp; 317 } */ *ap; 318{ 319 register struct vnode *vp = ap->a_vp; 320 321 /* 322 * Ugh, another place where interruptible mounts will get hung. 323 * If you make this sleep interruptible, then you have to fix all 324 * the VOP_LOCK() calls to expect interruptibility. 325 */ 326 while (vp->v_flag & VXLOCK) { 327 vp->v_flag |= VXWANT; 328 (void) tsleep((caddr_t)vp, PINOD, "nfslck", 0); 329 } 330 if (vp->v_tag == VT_NON) 331 return (ENOENT); 332 333#if 0 334 /* 335 * Only lock regular files. If a server crashed while we were 336 * holding a directory lock, we could easily end up sleeping 337 * until the server rebooted while holding a lock on the root. 338 * Locks are only needed for protecting critical sections in 339 * VMIO at the moment. 340 * New vnodes will have type VNON but they should be locked 341 * since they may become VREG. This is checked in loadattrcache 342 * and unwanted locks are released there. 343 */ 344 if (vp->v_type == VREG || vp->v_type == VNON) { 345 while (np->n_flag & NLOCKED) { 346 np->n_flag |= NWANTED; 347 (void) tsleep((caddr_t) np, PINOD, "nfslck2", 0); 348 /* 349 * If the vnode has transmuted into a VDIR while we 350 * were asleep, then skip the lock. 351 */ 352 if (vp->v_type != VREG && vp->v_type != VNON) 353 return (0); 354 } 355 np->n_flag |= NLOCKED; 356 } 357#endif 358 359 return (0); 360} 361 362/* 363 * Unlock an nfsnode 364 */ 365int 366nfs_unlock(ap) 367 struct vop_unlock_args /* { 368 struct vnode *a_vp; 369 } */ *ap; 370{ 371#if 0 372 struct vnode* vp = ap->a_vp; 373 struct nfsnode* np = VTONFS(vp); 374 375 if (vp->v_type == VREG || vp->v_type == VNON) { 376 if (!(np->n_flag & NLOCKED)) 377 panic("nfs_unlock: nfsnode not locked"); 378 np->n_flag &= ~NLOCKED; 379 if (np->n_flag & NWANTED) { 380 np->n_flag &= ~NWANTED; 381 wakeup((caddr_t) np); 382 } 383 } 384#endif 385 386 return (0); 387} 388 389/* 390 * Check for a locked nfsnode 391 */ 392int 393nfs_islocked(ap) 394 struct vop_islocked_args /* { 395 struct vnode *a_vp; 396 struct proc *a_p; 397 } */ *ap; 398{ 399 return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0; 400} 401#endif 402
| 305 cache_purge(vp); 306 zfree(nfsnode_zone, vp->v_data); 307 vp->v_data = (void *)0; 308 return (0); 309} 310 311#if 0 312/* 313 * Lock an nfsnode 314 */ 315int 316nfs_lock(ap) 317 struct vop_lock_args /* { 318 struct vnode *a_vp; 319 } */ *ap; 320{ 321 register struct vnode *vp = ap->a_vp; 322 323 /* 324 * Ugh, another place where interruptible mounts will get hung. 325 * If you make this sleep interruptible, then you have to fix all 326 * the VOP_LOCK() calls to expect interruptibility. 327 */ 328 while (vp->v_flag & VXLOCK) { 329 vp->v_flag |= VXWANT; 330 (void) tsleep((caddr_t)vp, PINOD, "nfslck", 0); 331 } 332 if (vp->v_tag == VT_NON) 333 return (ENOENT); 334 335#if 0 336 /* 337 * Only lock regular files. If a server crashed while we were 338 * holding a directory lock, we could easily end up sleeping 339 * until the server rebooted while holding a lock on the root. 340 * Locks are only needed for protecting critical sections in 341 * VMIO at the moment. 342 * New vnodes will have type VNON but they should be locked 343 * since they may become VREG. This is checked in loadattrcache 344 * and unwanted locks are released there. 345 */ 346 if (vp->v_type == VREG || vp->v_type == VNON) { 347 while (np->n_flag & NLOCKED) { 348 np->n_flag |= NWANTED; 349 (void) tsleep((caddr_t) np, PINOD, "nfslck2", 0); 350 /* 351 * If the vnode has transmuted into a VDIR while we 352 * were asleep, then skip the lock. 353 */ 354 if (vp->v_type != VREG && vp->v_type != VNON) 355 return (0); 356 } 357 np->n_flag |= NLOCKED; 358 } 359#endif 360 361 return (0); 362} 363 364/* 365 * Unlock an nfsnode 366 */ 367int 368nfs_unlock(ap) 369 struct vop_unlock_args /* { 370 struct vnode *a_vp; 371 } */ *ap; 372{ 373#if 0 374 struct vnode* vp = ap->a_vp; 375 struct nfsnode* np = VTONFS(vp); 376 377 if (vp->v_type == VREG || vp->v_type == VNON) { 378 if (!(np->n_flag & NLOCKED)) 379 panic("nfs_unlock: nfsnode not locked"); 380 np->n_flag &= ~NLOCKED; 381 if (np->n_flag & NWANTED) { 382 np->n_flag &= ~NWANTED; 383 wakeup((caddr_t) np); 384 } 385 } 386#endif 387 388 return (0); 389} 390 391/* 392 * Check for a locked nfsnode 393 */ 394int 395nfs_islocked(ap) 396 struct vop_islocked_args /* { 397 struct vnode *a_vp; 398 struct proc *a_p; 399 } */ *ap; 400{ 401 return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0; 402} 403#endif 404
|