Home | History | Annotate | Line # | Download | only in nfs
nfs_node.c revision 1.2.2.1
      1      1.1  cgd /*
      2      1.1  cgd  * Copyright (c) 1989 The Regents of the University of California.
      3      1.1  cgd  * All rights reserved.
      4      1.1  cgd  *
      5      1.1  cgd  * This code is derived from software contributed to Berkeley by
      6      1.1  cgd  * Rick Macklem at The University of Guelph.
      7      1.1  cgd  *
      8      1.1  cgd  * Redistribution and use in source and binary forms, with or without
      9      1.1  cgd  * modification, are permitted provided that the following conditions
     10      1.1  cgd  * are met:
     11      1.1  cgd  * 1. Redistributions of source code must retain the above copyright
     12      1.1  cgd  *    notice, this list of conditions and the following disclaimer.
     13      1.1  cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14      1.1  cgd  *    notice, this list of conditions and the following disclaimer in the
     15      1.1  cgd  *    documentation and/or other materials provided with the distribution.
     16      1.1  cgd  * 3. All advertising materials mentioning features or use of this software
     17      1.1  cgd  *    must display the following acknowledgement:
     18      1.1  cgd  *	This product includes software developed by the University of
     19      1.1  cgd  *	California, Berkeley and its contributors.
     20      1.1  cgd  * 4. Neither the name of the University nor the names of its contributors
     21      1.1  cgd  *    may be used to endorse or promote products derived from this software
     22      1.1  cgd  *    without specific prior written permission.
     23      1.1  cgd  *
     24      1.1  cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25      1.1  cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26      1.1  cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27      1.1  cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28      1.1  cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29      1.1  cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30      1.1  cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31      1.1  cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32      1.1  cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33      1.1  cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34      1.1  cgd  * SUCH DAMAGE.
     35      1.1  cgd  *
     36      1.2  cgd  *	from: @(#)nfs_node.c	7.34 (Berkeley) 5/15/91
     37  1.2.2.1  cgd  *	$Id: nfs_node.c,v 1.2.2.1 1993/07/24 20:26:40 cgd Exp $
     38      1.1  cgd  */
     39      1.1  cgd 
     40      1.1  cgd #include "param.h"
     41      1.1  cgd #include "systm.h"
     42      1.1  cgd #include "proc.h"
     43      1.1  cgd #include "mount.h"
     44      1.1  cgd #include "namei.h"
     45      1.1  cgd #include "vnode.h"
     46      1.1  cgd #include "kernel.h"
     47      1.1  cgd #include "malloc.h"
     48      1.1  cgd 
     49      1.1  cgd #include "nfsv2.h"
     50      1.1  cgd #include "nfs.h"
     51      1.1  cgd #include "nfsnode.h"
     52      1.1  cgd #include "nfsmount.h"
     53      1.1  cgd 
     54      1.1  cgd /* The request list head */
     55      1.1  cgd extern struct nfsreq nfsreqh;
     56      1.1  cgd 
     57      1.1  cgd #define	NFSNOHSZ	512
     58      1.1  cgd #if	((NFSNOHSZ&(NFSNOHSZ-1)) == 0)
     59      1.1  cgd #define	NFSNOHASH(fhsum)	((fhsum)&(NFSNOHSZ-1))
     60      1.1  cgd #else
     61      1.1  cgd #define	NFSNOHASH(fhsum)	(((unsigned)(fhsum))%NFSNOHSZ)
     62      1.1  cgd #endif
     63      1.1  cgd 
     64      1.1  cgd union nhead {
     65      1.1  cgd 	union  nhead *nh_head[2];
     66      1.1  cgd 	struct nfsnode *nh_chain[2];
     67      1.1  cgd } nhead[NFSNOHSZ];
     68      1.1  cgd 
     69      1.1  cgd #define TRUE	1
     70      1.1  cgd #define	FALSE	0
     71      1.1  cgd 
     72      1.1  cgd /*
     73      1.1  cgd  * Initialize hash links for nfsnodes
     74      1.1  cgd  * and build nfsnode free list.
     75      1.1  cgd  */
     76      1.1  cgd nfs_nhinit()
     77      1.1  cgd {
     78      1.1  cgd 	register int i;
     79      1.1  cgd 	register union  nhead *nh = nhead;
     80      1.1  cgd 
     81      1.1  cgd #ifndef lint
     82      1.1  cgd 	if (VN_MAXPRIVATE < sizeof(struct nfsnode))
     83      1.1  cgd 		panic("nfs_nhinit: too small");
     84      1.1  cgd #endif /* not lint */
     85      1.1  cgd 	for (i = NFSNOHSZ; --i >= 0; nh++) {
     86      1.1  cgd 		nh->nh_head[0] = nh;
     87      1.1  cgd 		nh->nh_head[1] = nh;
     88      1.1  cgd 	}
     89      1.1  cgd }
     90      1.1  cgd 
     91      1.1  cgd /*
     92      1.1  cgd  * Compute an entry in the NFS hash table structure
     93      1.1  cgd  */
     94      1.1  cgd union nhead *
     95      1.1  cgd nfs_hash(fhp)
     96      1.1  cgd 	register nfsv2fh_t *fhp;
     97      1.1  cgd {
     98      1.1  cgd 	register u_char *fhpp;
     99      1.1  cgd 	register u_long fhsum;
    100      1.1  cgd 	int i;
    101      1.1  cgd 
    102      1.1  cgd 	fhpp = &fhp->fh_bytes[0];
    103      1.1  cgd 	fhsum = 0;
    104      1.1  cgd 	for (i = 0; i < NFSX_FH; i++)
    105      1.1  cgd 		fhsum += *fhpp++;
    106      1.1  cgd 	return (&nhead[NFSNOHASH(fhsum)]);
    107      1.1  cgd }
    108      1.1  cgd 
    109      1.1  cgd /*
    110      1.1  cgd  * Look up a vnode/nfsnode by file handle.
    111      1.1  cgd  * Callers must check for mount points!!
    112      1.1  cgd  * In all cases, a pointer to a
    113      1.1  cgd  * nfsnode structure is returned.
    114      1.1  cgd  */
    115      1.1  cgd nfs_nget(mntp, fhp, npp)
    116      1.1  cgd 	struct mount *mntp;
    117      1.1  cgd 	register nfsv2fh_t *fhp;
    118      1.1  cgd 	struct nfsnode **npp;
    119      1.1  cgd {
    120      1.1  cgd 	register struct nfsnode *np;
    121      1.1  cgd 	register struct vnode *vp;
    122      1.1  cgd 	extern struct vnodeops nfsv2_vnodeops;
    123      1.1  cgd 	struct vnode *nvp;
    124      1.1  cgd 	union nhead *nh;
    125      1.1  cgd 	int error;
    126      1.1  cgd 
    127      1.1  cgd 	nh = nfs_hash(fhp);
    128      1.1  cgd loop:
    129      1.1  cgd 	for (np = nh->nh_chain[0]; np != (struct nfsnode *)nh; np = np->n_forw) {
    130      1.1  cgd 		if (mntp != NFSTOV(np)->v_mount ||
    131      1.1  cgd 		    bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
    132      1.1  cgd 			continue;
    133      1.1  cgd 		if ((np->n_flag & NLOCKED) != 0) {
    134      1.1  cgd 			np->n_flag |= NWANT;
    135      1.1  cgd 			(void) tsleep((caddr_t)np, PINOD, "nfsnode", 0);
    136      1.1  cgd 			goto loop;
    137      1.1  cgd 		}
    138      1.1  cgd 		vp = NFSTOV(np);
    139      1.1  cgd 		if (vget(vp))
    140      1.1  cgd 			goto loop;
    141      1.1  cgd 		*npp = np;
    142      1.1  cgd 		return(0);
    143      1.1  cgd 	}
    144      1.1  cgd 	if (error = getnewvnode(VT_NFS, mntp, &nfsv2_vnodeops, &nvp)) {
    145      1.1  cgd 		*npp = 0;
    146      1.1  cgd 		return (error);
    147      1.1  cgd 	}
    148      1.1  cgd 	vp = nvp;
    149      1.1  cgd 	np = VTONFS(vp);
    150      1.1  cgd 	np->n_vnode = vp;
    151      1.1  cgd 	/*
    152      1.1  cgd 	 * Insert the nfsnode in the hash queue for its new file handle
    153      1.1  cgd 	 */
    154      1.1  cgd 	np->n_flag = 0;
    155      1.1  cgd 	insque(np, nh);
    156      1.1  cgd 	nfs_lock(vp);
    157      1.1  cgd 	bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
    158      1.1  cgd 	np->n_attrstamp = 0;
    159      1.1  cgd 	np->n_direofoffset = 0;
    160      1.1  cgd 	np->n_sillyrename = (struct sillyrename *)0;
    161      1.1  cgd 	np->n_size = 0;
    162      1.1  cgd 	np->n_mtime = 0;
    163  1.2.2.1  cgd 	np->n_lockf = 0;
    164      1.1  cgd 	*npp = np;
    165      1.1  cgd 	return (0);
    166      1.1  cgd }
    167      1.1  cgd 
    168      1.1  cgd nfs_inactive(vp, p)
    169      1.1  cgd 	struct vnode *vp;
    170      1.1  cgd 	struct proc *p;
    171      1.1  cgd {
    172      1.1  cgd 	register struct nfsnode *np;
    173      1.1  cgd 	register struct sillyrename *sp;
    174      1.1  cgd 	struct nfsnode *dnp;
    175      1.1  cgd 	extern int prtactive;
    176      1.1  cgd 
    177      1.1  cgd 	np = VTONFS(vp);
    178      1.1  cgd 	if (prtactive && vp->v_usecount != 0)
    179      1.1  cgd 		vprint("nfs_inactive: pushing active", vp);
    180      1.1  cgd 	nfs_lock(vp);
    181      1.1  cgd 	sp = np->n_sillyrename;
    182      1.1  cgd 	np->n_sillyrename = (struct sillyrename *)0;
    183      1.1  cgd 	if (sp) {
    184      1.1  cgd 		/*
    185      1.1  cgd 		 * Remove the silly file that was rename'd earlier
    186      1.1  cgd 		 */
    187      1.1  cgd 		if (!nfs_nget(vp->v_mount, &sp->s_fh, &dnp)) {
    188      1.1  cgd 			sp->s_dvp = NFSTOV(dnp);
    189      1.1  cgd 			nfs_removeit(sp, p);
    190      1.1  cgd 			nfs_nput(sp->s_dvp);
    191      1.1  cgd 		}
    192      1.1  cgd 		crfree(sp->s_cred);
    193      1.1  cgd 		vrele(sp->s_dvp);
    194      1.1  cgd 		free((caddr_t)sp, M_NFSREQ);
    195      1.1  cgd 	}
    196      1.1  cgd 	nfs_unlock(vp);
    197      1.1  cgd 	np->n_flag &= NMODIFIED;
    198      1.1  cgd #ifdef notdef
    199      1.1  cgd 	/*
    200      1.1  cgd 	 * Scan the request list for any requests left hanging about
    201      1.1  cgd 	 */
    202      1.1  cgd 	s = splnet();
    203      1.1  cgd 	rep = nfsreqh.r_next;
    204      1.1  cgd 	while (rep && rep != &nfsreqh) {
    205      1.1  cgd 		if (rep->r_vp == vp) {
    206      1.1  cgd 			rep->r_prev->r_next = rep2 = rep->r_next;
    207      1.1  cgd 			rep->r_next->r_prev = rep->r_prev;
    208      1.1  cgd 			m_freem(rep->r_mreq);
    209      1.1  cgd 			if (rep->r_mrep != NULL)
    210      1.1  cgd 				m_freem(rep->r_mrep);
    211      1.1  cgd 			free((caddr_t)rep, M_NFSREQ);
    212      1.1  cgd 			rep = rep2;
    213      1.1  cgd 		} else
    214      1.1  cgd 			rep = rep->r_next;
    215      1.1  cgd 	}
    216      1.1  cgd 	splx(s);
    217      1.1  cgd #endif
    218      1.1  cgd 	return (0);
    219      1.1  cgd }
    220      1.1  cgd 
    221      1.1  cgd /*
    222      1.1  cgd  * Reclaim an nfsnode so that it can be used for other purposes.
    223      1.1  cgd  */
    224      1.1  cgd nfs_reclaim(vp)
    225      1.1  cgd 	register struct vnode *vp;
    226      1.1  cgd {
    227      1.1  cgd 	register struct nfsnode *np = VTONFS(vp);
    228      1.1  cgd 	extern int prtactive;
    229      1.1  cgd 
    230      1.1  cgd 	if (prtactive && vp->v_usecount != 0)
    231      1.1  cgd 		vprint("nfs_reclaim: pushing active", vp);
    232      1.1  cgd 	/*
    233      1.1  cgd 	 * Remove the nfsnode from its hash chain.
    234      1.1  cgd 	 */
    235      1.1  cgd 	remque(np);
    236      1.1  cgd 	np->n_forw = np;
    237      1.1  cgd 	np->n_back = np;
    238      1.1  cgd 	cache_purge(vp);
    239      1.1  cgd 	np->n_flag = 0;
    240      1.1  cgd 	np->n_direofoffset = 0;
    241      1.1  cgd 	return (0);
    242      1.1  cgd }
    243      1.1  cgd 
    244      1.1  cgd /*
    245      1.1  cgd  * In theory, NFS does not need locking, but we make provision
    246      1.1  cgd  * for doing it just in case it is needed.
    247      1.1  cgd  */
    248      1.1  cgd int donfslocking = 0;
    249      1.1  cgd /*
    250      1.1  cgd  * Lock an nfsnode
    251      1.1  cgd  */
    252      1.1  cgd 
    253      1.1  cgd nfs_lock(vp)
    254      1.1  cgd 	struct vnode *vp;
    255      1.1  cgd {
    256      1.1  cgd 	register struct nfsnode *np = VTONFS(vp);
    257      1.1  cgd 
    258      1.1  cgd 	if (!donfslocking)
    259      1.1  cgd 		return;
    260      1.1  cgd 	while (np->n_flag & NLOCKED) {
    261      1.1  cgd 		np->n_flag |= NWANT;
    262      1.1  cgd 		if (np->n_lockholder == curproc->p_pid)
    263      1.1  cgd 			panic("locking against myself");
    264      1.1  cgd 		np->n_lockwaiter = curproc->p_pid;
    265      1.1  cgd 		(void) tsleep((caddr_t)np, PINOD, "nfslock", 0);
    266      1.1  cgd 	}
    267      1.1  cgd 	np->n_lockwaiter = 0;
    268      1.1  cgd 	np->n_lockholder = curproc->p_pid;
    269      1.1  cgd 	np->n_flag |= NLOCKED;
    270      1.1  cgd }
    271      1.1  cgd 
    272      1.1  cgd /*
    273      1.1  cgd  * Unlock an nfsnode
    274      1.1  cgd  */
    275      1.1  cgd nfs_unlock(vp)
    276      1.1  cgd 	struct vnode *vp;
    277      1.1  cgd {
    278      1.1  cgd 	register struct nfsnode *np = VTONFS(vp);
    279      1.1  cgd 
    280      1.1  cgd 	np->n_lockholder = 0;
    281      1.1  cgd 	np->n_flag &= ~NLOCKED;
    282      1.1  cgd 	if (np->n_flag & NWANT) {
    283      1.1  cgd 		np->n_flag &= ~NWANT;
    284      1.1  cgd 		wakeup((caddr_t)np);
    285      1.1  cgd 	}
    286      1.1  cgd }
    287      1.1  cgd 
    288      1.1  cgd /*
    289      1.1  cgd  * Check for a locked nfsnode
    290      1.1  cgd  */
    291      1.1  cgd nfs_islocked(vp)
    292      1.1  cgd 	struct vnode *vp;
    293      1.1  cgd {
    294      1.1  cgd 
    295      1.1  cgd 	if (VTONFS(vp)->n_flag & NLOCKED)
    296      1.1  cgd 		return (1);
    297      1.1  cgd 	return (0);
    298      1.1  cgd }
    299      1.1  cgd 
    300      1.1  cgd /*
    301      1.1  cgd  * Unlock and vrele()
    302      1.1  cgd  * since I can't decide if dirs. should be locked, I will check for
    303      1.1  cgd  * the lock and be flexible
    304      1.1  cgd  */
    305      1.1  cgd nfs_nput(vp)
    306      1.1  cgd 	struct vnode *vp;
    307      1.1  cgd {
    308      1.1  cgd 	register struct nfsnode *np = VTONFS(vp);
    309      1.1  cgd 
    310      1.1  cgd 	if (np->n_flag & NLOCKED)
    311      1.1  cgd 		nfs_unlock(vp);
    312      1.1  cgd 	vrele(vp);
    313      1.1  cgd }
    314      1.1  cgd 
    315      1.1  cgd /*
    316      1.1  cgd  * Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
    317      1.1  cgd  * done. Currently nothing to do.
    318      1.1  cgd  */
    319      1.1  cgd /* ARGSUSED */
    320      1.1  cgd nfs_abortop(ndp)
    321      1.1  cgd 	struct nameidata *ndp;
    322      1.1  cgd {
    323      1.1  cgd 
    324      1.1  cgd 	if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
    325      1.1  cgd 		FREE(ndp->ni_pnbuf, M_NAMEI);
    326      1.1  cgd 	return (0);
    327      1.1  cgd }
    328