⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfs_vnodeops.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
			vp->g_size = vap->va_size;		}		vattr_to_sattr(vap, &args.saa_sa);		args.saa_fh = *vtofh(vp);		error = rfscall(vtomi(vp), RFS_SETATTR, xdr_saargs,				(caddr_t)&args, xdr_attrstat,				(caddr_t)ns, cred);		if (!error) {			error = geterrno(ns->ns_status);			if (!error) {				nfs_attrcache(vp, &ns->ns_attr, SFLUSH);			}			else {				check_stale_fh(error, vp);			}		}	}	kmem_free(ns, KM_NFS);	return (error);}intnfs_readlink(vp, uiop, cred)	struct vnode *vp;	struct uio *uiop;	struct ucred *cred;{	int error;	struct nfsrdlnres rl;	if(vp->v_type != VLNK)		return (ENXIO);	kmem_alloc(rl.rl_data, char *, (u_int)NFS_MAXPATHLEN, KM_NFS);	error =	    rfscall(vtomi(vp), RFS_READLINK, xdr_fhandle, (caddr_t)vtofh(vp),		    xdr_rdlnres, (caddr_t)&rl, cred);	if (!error) {		error = geterrno(rl.rl_status);		if (!error) {			error = uiomove(rl.rl_data, (int)rl.rl_count,			    UIO_READ, uiop);		}		else {			check_stale_fh(error, vp);		}	}	kmem_free(rl.rl_data, KM_NFS);	return (error);}int nfs_fsync_size = 16;intnfs_fsync(vp)	struct vnode *vp;{	register struct rnode *rp = vtor(vp);	register int offset, blksize;	register long lastlbn;	struct nfsattrstat *ns;	int error;	int need_lock = 0;	/* Do nothing if the file is not dirty */	if (rp->r_flags & RDIRTY) {		/* First off, synchronize processes by locking vp */		if (glocked((struct gnode *)vp) != LK_TRUE) {			need_lock = 1;			gfs_lock((struct gnode *)vp);		}		if (!(rp->r_flags & RDIRTY)) {			/* someone beat us to it */			if (need_lock) {				gfs_unlock((struct gnode *)vp);			} else {				panic("nfs_fsync: lost RDIRTY");			}			return (rp->r_error);		}		/*		 * Now that we have the gnode locked, we can reset the		 * RDIRTY flag when we are done since no		 * writes can occur "behind" us while we are flushing.		 *		 * This flag is used by nfs_attrcache() to determine if the		 * delayed write block completions that we are flushing		 * are allowed to update the g_size field with the server's		 * notion of file size.		 *		 * If we reset the flag before we are done, there may be an		 * orphaned delayed write block at the end of the file		 * (the loop terminates early because the g_size field		 * is down-sized). If this happens, then the next sync()		 * may get left holding the bag with a buffer for a gnode		 * that has been inactive'd.		 */		blksize = vtoblksz(vp);		lastlbn = howmany((unsigned long)vp->g_size,				  (unsigned long)blksize);		if (lastlbn < nfs_fsync_size) {			/* small file - synchronous writes */			error = u.u_error; /* save state */			for (offset = 0; offset < vp->g_size;			     offset += blksize)				{					blkflush(vp->g_dev,						 (daddr_t)(offset/DEV_BSIZE),						 (long)blksize, vp);				}			/*			 * If there were writes performed above by blkflush()			 * they were synchronous, and geterror() posted any			 * error directly into u.u_error. To make this			 * policy work like the one below, remove any			 * change to u.u_error caused by us.			 */			if (u.u_error) {				rp->r_error = u.u_error;				if (!error)					u.u_error = 0;			}		}		else {			/* large file - asynchronous writes */			bflush(NODEV, vp, 1); /* sync delayed writes */			/*			 * If there were writes performed above by bflush()			 * they were asynchronous, and nfswrite() posted			 * any error in rp->r_error. If an asynch write error			 * occurred prior to this routine being called			 * (or during the call), then all remaing dirty			 * buffers are "tossed" in nfs_strategy() or			 * nfswrite().			 */		}		/*		 * NB: Note that the file has been flushed.		 * All writes to this file, including writes handed off		 * to biods prior to or during this invocation,		 * have been accounted for.		 * Since the biods would pile up sleeping on gp		 * (in nfs_attrcache()) until we unlock it, nfswrite()		 * doesn't call nfs_attrcache() for async writes.		 * Thus, we are not put in a race with nfs_attrcache()		 * which could result in confused file attributes		 * (most probably size).		 *		 * We ensure that when this call completes		 * the file attributes are up to date with any		 * writes that we have pushed out. We go directly to the		 * wire (holding gp locked) to get current ones.		 */		kmem_alloc(ns, struct nfsattrstat *, (u_int)sizeof(*ns),			   KM_NFS);		error = rfscall(vtomi(vp), RFS_GETATTR, xdr_fhandle,				(caddr_t)vtofh(vp), xdr_attrstat, (caddr_t)ns,				u.u_cred);		if (!error) {			error = geterrno(ns->ns_status);			if (!error) {				nfs_attrcache(vp, &ns->ns_attr, NOFLUSH);			}			else {				check_stale_fh(error, vp);			}		}		kmem_free(ns, KM_NFS);		rp->r_flags &= ~RDIRTY; /* open the gate in nfs_attrcache() */		if (need_lock)			gfs_unlock((struct gnode *)vp);	}	return (rp->r_error);}/* * Make an NFS gnode inactive. * Weirdness: if the file was removed while it was open it got * renamed (by nfs_remove) instead.  Here we remove the renamed * file.  Note: the gnode must be in a consistent state when this * routine is called, since we may block in rfscall. *//*ARGSUSED*/intnfs_inactive(vp, cred)	struct vnode *vp;	struct ucred *cred;{	register struct rnode *rp = vtor(vp);	int error;	struct nfsdiropargs da;	enum nfsstat status;	if (rp->r_unlname != NULL) {		setdiropargs(&da, rp->r_unlname, rp->r_unldvp);		error = rfscall(vtomi(rp->r_unldvp), RFS_REMOVE,		    xdr_diropargs, (caddr_t)&da,		    xdr_enum, (caddr_t)&status, rp->r_unlcred);		if (!error) {			error = geterrno(status);		}		VN_RELE(rp->r_unldvp);		kmem_free((caddr_t)rp->r_unlname, KM_NFS);		crfree(rp->r_unlcred);		rp->r_unldvp = NULL;		rp->r_unlname = NULL;		rp->r_unlcred = NULL;	}	if (rp->r_cred) {		crfree(rp->r_cred);		rp->r_cred = NULL;	}	return (0);}/* * Remote file system operations having to do with directory manipulation. */intnfs_lookup(dvp, nm, vpp, cred)	struct vnode *dvp;	char *nm;	struct vnode **vpp;	struct ucred *cred;{	int error;	struct nfsdiropargs da;	struct nfsdiropres *dr;	/*	 * Before checking dnlc, call getattr to be	 * sure directory hasn't changed.  getattr	 * will purge dnlc if a change has occurred.	 */	if (error = nfs_getattr(dvp, cred)) {		*vpp = (struct vnode *)0;		return (error);	}	*vpp = (struct vnode *) dnlc_lookup(dvp, nm, cred);	if (*vpp) {		nfs_lock(dvp);	/* synchronize with any other process */		                /* that has vp locked before the check, */		                /* where it may be temporarily unlocked */		if (access(dvp, GEXEC)) { /* must be able to scan the dir */			nfs_unlock(dvp);			return (u.u_error);		}		nfs_unlock(dvp);		return (0);	}	kmem_alloc(dr, struct nfsdiropres *, (u_int)sizeof(*dr), KM_NFS);	setdiropargs(&da, nm, dvp);	error = rfscall(vtomi(dvp), RFS_LOOKUP, xdr_diropargs, (caddr_t)&da,			xdr_diropres, (caddr_t)dr, cred);	if (!error) {		error = geterrno(dr->dr_status);		check_stale_fh(error, dvp);	}		if (!error) {		*vpp = makenfsnode(&dr->dr_fhandle, &dr->dr_attr, dvp->v_vfsp,				   ((struct gnode *) dvp)->g_mp);		if(*vpp == NULL)			error = u.u_error;		else if (nfs_dnlc)			dnlc_enter(dvp, nm, *vpp, cred);	} else {		*vpp = (struct vnode *)0;	}	kmem_free(dr, KM_NFS);	return (error);}/*ARGSUSED*/intnfs_create(dvp, nm, va, exclusive, vpp, cred)	struct vnode *dvp;	char *nm;	struct vattr *va;	enum vcexcl exclusive;	struct vnode **vpp;	struct ucred *cred;{	int error;	struct nfscreatargs args;	struct  nfsdiropres *dr;	if (exclusive == EXCL) {		/*		 * This is buggy: there is a race between the lookup and the		 * create.  We should send the exclusive flag over the wire.		 */		error = nfs_lookup(dvp, nm, vpp, cred);		if (error != ENOENT) { 			if (*vpp)				VN_RELE(*vpp);			return (error ? error : EEXIST);		}			}	*vpp = (struct vnode *)0;	kmem_alloc(dr, struct nfsdiropres *, (u_int)sizeof(*dr), KM_NFS);	setdiropargs(&args.ca_da, nm, dvp);         /*         * This is a completely gross hack to make mknod         * work over the wire until we can wack the protocol         */#define IFCHR           0020000         /* character special */#define IFBLK           0060000         /* block special */#define IFSOCK          0140000         /* socket */        if (va->va_type == VCHR) {                va->va_mode |= IFCHR;                va->va_size = (u_long)va->va_rdev;        } else if (va->va_type == VBLK) {                va->va_mode |= IFBLK;                va->va_size = (u_long)va->va_rdev;        } else if (va->va_type == VFIFO) {		/* xtra kludge for namedpipe */                va->va_mode = (va->va_mode & ~GFMT) | IFCHR;                va->va_size = (u_long)NFS_FIFO_DEV;     /* blech */        } else if (va->va_type == VSOCK) {                va->va_mode |= IFSOCK;        }	vattr_to_sattr(va, &args.ca_sa);	dnlc_remove(dvp, nm);	error = rfscall(vtomi(dvp), RFS_CREATE, xdr_creatargs, (caddr_t)&args,			xdr_diropres, (caddr_t)dr, cred);	nfsattr_inval(dvp);	if (!error) {		error = geterrno(dr->dr_status);		if (error) {			check_stale_fh(error, dvp);		}		else {			*vpp = makenfsnode(&dr->dr_fhandle, &dr->dr_attr,					   dvp->v_vfsp,					   ((struct gnode *)dvp)->g_mp);			if (*vpp != NULL) {				((struct gnode *)*vpp)->g_size = 0;				if (nfs_dnlc) {					dnlc_enter(dvp, nm, *vpp, cred);				}			} else				error = u.u_error;		}	}	kmem_free(dr, KM_NFS);	return (error);}/* * Weirdness: if the vnode to be removed is open * we rename it instead of removing it and nfs_inactive * will remove the new name. */intnfs_remove(dvp, vp, nm, cred)	struct vnode *dvp;	struct vnode *vp;	char *nm;	struct ucred *cred;{	register struct rnode *rp = vtor(vp);	int error;	struct nfsdiropargs da;	enum nfsstat status;	char *tmpname;	status = NFS_OK;	/*	 * We need to flush the name cache so we can	 * check the real reference count on the vnode	 */	dnlc_purge_vp(vp);	if (((struct gnode *)vp)->g_count > 1 && rp->r_unlname == NULL) {		tmpname = newname(nm);		error = nfs_rename(dvp, nm, dvp, tmpname, cred);		if (error) {			kmem_free(tmpname, KM_NFS);		} else {			VN_HOLD(dvp);			rp->r_unldvp = dvp;			rp->r_unlname = tmpname;			if (rp->r_unlcred != NULL) {				crfree(rp->r_unlcred);			}			crhold(cred);			rp->r_unlcred = cred;		}	} else {		setdiropargs(&da, nm, dvp);		error = rfscall(vtomi(dvp), RFS_REMOVE, xdr_diropargs,				(caddr_t)&da, xdr_enum, (caddr_t)&status,				cred);		nfsattr_inval(dvp);	/* mod time changed */		nfsattr_inval(vp);	/* link count changed */		check_stale_fh(error ? error : geterrno(error), dvp);	}	if (!error) {		error = geterrno(status);	}	return (error);}intnfs_link(vp, tdvp, tnm, cred)	struct vnode *vp;	struct vnode *tdvp;	char *tnm;	struct ucred *cred;{	int error;	struct nfslinkargs args;	enum nfsstat status;	args.la_from = *vtofh(vp);	setdiropargs(&args.la_to, tnm, tdvp);	error = rfscall(vtomi(vp), RFS_LINK, xdr_linkargs, (caddr_t)&args,			xdr_enum, (caddr_t)&status, cred);	nfsattr_inval(tdvp);	/* mod time changed */	nfsattr_inval(vp);	/* link count changed */	if (!error) {		error = geterrno(status);		check_stale_fh(error, vp);		check_stale_fh(error, tdvp);	}	return (error);}intnfs_rename(odvp, onm, ndvp, nnm, cred)	struct vnode *odvp;	char *onm;	struct vnode *ndvp;	char *nnm;	struct ucred *cred;{	int error;	enum nfsstat status;	struct nfsrnmargs args;	if (!bcmp(onm, ".", 2) || !bcmp(onm, "..", 3) 		|| !bcmp(nnm, ".", 3) || !bcmp(nnm, "..", 3)) {		error = EINVAL;	} else {		dnlc_remove(odvp, onm);		dnlc_remove(ndvp, nnm);		setdiropargs(&args.rna_from, onm, odvp);		setdiropargs(&args.rna_to, nnm, ndvp);		error = rfscall(vtomi(odvp), RFS_RENAME, xdr_rnmargs,				(caddr_t)&args, xdr_enum, (caddr_t)&status,				cred);		nfsattr_inval(odvp);	/* mod time changed */		nfsattr_inval(ndvp);	/* mod time changed */		if (!error) {			error = geterrno(status);			check_stale_fh(error, odvp);			check_stale_fh(error, ndvp);		}	}	return (error);}intnfs_mkdir(dvp, nm, va, vpp, cred)	struct vnode *dvp;	char *nm;	register struct vattr *va;	struct vnode **vpp;	struct ucred *cred;{	int error;	struct nfscreatargs args;	struct  nfsdiropres *dr;	kmem_alloc(dr, struct nfsdiropres *, (u_int)sizeof(*dr), KM_NFS);	setdiropargs(&args.ca_da, nm, dvp);	vattr_to_sattr(va, &args.ca_sa);	dnlc_remove(dvp, nm);	error = rfscall(vtomi(dvp), RFS_MKDIR, xdr_creatargs, (caddr_t)&args,			xdr_diropres, (caddr_t)dr, cred);	nfsattr_inval(dvp);	/* mod time changed */	if (!error) {		error = geterrno(dr->dr_status);		check_stale_fh(error, dvp);	}	if (!error) {		/*		 * Due to a 4.0 reference port fiasco, the attributes that		 * come back on a mkdir may not be correct. Use them only		 * to set the vnode type in makenfsnode, then invalidate them.		 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -