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*39575Smckusick * @(#)nfs_node.c 7.13 (Berkeley) 11/21/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 6639494Smckusick #ifndef lint 6739395Smckusick if (VN_MAXPRIVATE < sizeof(struct nfsnode)) 6839395Smckusick panic("nfs_nhinit: too small"); 6939494Smckusick #endif /* not lint */ 7038415Smckusick for (i = NFSNOHSZ; --i >= 0; nh++) { 7138415Smckusick nh->nh_head[0] = nh; 7238415Smckusick nh->nh_head[1] = nh; 7338415Smckusick } 7438415Smckusick } 7538415Smckusick 7638415Smckusick /* 7739445Smckusick * Compute an entry in the NFS hash table structure 7839445Smckusick */ 7939445Smckusick union nhead * 8039445Smckusick nfs_hash(fhp) 8139445Smckusick register nfsv2fh_t *fhp; 8239445Smckusick { 8339445Smckusick register u_char *fhpp; 8439445Smckusick register u_long fhsum; 8539445Smckusick int i; 8639445Smckusick 8739445Smckusick fhpp = &fhp->fh_bytes[0]; 8839445Smckusick fhsum = 0; 8939445Smckusick for (i = 0; i < NFSX_FH; i++) 9039445Smckusick fhsum += *fhpp++; 9139445Smckusick return (&nhead[NFSNOHASH(fhsum)]); 9239445Smckusick } 9339445Smckusick 9439445Smckusick /* 9539395Smckusick * Look up a vnode/nfsnode by file handle. 9638415Smckusick * Callers must check for mount points!! 9738415Smckusick * In all cases, a pointer to a 9838415Smckusick * nfsnode structure is returned. 9938415Smckusick */ 10038415Smckusick nfs_nget(mntp, fhp, npp) 10138415Smckusick struct mount *mntp; 10238415Smckusick register nfsv2fh_t *fhp; 10338415Smckusick struct nfsnode **npp; 10438415Smckusick { 10538415Smckusick register struct nfsnode *np; 10638415Smckusick register struct vnode *vp; 10739445Smckusick extern struct vnodeops nfsv2_vnodeops; 10839395Smckusick struct vnode *nvp; 10939395Smckusick union nhead *nh; 11039445Smckusick int error; 11138415Smckusick 11239445Smckusick nh = nfs_hash(fhp); 11338415Smckusick loop: 11438884Smacklem for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) { 11539395Smckusick if (mntp != NFSTOV(np)->v_mount || 11639395Smckusick bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH)) 11739395Smckusick continue; 11839395Smckusick if ((np->n_flag & NLOCKED) != 0) { 11939395Smckusick np->n_flag |= NWANT; 12039395Smckusick sleep((caddr_t)np, PINOD); 12139395Smckusick goto loop; 12239395Smckusick } 12339395Smckusick vp = NFSTOV(np); 12439445Smckusick if (vget(vp)) 12539445Smckusick goto loop; 12639395Smckusick *npp = np; 12739395Smckusick return(0); 12838884Smacklem } 12939395Smckusick if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) { 13038415Smckusick *npp = 0; 13139395Smckusick return (error); 13238415Smckusick } 13339395Smckusick vp = nvp; 13439395Smckusick np = VTONFS(vp); 13539395Smckusick np->n_vnode = vp; 13638415Smckusick /* 13738884Smacklem * Insert the nfsnode in the hash queue for its new file handle 13838884Smacklem */ 13938884Smacklem np->n_flag = NLOCKED; 14038415Smckusick insque(np, nh); 14138415Smckusick bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH); 14238415Smckusick np->n_attrstamp = 0; 14338415Smckusick np->n_sillyrename = (struct sillyrename *)0; 14438884Smacklem np->n_size = 0; 14538884Smacklem np->n_mtime = 0; 14638415Smckusick *npp = np; 14738415Smckusick return (0); 14838415Smckusick } 14938415Smckusick 15038415Smckusick nfs_inactive(vp) 15138415Smckusick struct vnode *vp; 15238415Smckusick { 15338415Smckusick register struct nfsnode *np; 15438415Smckusick register struct nameidata *ndp; 15538415Smckusick register struct sillyrename *sp; 15638415Smckusick struct nfsnode *dnp; 157*39575Smckusick extern int prtactive; 15838415Smckusick 15939395Smckusick np = VTONFS(vp); 160*39575Smckusick if (prtactive && vp->v_count != 0) 16139445Smckusick printf("nfs_inactive: pushing active fileid %d fsid 0x%x\n", 16239445Smckusick np->n_vattr.va_fileid, np->n_vattr.va_fsid); 16339395Smckusick nfs_lock(vp); 16439395Smckusick sp = np->n_sillyrename; 16539395Smckusick np->n_sillyrename = (struct sillyrename *)0; 16639395Smckusick if (sp) { 16738415Smckusick /* 16839395Smckusick * Remove the silly file that was rename'd earlier 16938415Smckusick */ 17039395Smckusick ndp = &sp->s_namei; 17139395Smckusick if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) { 17239395Smckusick ndp->ni_dvp = NFSTOV(dnp); 17339395Smckusick nfs_removeit(ndp); 17439395Smckusick nfs_nput(ndp->ni_dvp); 17538415Smckusick } 17639395Smckusick crfree(ndp->ni_cred); 17739395Smckusick free((caddr_t)sp, M_TEMP); 17839395Smckusick } 17939395Smckusick nfs_unlock(vp); 18039399Smckusick np->n_flag &= NBUFFERED; 18139395Smckusick #ifdef notdef 18239395Smckusick /* 18339395Smckusick * Scan the request list for any requests left hanging about 18439395Smckusick */ 18539395Smckusick s = splnet(); 18639395Smckusick rep = nfsreqh.r_next; 18739395Smckusick while (rep && rep != &nfsreqh) { 18839395Smckusick if (rep->r_vp == vp) { 18939395Smckusick rep->r_prev->r_next = rep2 = rep->r_next; 19039395Smckusick rep->r_next->r_prev = rep->r_prev; 19139395Smckusick m_freem(rep->r_mreq); 19239395Smckusick if (rep->r_mrep != NULL) 19339395Smckusick m_freem(rep->r_mrep); 19439395Smckusick free((caddr_t)rep, M_NFSREQ); 19539395Smckusick rep = rep2; 19639395Smckusick } else 19739395Smckusick rep = rep->r_next; 19839395Smckusick } 19939395Smckusick splx(s); 20038884Smacklem #endif 20139395Smckusick return (0); 20239395Smckusick } 20339395Smckusick 20439395Smckusick /* 20539395Smckusick * Reclaim an nfsnode so that it can be used for other purposes. 20639395Smckusick */ 20739395Smckusick nfs_reclaim(vp) 20839395Smckusick register struct vnode *vp; 20939395Smckusick { 21039395Smckusick register struct nfsnode *np = VTONFS(vp); 211*39575Smckusick extern int prtactive; 21239395Smckusick 21339522Smckusick /* 21439522Smckusick * Flush out any associated bio buffers that might be lying about 21539522Smckusick */ 21639522Smckusick if (vp->v_type == VREG && (np->n_flag & NBUFFERED)) { 21739522Smckusick nfs_lock(np); 21839522Smckusick nfs_blkflush(vp, (daddr_t)0, np->n_size, TRUE); 21939522Smckusick nfs_unlock(np); 22039522Smckusick } 221*39575Smckusick if (prtactive && vp->v_count != 0) 22239445Smckusick printf("nfs_reclaim: pushing active fileid %d fsid 0x%x\n", 22339445Smckusick np->n_vattr.va_fileid, np->n_vattr.va_fsid); 22439395Smckusick /* 22539395Smckusick * Remove the nfsnode from its hash chain. 22639395Smckusick */ 22739395Smckusick remque(np); 22839395Smckusick np->n_forw = np; 22939395Smckusick np->n_back = np; 23039395Smckusick cache_purge(vp); 23138415Smckusick return (0); 23238415Smckusick } 23338415Smckusick 23438415Smckusick /* 23538415Smckusick * Lock an nfsnode 23638415Smckusick */ 23738415Smckusick nfs_lock(vp) 23838415Smckusick struct vnode *vp; 23938415Smckusick { 24038415Smckusick register struct nfsnode *np = VTONFS(vp); 24138415Smckusick 24238415Smckusick while (np->n_flag & NLOCKED) { 24338415Smckusick np->n_flag |= NWANT; 24438415Smckusick sleep((caddr_t)np, PINOD); 24538415Smckusick } 24638415Smckusick np->n_flag |= NLOCKED; 24738415Smckusick } 24838415Smckusick 24938415Smckusick /* 25038415Smckusick * Unlock an nfsnode 25138415Smckusick */ 25238415Smckusick nfs_unlock(vp) 25338415Smckusick struct vnode *vp; 25438415Smckusick { 25538415Smckusick register struct nfsnode *np = VTONFS(vp); 25638415Smckusick 25738415Smckusick np->n_flag &= ~NLOCKED; 25838415Smckusick if (np->n_flag & NWANT) { 25938415Smckusick np->n_flag &= ~NWANT; 26038415Smckusick wakeup((caddr_t)np); 26138415Smckusick } 26238415Smckusick } 26338415Smckusick 26438415Smckusick /* 26538415Smckusick * Unlock and vrele() 26638415Smckusick * since I can't decide if dirs. should be locked, I will check for 26738415Smckusick * the lock and be flexible 26838415Smckusick */ 26938415Smckusick nfs_nput(vp) 27038415Smckusick struct vnode *vp; 27138415Smckusick { 27238415Smckusick register struct nfsnode *np = VTONFS(vp); 27338415Smckusick 27438415Smckusick if (np->n_flag & NLOCKED) 27538415Smckusick nfs_unlock(vp); 27638415Smckusick vrele(vp); 27738415Smckusick } 27838415Smckusick 27938415Smckusick nfs_abortop(ndp) 28038415Smckusick register struct nameidata *ndp; 28138415Smckusick { 28238415Smckusick register struct nfsnode *np; 28338415Smckusick 28438415Smckusick if (ndp->ni_vp != NULL) { 28538415Smckusick np = VTONFS(ndp->ni_vp); 28638415Smckusick if (np->n_flag & NLOCKED) 28738415Smckusick nfs_unlock(ndp->ni_vp); 28838415Smckusick vrele(ndp->ni_vp); 28938415Smckusick } 29038415Smckusick if (ndp->ni_dvp != NULL) { 29138415Smckusick np = VTONFS(ndp->ni_dvp); 29238415Smckusick if (np->n_flag & NLOCKED) 29338415Smckusick nfs_unlock(ndp->ni_dvp); 29438415Smckusick vrele(ndp->ni_dvp); 29538415Smckusick } 29638415Smckusick } 29738415Smckusick 29838415Smckusick /* 29938415Smckusick * This is silly, but if you use a macro and try and use it in a file 30038415Smckusick * that has mbuf.h included, m_data --> m_hdr.mh_data and this is not 30138415Smckusick * a good thing 30238415Smckusick */ 30338415Smckusick struct nfsmount *vfs_to_nfs(mp) 30438415Smckusick struct mount *mp; 30538415Smckusick { 30638415Smckusick return ((struct nfsmount *)mp->m_data); 30738415Smckusick } 308