示例#1
0
/*
 * Close a file or directory
 */
static int
pfs_close(struct vop_close_args *va)
{
	struct vnode *vn = va->a_vp;
	struct pfs_vdata *pvd = vn->v_data;
	struct pfs_node *pn = pvd->pvd_pn;
	struct proc *proc;
	int error;

	PFS_TRACE(("%s", pn->pn_name));
	pfs_assert_not_owned(pn);

	/*
	 * Do nothing unless this is the last close and the node has a
	 * last-close handler.
	 */
	if (vrefcnt(vn) > 1 || pn->pn_close == NULL)
		PFS_RETURN (0);

	if (pvd->pvd_pid != NO_PID) {
		proc = pfind(pvd->pvd_pid);
	} else {
		proc = NULL;
	}

	error = pn_close(va->a_td, proc, pn);

	if (proc != NULL)
		PROC_UNLOCK(proc);

	PFS_RETURN (error);
}
示例#2
0
static __inline
struct vnode *
union_lock_upper(struct union_node *un, struct thread *td)
{
	struct vnode *uppervp;

	if ((uppervp = un->un_uppervp) != NULL) {
		VREF(uppervp);
		vn_lock(uppervp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
	}
	KASSERT((uppervp == NULL || vrefcnt(uppervp) > 0), ("uppervp usecount is 0"));
	return(uppervp);
}
int
msdosfs_inactive(struct vop_inactive_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct denode *dep = VTODE(vp);
	int error = 0;

#ifdef MSDOSFS_DEBUG
	printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]);
#endif

	/*
	 * Ignore denodes related to stale file handles.
	 */
	if (dep->de_Name[0] == SLOT_DELETED || dep->de_Name[0] == SLOT_EMPTY)
		goto out;

	/*
	 * If the file has been deleted and it is on a read/write
	 * filesystem, then truncate the file, and mark the directory slot
	 * as empty.  (This may not be necessary for the dos filesystem.)
	 */
#ifdef MSDOSFS_DEBUG
	printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %llx, MNT_RDONLY %llx\n",
	    dep, dep->de_refcnt, (unsigned long long)vp->v_mount->mnt_flag,
	    (unsigned long long)MNT_RDONLY);
#endif
	if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
		error = detrunc(dep, (u_long) 0, 0, NOCRED);
		dep->de_flag |= DE_UPDATE;
		dep->de_Name[0] = SLOT_DELETED;
	}
	deupdat(dep, 0);

out:
	/*
	 * If we are done with the denode, reclaim it
	 * so that it can be reused immediately.
	 */
#ifdef MSDOSFS_DEBUG
	printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n",
	       vrefcnt(vp), dep->de_Name[0]);
#endif
	if (dep->de_Name[0] == SLOT_DELETED || dep->de_Name[0] == SLOT_EMPTY)
		vrecycle(vp);
	return (error);
}
示例#4
0
/*
 * Increasing refcount of lower vnode is needed at least for the case
 * when lower FS is NFS to do sillyrename if the file is in use.
 * Unfortunately v_usecount is incremented in many places in
 * the kernel and, as such, there may be races that result in
 * the NFS client doing an extraneous silly rename, but that seems
 * preferable to not doing a silly rename when it is needed.
 */
