Пример #1
0
/*
 * Add a ref to an active vnode.  This function should never be called
 * with an inactive vnode (use vget() instead), but might be called
 * with other states.
 */
void
vref(struct vnode *vp)
{
	KASSERT((VREFCNT(vp) > 0 && vp->v_state != VS_INACTIVE),
		("vref: bad refcnt %08x %d", vp->v_refcnt, vp->v_state));
	atomic_add_int(&vp->v_refcnt, 1);
}
Пример #2
0
/*
 * Reclaim an inode so that it can be used for other purposes.
 *
 * ufs_reclaim(struct vnode *a_vp)
 */
int
ufs_reclaim(struct vop_reclaim_args *ap)
{
	struct inode *ip;
	struct vnode *vp = ap->a_vp;
	struct ufsmount *ump;
#ifdef QUOTA
	int i;
#endif

	ump = VFSTOUFS(vp->v_mount);

	if (prtactive && VREFCNT(vp) > 1)
		vprint("ufs_reclaim: pushing active", vp);
	ip = VTOI(vp);

	/*
	 * Lazy updates.
	 */
	if (ip) {
		if (ip->i_flag & IN_LAZYMOD) {
			ip->i_flag |= IN_MODIFIED;
			ffs_update(vp, 0);
		}
	}
#ifdef INVARIANTS
	if (ip && (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE))) {
		kprintf("WARNING: INODE %ld flags %08x: modified inode being released!\n", (long)ip->i_number, (int)ip->i_flag);
		ip->i_flag |= IN_MODIFIED;
		ffs_update(vp, 0);
	}
#endif
	/*
	 * Remove the inode from its hash chain and purge namecache
	 * data associated with the vnode.
	 */
	vp->v_data = NULL;
	if (ip) {
		ufs_ihashrem(ump, ip);
		if (ip->i_devvp) {
			vrele(ip->i_devvp);
			ip->i_devvp = 0;
		}
#ifdef QUOTA
		for (i = 0; i < MAXQUOTAS; i++) {
			if (ip->i_dquot[i] != NODQUOT) {
				ufs_dqrele(vp, ip->i_dquot[i]);
				ip->i_dquot[i] = NODQUOT;
			}
		}
#endif
#ifdef UFS_DIRHASH
		if (ip->i_dirhash != NULL)
			ufsdirhash_free(ip);
#endif
		kfree(ip, VFSTOUFS(vp->v_mount)->um_malloctype);
	}
	return (0);
}
Пример #3
0
/*
 * Last reference to an inode.  If necessary, write or delete it.
 *
 * ufs_inactive(struct vnode *a_vp)
 */
int
ufs_inactive(struct vop_inactive_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct inode *ip = VTOI(vp);
	int mode, error = 0;

	if (prtactive && VREFCNT(vp) > 1)
		vprint("ufs_inactive: pushing active", vp);

	/*
	 * Ignore inodes related to stale file handles.
	 */
	if (ip == NULL || ip->i_mode == 0)
		goto out;
	if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
#ifdef QUOTA
		if (!ufs_getinoquota(ip))
			(void)ufs_chkiq(ip, -1, NOCRED, FORCE);
#endif
		/* Must have a VM object to truncate */
		error = ffs_truncate(vp, (off_t)0, 0, NOCRED);
		ip->i_rdev = 0;
		mode = ip->i_mode;
		ip->i_mode = 0;
		ip->i_flag |= IN_CHANGE | IN_UPDATE;
		ffs_vfree(vp, ip->i_number, mode);
	}
	if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE))
		ffs_update(vp, 0);
out:
	/*
	 * If we are done with the inode, reclaim it
	 * so that it can be reused immediately.
	 */
	if (ip == NULL || ip->i_mode == 0)
		vrecycle(vp);
	return (error);
}
Пример #4
0
/*
 * nwfs_remove call. It isn't possible to emulate UFS behaivour because
 * NetWare doesn't allow delete/rename operations on an opened file.
 *
 * nwfs_remove(struct vnode *a_dvp,
 *	       struct vnode *a_vp, struct componentname *a_cnp)
 */
static int
nwfs_remove(struct vop_old_remove_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct vnode *dvp = ap->a_dvp;
	struct componentname *cnp = ap->a_cnp;
	struct nwnode *np = VTONW(vp);
	struct nwmount *nmp = VTONWFS(vp);
	int error;

	if (vp->v_type == VDIR || np->opened || VREFCNT(vp) > 1) {
		error = EPERM;
	} else if (!ncp_conn_valid(NWFSTOCONN(nmp))) {
		error = EIO;
	} else {
		error = ncp_DeleteNSEntry(nmp, VTONW(dvp)->n_fid.f_id,
		    cnp->cn_namelen,cnp->cn_nameptr,cnp->cn_td,cnp->cn_cred);
		if (error == 0)
			np->n_flag |= NSHOULDFREE;
		else if (error == 0x899c)
			error = EACCES;
	}
	return (error);
}
Пример #5
0
/*
 * Last reference to an node.  If necessary, write or delete it.
 *
 * hpfs_inactive(struct vnode *a_vp)
 */
