138415Smckusick /* 238415Smckusick * Copyright (c) 1989 The Regents of the University of California. 338415Smckusick * All rights reserved. 438415Smckusick * 538415Smckusick * This code is derived from software contributed to Berkeley by 638415Smckusick * Rick Macklem at The University of Guelph. 738415Smckusick * 838415Smckusick * Redistribution and use in source and binary forms are permitted 938415Smckusick * provided that the above copyright notice and this paragraph are 1038415Smckusick * duplicated in all such forms and that any documentation, 1138415Smckusick * advertising materials, and other materials related to such 1238415Smckusick * distribution and use acknowledge that the software was developed 1338415Smckusick * by the University of California, Berkeley. The name of the 1438415Smckusick * University may not be used to endorse or promote products derived 1538415Smckusick * from this software without specific prior written permission. 1638415Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1738415Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1838415Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1938415Smckusick * 20*39445Smckusick * @(#)nfs_node.c 7.9 (Berkeley) 10/29/89 2138415Smckusick */ 2238415Smckusick 2338415Smckusick #include "param.h" 2438415Smckusick #include "systm.h" 2538415Smckusick #include "user.h" 2638415Smckusick #include "proc.h" 2738415Smckusick #include "mount.h" 2838415Smckusick #include "vnode.h" 2938425Smckusick #include "../ufs/dir.h" 3038415Smckusick #include "namei.h" 3138415Smckusick #include "errno.h" 3238415Smckusick #include "nfsv2.h" 3338415Smckusick #include "nfs.h" 3438415Smckusick #include "nfsnode.h" 3538415Smckusick #include "nfsmount.h" 3638415Smckusick #include "kernel.h" 3738415Smckusick #include "malloc.h" 3838415Smckusick 3938415Smckusick /* The request list head */ 4038415Smckusick extern struct nfsreq nfsreqh; 4138415Smckusick 4238415Smckusick #define NFSNOHSZ 512 4338415Smckusick #if ((NFSNOHSZ&(NFSNOHSZ-1)) == 0) 4438415Smckusick #define NFSNOHASH(fhsum) ((fhsum)&(NFSNOHSZ-1)) 4538415Smckusick #else 4638415Smckusick #define NFSNOHASH(fhsum) (((unsigned)(fhsum))%NFSNOHSZ) 4738415Smckusick #endif 4838415Smckusick 4939395Smckusick union nhead { 5038415Smckusick union nhead *nh_head[2]; 5138415Smckusick struct nfsnode *nh_chain[2]; 5238415Smckusick } nhead[NFSNOHSZ]; 5338415Smckusick 5438884Smacklem #define TRUE 1 5538884Smacklem #define FALSE 0 5638884Smacklem 5738415Smckusick /* 5838415Smckusick * Initialize hash links for nfsnodes 5938415Smckusick * and build nfsnode free list. 6038415Smckusick */ 6138415Smckusick nfs_nhinit() 6238415Smckusick { 6338415Smckusick register int i; 6438415Smckusick register union nhead *nh = nhead; 6538415Smckusick 6639395Smckusick if (VN_MAXPRIVATE < sizeof(struct nfsnode)) 6739395Smckusick panic("nfs_nhinit: too small"); 6838415Smckusick for (i = NFSNOHSZ; --i >= 0; nh++) { 6938415Smckusick nh->nh_head[0] = nh; 7038415Smckusick nh->nh_head[1] = nh; 7138415Smckusick } 7238415Smckusick } 7338415Smckusick 7438415Smckusick /* 75*39445Smckusick * Compute an entry in the NFS hash table structure 76*39445Smckusick */ 77*39445Smckusick union nhead * 78*39445Smckusick nfs_hash(fhp) 79*39445Smckusick register nfsv2fh_t *fhp; 80*39445Smckusick { 81*39445Smckusick register u_char *fhpp; 82*39445Smckusick register u_long fhsum; 83*39445Smckusick int i; 84*39445Smckusick 85*39445Smckusick fhpp = &fhp->fh_bytes[0]; 86*39445Smckusick fhsum = 0; 87*39445Smckusick for (i = 0; i < NFSX_FH; i++) 88*39445Smckusick fhsum += *fhpp++; 89*39445Smckusick return (&nhead[NFSNOHASH(fhsum)]); 90*39445Smckusick } 91*39445Smckusick 92*39445Smckusick /* 9339395Smckusick * Look up a vnode/nfsnode by file handle. 9438415Smckusick * Callers must check for mount points!! 9538415Smckusick * In all cases, a pointer to a 9638415Smckusick * nfsnode structure is returned. 9738415Smckusick */ 9838415Smckusick nfs_nget(mntp, fhp, npp) 9938415Smckusick struct mount *mntp; 10038415Smckusick register nfsv2fh_t *fhp; 10138415Smckusick struct nfsnode **npp; 10238415Smckusick { 10338415Smckusick register struct nfsnode *np; 10438415Smckusick register struct vnode *vp; 105*39445Smckusick extern struct vnodeops nfsv2_vnodeops; 10639395Smckusick struct vnode *nvp; 10739395Smckusick union nhead *nh; 108*39445Smckusick int error; 10938415Smckusick 110*39445Smckusick nh = nfs_hash(fhp); 11138415Smckusick loop: 11238884Smacklem for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) { 11339395Smckusick if (mntp != NFSTOV(np)->v_mount || 11439395Smckusick bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH)) 11539395Smckusick continue; 11639395Smckusick if ((np->n_flag & NLOCKED) != 0) { 11739395Smckusick np->n_flag |= NWANT; 11839395Smckusick sleep((caddr_t)np, PINOD); 11939395Smckusick goto loop; 12039395Smckusick } 12139395Smckusick vp = NFSTOV(np); 122*39445Smckusick if (vget(vp)) 123*39445Smckusick goto loop; 12439395Smckusick *npp = np; 12539395Smckusick return(0); 12638884Smacklem } 12739395Smckusick if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) { 12838415Smckusick *npp = 0; 12939395Smckusick return (error); 13038415Smckusick } 13139395Smckusick vp = nvp; 13239395Smckusick np = VTONFS(vp); 13339395Smckusick np->n_vnode = vp; 13438415Smckusick /* 13538884Smacklem * Insert the nfsnode in the hash queue for its new file handle 13638884Smacklem */ 13738884Smacklem np->n_flag = NLOCKED; 13838415Smckusick insque(np, nh); 13938415Smckusick bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH); 14038415Smckusick np->n_attrstamp = 0; 14138415Smckusick np->n_sillyrename = (struct sillyrename *)0; 14238884Smacklem np->n_size = 0; 14338884Smacklem np->n_mtime = 0; 14438415Smckusick *npp = np; 14538415Smckusick return (0); 14638415Smckusick } 14738415Smckusick 14838415Smckusick nfs_inactive(vp) 14938415Smckusick struct vnode *vp; 15038415Smckusick { 15138415Smckusick register struct nfsnode *np; 15238415Smckusick register struct nameidata *ndp; 15338415Smckusick register struct sillyrename *sp; 15438415Smckusick struct nfsnode *dnp; 15538415Smckusick 15639395Smckusick np = VTONFS(vp); 157*39445Smckusick if (vp->v_count != 0) 158*39445Smckusick printf("nfs_inactive: pushing active fileid %d fsid 0x%x\n", 159*39445Smckusick np->n_vattr.va_fileid, np->n_vattr.va_fsid); 16039395Smckusick nfs_lock(vp); 16139395Smckusick sp = np->n_sillyrename; 16239395Smckusick np->n_sillyrename = (struct sillyrename *)0; 16339395Smckusick if (sp) { 16438415Smckusick /* 16539395Smckusick * Remove the silly file that was rename'd earlier 16638415Smckusick */ 16739395Smckusick ndp = &sp->s_namei; 16839395Smckusick if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) { 16939395Smckusick ndp->ni_dvp = NFSTOV(dnp); 17039395Smckusick nfs_removeit(ndp); 17139395Smckusick nfs_nput(ndp->ni_dvp); 17238415Smckusick } 17339395Smckusick crfree(ndp->ni_cred); 17439395Smckusick free((caddr_t)sp, M_TEMP); 17539395Smckusick } 17639395Smckusick nfs_unlock(vp); 17739399Smckusick np->n_flag &= NBUFFERED; 17839395Smckusick #ifdef notdef 17939395Smckusick /* 18039395Smckusick * Scan the request list for any requests left hanging about 18139395Smckusick */ 18239395Smckusick s = splnet(); 18339395Smckusick rep = nfsreqh.r_next; 18439395Smckusick while (rep && rep != &nfsreqh) { 18539395Smckusick if (rep->r_vp == vp) { 18639395Smckusick rep->r_prev->r_next = rep2 = rep->r_next; 18739395Smckusick rep->r_next->r_prev = rep->r_prev; 18839395Smckusick m_freem(rep->r_mreq); 18939395Smckusick if (rep->r_mrep != NULL) 19039395Smckusick m_freem(rep->r_mrep); 19139395Smckusick free((caddr_t)rep, M_NFSREQ); 19239395Smckusick rep = rep2; 19339395Smckusick } else 19439395Smckusick rep = rep->r_next; 19539395Smckusick } 19639395Smckusick splx(s); 19738884Smacklem #endif 19839395Smckusick return (0); 19939395Smckusick } 20039395Smckusick 20139395Smckusick /* 20239395Smckusick * Reclaim an nfsnode so that it can be used for other purposes. 20339395Smckusick */ 20439395Smckusick nfs_reclaim(vp) 20539395Smckusick register struct vnode *vp; 20639395Smckusick { 20739395Smckusick register struct nfsnode *np = VTONFS(vp); 20839395Smckusick 20939395Smckusick if (vp->v_count != 0) 210*39445Smckusick printf("nfs_reclaim: pushing active fileid %d fsid 0x%x\n", 211*39445Smckusick np->n_vattr.va_fileid, np->n_vattr.va_fsid); 21239395Smckusick /* 21339395Smckusick * Remove the nfsnode from its hash chain. 21439395Smckusick */ 21539395Smckusick remque(np); 21639395Smckusick np->n_forw = np; 21739395Smckusick np->n_back = np; 21839395Smckusick cache_purge(vp); 21939395Smckusick /* 22039395Smckusick * Flush out any associated bio buffers that might be lying about 22139395Smckusick */ 22239395Smckusick if (vp->v_type == VREG && (np->n_flag & NBUFFERED)) { 22339395Smckusick np->n_flag |= NLOCKED; 22439395Smckusick nfs_blkflush(vp, (daddr_t)0, np->n_size, TRUE); 22538415Smckusick } 22638415Smckusick return (0); 22738415Smckusick } 22838415Smckusick 22938415Smckusick /* 23038415Smckusick * Remove any nfsnodes in the nfsnode cache belonging to mount. 23138415Smckusick * 23238415Smckusick * There should not be any active ones, return error if any are found 23338415Smckusick * (nb: this is a user error, not a system err). 23438415Smckusick */ 23538415Smckusick nfs_nflush(mntp) 23638415Smckusick struct mount *mntp; 23738415Smckusick { 238*39445Smckusick register struct vnode *nvp, *vp; 23939395Smckusick int busy = 0; 24038415Smckusick 241*39445Smckusick for (vp = mntp->m_mounth; vp; vp = nvp) { 242*39445Smckusick nvp = vp->v_mountf; 24339395Smckusick if (vp->v_count) { 24439395Smckusick busy++; 24539395Smckusick continue; 24639395Smckusick } 24739395Smckusick /* 248*39445Smckusick * With v_count == 0, all we need to do is clear out the 249*39445Smckusick * vnode data structures and we are done. 25039395Smckusick */ 251*39445Smckusick vgone(vp); 25238415Smckusick } 25339395Smckusick if (busy) 25439395Smckusick return (EBUSY); 25538415Smckusick return (0); 25638415Smckusick } 25738415Smckusick 25838415Smckusick /* 25938415Smckusick * Lock an nfsnode 26038415Smckusick */ 26138415Smckusick nfs_lock(vp) 26238415Smckusick struct vnode *vp; 26338415Smckusick { 26438415Smckusick register struct nfsnode *np = VTONFS(vp); 26538415Smckusick 26638415Smckusick while (np->n_flag & NLOCKED) { 26738415Smckusick np->n_flag |= NWANT; 26838415Smckusick sleep((caddr_t)np, PINOD); 26938415Smckusick } 27038415Smckusick np->n_flag |= NLOCKED; 27138415Smckusick } 27238415Smckusick 27338415Smckusick /* 27438415Smckusick * Unlock an nfsnode 27538415Smckusick */ 27638415Smckusick nfs_unlock(vp) 27738415Smckusick struct vnode *vp; 27838415Smckusick { 27938415Smckusick register struct nfsnode *np = VTONFS(vp); 28038415Smckusick 28138415Smckusick np->n_flag &= ~NLOCKED; 28238415Smckusick if (np->n_flag & NWANT) { 28338415Smckusick np->n_flag &= ~NWANT; 28438415Smckusick wakeup((caddr_t)np); 28538415Smckusick } 28638415Smckusick } 28738415Smckusick 28838415Smckusick /* 28938415Smckusick * Unlock and vrele() 29038415Smckusick * since I can't decide if dirs. should be locked, I will check for 29138415Smckusick * the lock and be flexible 29238415Smckusick */ 29338415Smckusick nfs_nput(vp) 29438415Smckusick struct vnode *vp; 29538415Smckusick { 29638415Smckusick register struct nfsnode *np = VTONFS(vp); 29738415Smckusick 29838415Smckusick if (np->n_flag & NLOCKED) 29938415Smckusick nfs_unlock(vp); 30038415Smckusick vrele(vp); 30138415Smckusick } 30238415Smckusick 30338415Smckusick nfs_abortop(ndp) 30438415Smckusick register struct nameidata *ndp; 30538415Smckusick { 30638415Smckusick register struct nfsnode *np; 30738415Smckusick 30838415Smckusick if (ndp->ni_vp != NULL) { 30938415Smckusick np = VTONFS(ndp->ni_vp); 31038415Smckusick if (np->n_flag & NLOCKED) 31138415Smckusick nfs_unlock(ndp->ni_vp); 31238415Smckusick vrele(ndp->ni_vp); 31338415Smckusick } 31438415Smckusick if (ndp->ni_dvp != NULL) { 31538415Smckusick np = VTONFS(ndp->ni_dvp); 31638415Smckusick if (np->n_flag & NLOCKED) 31738415Smckusick nfs_unlock(ndp->ni_dvp); 31838415Smckusick vrele(ndp->ni_dvp); 31938415Smckusick } 32038415Smckusick } 32138415Smckusick 32238415Smckusick /* 32338415Smckusick * This is silly, but if you use a macro and try and use it in a file 32438415Smckusick * that has mbuf.h included, m_data --> m_hdr.mh_data and this is not 32538415Smckusick * a good thing 32638415Smckusick */ 32738415Smckusick struct nfsmount *vfs_to_nfs(mp) 32838415Smckusick struct mount *mp; 32938415Smckusick { 33038415Smckusick return ((struct nfsmount *)mp->m_data); 33138415Smckusick } 332