static int
null_remove(struct vop_remove_args *ap)
{
	int retval, vreleit;
	struct vnode *lvp;

	if (vrefcnt(ap->a_vp) > 1) {
		lvp = NULLVPTOLOWERVP(ap->a_vp);
		VREF(lvp);
		vreleit = 1;
	} else
		vreleit = 0;
	retval = null_bypass(&ap->a_gen);
	if (vreleit != 0)
		vrele(lvp);
	return (retval);
}
示例#5
0
int
nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) {
	struct nwnode *np;
	struct nwnode_hash_head *nhpp;
	struct vnode *vp;
	int i;

	if (nwfs_debuglevel == 0)
		return 0;
	printf("Name:uc:hc:fid:pfid\n");
	for(i = 0; i <= nwnodehash; i++) {
		nhpp = &nwhashtbl[i];
		LIST_FOREACH(np, nhpp, n_hash) {
			vp = NWTOV(np);
			vprint("", vp);
			printf("%s:%d:%d:%d:%d\n",np->n_name,vrefcnt(vp),
			    vp->v_holdcnt,np->n_fid.f_id, np->n_fid.f_parent);
		}
	}
示例#6
0
/*
 * Increasing refcount of lower vnode is needed at least for the case
 * when lower FS is NFS to do sillyrename if the file is in use.
 * Unfortunately v_usecount is incremented in many places in
 * the kernel and, as such, there may be races that result in
 * the NFS client doing an extraneous silly rename, but that seems
 * preferable to not doing a silly rename when it is needed.
 */
static int
crypto_remove(struct vop_remove_args *ap)
{
	int retval, vreleit;
	struct vnode *lvp, *vp;

	vp = ap->a_vp;
	if (vrefcnt(vp) > 1) {
		lvp = NULLVPTOLOWERVP(vp);
		VREF(lvp);
		vreleit = 1;
	} else
		vreleit = 0;
	VTONULL(vp)->crypto_flags |= NULLV_DROP;
	retval = crypto_bypass(&ap->a_gen);
	if (vreleit != 0)
		vrele(lvp);
	return (retval);
}
示例#7
0
static int
smbfs_mount(struct mount *mp)
{
	struct smbmount *smp = NULL;
	struct smb_vc *vcp;
	struct smb_share *ssp = NULL;
	struct vnode *vp;
	struct thread *td;
	struct smb_dev *dev;
	struct smb_cred *scred;
	int error, v;
	char *pc, *pe;

	dev = NULL;
	td = curthread;
	if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
		return EOPNOTSUPP;

	if (vfs_filteropt(mp->mnt_optnew, smbfs_opts)) {
		vfs_mount_error(mp, "%s", "Invalid option");
		return (EINVAL);
	}

	scred = smbfs_malloc_scred();
	smb_makescred(scred, td, td->td_ucred);
	
	/* Ask userspace of `fd`, the file descriptor of this session */
	if (1 != vfs_scanopt(mp->mnt_optnew, "fd", "%d", &v)) {
		vfs_mount_error(mp, "No fd option");
		smbfs_free_scred(scred);
		return (EINVAL);
	}
	error = smb_dev2share(v, SMBM_EXEC, scred, &ssp, &dev);
	smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK | M_ZERO);
	if (error) {
		printf("invalid device handle %d (%d)\n", v, error);
		vfs_mount_error(mp, "invalid device handle %d %d\n", v, error);
		smbfs_free_scred(scred);
		free(smp, M_SMBFSDATA);
		return error;
	}
	vcp = SSTOVC(ssp);
	smb_share_unlock(ssp);
	mp->mnt_stat.f_iosize = SSTOVC(ssp)->vc_txmax;
	mp->mnt_data = smp;
	smp->sm_share = ssp;
	smp->sm_root = NULL;
	smp->sm_dev = dev;
	if (1 != vfs_scanopt(mp->mnt_optnew,
	    "caseopt", "%d", &smp->sm_caseopt)) {
		vfs_mount_error(mp, "Invalid caseopt");
		error = EINVAL;
		goto bad;
	}
	if (1 != vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v)) {
		vfs_mount_error(mp, "Invalid uid");
		error = EINVAL;
		goto bad;
	}
	smp->sm_uid = v;

	if (1 != vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v)) {
		vfs_mount_error(mp, "Invalid gid");
		error = EINVAL;
		goto bad;
	}
	smp->sm_gid = v;

	if (1 != vfs_scanopt(mp->mnt_optnew, "file_mode", "%d", &v)) {
		vfs_mount_error(mp, "Invalid file_mode");
		error = EINVAL;
		goto bad;
	}
	smp->sm_file_mode = (v & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;

	if (1 != vfs_scanopt(mp->mnt_optnew, "dir_mode", "%d", &v)) {
		vfs_mount_error(mp, "Invalid dir_mode");
		error = EINVAL;
		goto bad;
	}
	smp->sm_dir_mode  = (v & (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;

	vfs_flagopt(mp->mnt_optnew,
	    "nolong", &smp->sm_flags, SMBFS_MOUNT_NO_LONG);

	pc = mp->mnt_stat.f_mntfromname;
	pe = pc + sizeof(mp->mnt_stat.f_mntfromname);
	bzero(pc, MNAMELEN);
	*pc++ = '/';
	*pc++ = '/';
	pc = strchr(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
	if (pc < pe-1) {
		*(pc++) = '@';
		pc = strchr(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
		if (pc < pe - 1) {
			*(pc++) = '/';
			strncpy(pc, ssp->ss_name, pe - pc - 2);
		}
	}
	vfs_getnewfsid(mp);
	error = smbfs_root(mp, LK_EXCLUSIVE, &vp);
	if (error) {
		vfs_mount_error(mp, "smbfs_root error: %d", error);
		goto bad;
	}
	VOP_UNLOCK(vp, 0);
	SMBVDEBUG("root.v_usecount = %d\n", vrefcnt(vp));

#ifdef DIAGNOSTIC
	SMBERROR("mp=%p\n", mp);
#endif
	smbfs_free_scred(scred);
	return error;
bad:
	if (ssp)
		smb_share_put(ssp, scred);
	smbfs_free_scred(scred);	
	SMB_LOCK();
	if (error && smp->sm_dev == dev) {
		smp->sm_dev = NULL;
		sdp_trydestroy(dev);
	}
	SMB_UNLOCK();
	free(smp, M_SMBFSDATA);
	return error;
}
示例#8
0
/*
 * mp - path - addr in user space of mount point (ie /usr or whatever)
 * data - addr in user space of mount params 
 */
static int nwfs_mount(struct mount *mp)
{
	struct nwfs_args args; 	  /* will hold data from mount request */
	int error;
	struct nwmount *nmp = NULL;
	struct ncp_conn *conn = NULL;
	struct ncp_handle *handle = NULL;
	struct vnode *vp;
	struct thread *td;
	char *pc,*pe;

	td = curthread;
	if (mp->mnt_flag & MNT_ROOTFS)
		return (EOPNOTSUPP);
	if (mp->mnt_flag & MNT_UPDATE) {
		nwfs_printf("MNT_UPDATE not implemented");
		return (EOPNOTSUPP);
	}
	error = vfs_copyopt(mp->mnt_optnew, "nwfs_args", &args, sizeof args);
	if (error)
		return (error);
	if (args.version != NWFS_VERSION) {
		nwfs_printf("mount version mismatch: kernel=%d, mount=%d\n",NWFS_VERSION,args.version);
		return (1);
	}
	error = ncp_conn_getbyref(args.connRef, td , td->td_ucred,NCPM_EXECUTE,&conn);
	if (error) {
		nwfs_printf("invalid connection refernce %d\n",args.connRef);
		return (error);
	}
	error = ncp_conn_gethandle(conn, NULL, &handle);
	if (error) {
		nwfs_printf("can't get connection handle\n");
		return (error);
	}
	ncp_conn_unlock(conn, td);	/* we keep the ref */
	mp->mnt_stat.f_iosize = conn->buffer_size;
        /* We must malloc our own mount info */
        nmp = malloc(sizeof(struct nwmount),M_NWFSDATA,
	    M_WAITOK | M_USE_RESERVE | M_ZERO);
        if (nmp == NULL) {
                nwfs_printf("could not alloc nwmount\n");
                error = ENOMEM;
		goto bad;
        }
        mp->mnt_data = nmp;
	nmp->connh = handle;
	nmp->n_root = NULL;
	nmp->n_id = nwfsid++;
        nmp->m = args;
	nmp->m.file_mode = (nmp->m.file_mode &
			    (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
	nmp->m.dir_mode  = (nmp->m.dir_mode &
			    (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
	if ((error = nwfs_initnls(nmp)) != 0) goto bad;
	pc = mp->mnt_stat.f_mntfromname;
	pe = pc+sizeof(mp->mnt_stat.f_mntfromname);
	bzero(pc, MNAMELEN);
	*(pc++) = '/';
	pc = index(strncpy(pc, conn->li.server, pe-pc-2),0);
	if (pc < pe-1) {
		*(pc++) = ':';
		pc=index(strncpy(pc, conn->li.user, pe-pc-2),0);
		if (pc < pe-1) {
			*(pc++) = '/';
			strncpy(pc, nmp->m.mounted_vol, pe-pc-2);
		}
	}
	/* protect against invalid mount points */
	nmp->m.mount_point[sizeof(nmp->m.mount_point)-1] = '\0';
	vfs_getnewfsid(mp);
	error = nwfs_root(mp, LK_EXCLUSIVE, &vp);
	if (error)
		goto bad;
	/*
	 * Lose the lock but keep the ref.
	 */
	VOP_UNLOCK(vp, 0);
	NCPVODEBUG("rootvp.vrefcnt=%d\n",vrefcnt(vp));
	return error;
bad:
        if (nmp)
		free(nmp, M_NWFSDATA);
	if (handle)
		ncp_conn_puthandle(handle, NULL, 0);
        return error;
}