int
hpfs_inactive(struct vop_inactive_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct hpfsnode *hp = VTOHP(vp);
	int error;

	dprintf(("hpfs_inactive(0x%x): \n", hp->h_no));

	if (hp->h_flag & H_CHANGE) {
		dprintf(("hpfs_inactive: node changed, update\n"));
		error = hpfs_update (hp);
		if (error)
			return (error);
	}

	if (hp->h_flag & H_PARCHANGE) {
		dprintf(("hpfs_inactive: parent node changed, update\n"));
		error = hpfs_updateparent (hp);
		if (error)
			return (error);
	}

	if (prtactive && VREFCNT(vp) > 1)
		vprint("hpfs_inactive: pushing active", vp);

	if (hp->h_flag & H_INVAL) {
#if defined(__DragonFly__)
		vrecycle(vp);
#else /* defined(__NetBSD__) */
		vgone(vp);
#endif
		return (0);
	}
	return (0);
}
static int
ntfs_unmount(struct mount *mp, int mntflags)
{
	struct ntfsmount *ntmp;
	int error, ronly, flags, i;

	dprintf(("ntfs_unmount: unmounting...\n"));
	ntmp = VFSTONTFS(mp);

	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
	flags = 0;
	if(mntflags & MNT_FORCE)
		flags |= FORCECLOSE;

	dprintf(("ntfs_unmount: vflushing...\n"));
	error = vflush(mp, 0, flags | SKIPSYSTEM);
	if (error) {
		kprintf("ntfs_unmount: vflush failed: %d\n",error);
		return (error);
	}

	/* Check if only system vnodes are left */
	for(i=0;i<NTFS_SYSNODESNUM;i++)
		 if((ntmp->ntm_sysvn[i]) &&
		    (VREFCNT(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY);

	/* Dereference all system vnodes */
	for(i=0;i<NTFS_SYSNODESNUM;i++)
		 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);

	/* vflush system vnodes */
	error = vflush(mp, 0, flags);
	if (error)
		kprintf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);

	/* Check if the type of device node isn't VBAD before
	 * touching v_cdevinfo.  If the device vnode is revoked, the
	 * field is NULL and touching it causes null pointer derefercence.
	 */
	if (ntmp->ntm_devvp->v_type != VBAD)
		ntmp->ntm_devvp->v_rdev->si_mountpoint = NULL;

	vn_lock(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY);
	vinvalbuf(ntmp->ntm_devvp, V_SAVE, 0, 0);
	error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE, NULL);
	vn_unlock(ntmp->ntm_devvp);

	vrele(ntmp->ntm_devvp);

	/* free the toupper table, if this has been last mounted ntfs volume */
	ntfs_toupper_unuse();

	dprintf(("ntfs_umount: freeing memory...\n"));
	ntfs_u28_uninit(ntmp);
	ntfs_82u_uninit(ntmp);
	mp->mnt_data = (qaddr_t)0;
	mp->mnt_flag &= ~MNT_LOCAL;
	kfree(ntmp->ntm_ad, M_NTFSMNT);
	kfree(ntmp, M_NTFSMNT);
	return (error);
}
Пример #7
0
/*
 * nwfs_file rename call
 *
 * nwfs_rename(struct vnode *a_fdvp, struct vnode *a_fvp,
 *		struct componentname *a_fcnp, struct vnode *a_tdvp,
 *		struct vnode *a_tvp, struct componentname *a_tcnp)
 */
static int
nwfs_rename(struct vop_old_rename_args *ap)
{
	struct vnode *fvp = ap->a_fvp;
	struct vnode *tvp = ap->a_tvp;
	struct vnode *fdvp = ap->a_fdvp;
	struct vnode *tdvp = ap->a_tdvp;
	struct componentname *tcnp = ap->a_tcnp;
	struct componentname *fcnp = ap->a_fcnp;
	struct nwmount *nmp=VTONWFS(fvp);
	u_int16_t oldtype = 6;
	int error=0;

	/* Check for cross-device rename */
	if ((fvp->v_mount != tdvp->v_mount) ||
	    (tvp && (fvp->v_mount != tvp->v_mount))) {
		error = EXDEV;
		goto out;
	}

	if (tvp && VREFCNT(tvp) > 1) {
		error = EBUSY;
		goto out;
	}
	if (tvp && tvp != fvp) {
		error = ncp_DeleteNSEntry(nmp, VTONW(tdvp)->n_fid.f_id,
		    tcnp->cn_namelen, tcnp->cn_nameptr, 
		    tcnp->cn_td, tcnp->cn_cred);
		if (error == 0x899c) error = EACCES;
		if (error)
			goto out;
	}
	if (fvp->v_type == VDIR) {
		oldtype |= NW_TYPE_SUBDIR;
	} else if (fvp->v_type == VREG) {
		oldtype |= NW_TYPE_FILE;
	} else
		return EINVAL;
	error = ncp_nsrename(NWFSTOCONN(nmp), nmp->n_volume, nmp->name_space, 
		oldtype, &nmp->m.nls,
		VTONW(fdvp)->n_fid.f_id, fcnp->cn_nameptr, fcnp->cn_namelen,
		VTONW(tdvp)->n_fid.f_id, tcnp->cn_nameptr, tcnp->cn_namelen,
		tcnp->cn_td,tcnp->cn_cred);

	if (error == 0x8992)
		error = EEXIST;
out:
	if (tdvp == tvp)
		vrele(tdvp);
	else
		vput(tdvp);
	if (tvp)
		vput(tvp);
	vrele(fdvp);
	vrele(fvp);
	nwfs_attr_cacheremove(fdvp);
	nwfs_attr_cacheremove(tdvp);
	/*
	 * Need to get rid of old vnodes, because netware will change
	 * file id on rename
	 */
	vgone_vxlocked(fvp);
	if (tvp)
		vgone_vxlocked(tvp);
	/*
	 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
	 */
	if (error == ENOENT)
		error = 0;
	return (error);
}
/*
 * Allocate a VM object for a vnode, typically a regular file vnode.
 *
 * Some additional information is required to generate a properly sized
 * object which covers the entire buffer cache buffer straddling the file
 * EOF.  Userland does not see the extra pages as the VM fault code tests
 * against v_filesize.
 */
vm_object_t
vnode_pager_alloc(void *handle, off_t length, vm_prot_t prot, off_t offset,
		  int blksize, int boff)
{
	vm_object_t object;
	struct vnode *vp;
	off_t loffset;
	vm_pindex_t lsize;

	/*
	 * Pageout to vnode, no can do yet.
	 */
	if (handle == NULL)
		return (NULL);

	/*
	 * XXX hack - This initialization should be put somewhere else.
	 */
	if (vnode_pbuf_freecnt < 0) {
	    vnode_pbuf_freecnt = nswbuf / 2 + 1;
	}

	/*
	 * Serialize potential vnode/object teardowns and interlocks
	 */
	vp = (struct vnode *)handle;
	lwkt_gettoken(&vp->v_token);

	/*
	 * If the object is being terminated, wait for it to
	 * go away.
	 */
	object = vp->v_object;
	if (object) {
		vm_object_hold(object);
		KKASSERT((object->flags & OBJ_DEAD) == 0);
	}

	if (VREFCNT(vp) <= 0)
		panic("vnode_pager_alloc: no vnode reference");

	/*
	 * Round up to the *next* block, then destroy the buffers in question.
	 * Since we are only removing some of the buffers we must rely on the
	 * scan count to determine whether a loop is necessary.
	 *
	 * Destroy any pages beyond the last buffer.
	 */
	if (boff < 0)
		boff = (int)(length % blksize);
	if (boff)
		loffset = length + (blksize - boff);
	else
		loffset = length;
	lsize = OFF_TO_IDX(round_page64(loffset));

	if (object == NULL) {
		/*
		 * And an object of the appropriate size
		 */
		object = vm_object_allocate_hold(OBJT_VNODE, lsize);
		object->handle = handle;
		vp->v_object = object;
		vp->v_filesize = length;
		if (vp->v_mount && (vp->v_mount->mnt_kern_flag & MNTK_NOMSYNC))
			vm_object_set_flag(object, OBJ_NOMSYNC);
		vref(vp);
	} else {
		vm_object_reference_quick(object);	/* also vref's */
		if (object->size != lsize) {
			kprintf("vnode_pager_alloc: Warning, objsize "
				"mismatch %jd/%jd vp=%p obj=%p\n",
				(intmax_t)object->size,
				(intmax_t)lsize,
				vp, object);
		}
		if (vp->v_filesize != length) {
			kprintf("vnode_pager_alloc: Warning, filesize "
				"mismatch %jd/%jd vp=%p obj=%p\n",
				(intmax_t)vp->v_filesize,
				(intmax_t)length,
				vp, object);
		}
	}
	vm_object_drop(object);
	lwkt_reltoken(&vp->v_token);

	return (object);
}