Beispiel #1
0
/* Unmount the filesystem described by mp. */
static int
smbfs_unmount(struct mount *mp, int mntflags)
{
	struct thread *td;
	struct smbmount *smp = VFSTOSMBFS(mp);
	struct smb_cred *scred;
	struct smb_dev *dev;
	int error, flags;

	SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
	td = curthread;
	flags = 0;
	if (mntflags & MNT_FORCE)
		flags |= FORCECLOSE;
	/*
	 * Keep trying to flush the vnode list for the mount while 
	 * some are still busy and we are making progress towards
	 * making them not busy. This is needed because smbfs vnodes
	 * reference their parent directory but may appear after their
	 * parent in the list; one pass over the vnode list is not
	 * sufficient in this case.
	 */
	do {
		smp->sm_didrele = 0;
		/* There is 1 extra root vnode reference from smbfs_mount(). */
		error = vflush(mp, 1, flags, td);
	} while (error == EBUSY && smp->sm_didrele != 0);
	if (error)
		return error;
	scred = smbfs_malloc_scred();
	smb_makescred(scred, td, td->td_ucred);
	error = smb_share_lock(smp->sm_share);
	if (error)
		goto out;
	smb_share_put(smp->sm_share, scred);
	SMB_LOCK();
	dev = smp->sm_dev;
	if (!dev)
		panic("No private data for mount point");
	sdp_trydestroy(dev);
	mp->mnt_data = NULL;
	SMB_UNLOCK();
	free(smp, M_SMBFSDATA);
	MNT_ILOCK(mp);
	mp->mnt_flag &= ~MNT_LOCAL;
	MNT_IUNLOCK(mp);
out:
	smbfs_free_scred(scred);
	return error;
}
Beispiel #2
0
/* Unmount the filesystem described by mp. */
int
smbfs_unmount(struct mount *mp, int mntflags)
{
	struct lwp *l = curlwp;
	struct smbmount *smp = VFSTOSMBFS(mp);
	struct smb_cred scred;
	struct vnode *smbfs_rootvp = SMBTOV(smp->sm_root);
	int error, flags;

	SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
	flags = 0;
	if (mntflags & MNT_FORCE)
		flags |= FORCECLOSE;

	if (smbfs_rootvp->v_usecount > 1 && (mntflags & MNT_FORCE) == 0)
		return EBUSY;

	/* Flush all vnodes.
	 * Keep trying to flush the vnode list for the mount while 
	 * some are still busy and we are making progress towards
	 * making them not busy. This is needed because smbfs vnodes
	 * reference their parent directory but may appear after their
	 * parent in the list; one pass over the vnode list is not
	 * sufficient in this case. */
	do {
		smp->sm_didrele = 0;
		error = vflush(mp, smbfs_rootvp, flags);
	} while (error == EBUSY && smp->sm_didrele != 0);
	if (error)
		return error;

	vgone(smbfs_rootvp);

	smb_makescred(&scred, l, l->l_cred);
	smb_share_lock(smp->sm_share);
	smb_share_put(smp->sm_share, &scred);
	mp->mnt_data = NULL;

	hashdone(smp->sm_hash, HASH_LIST, smp->sm_hashlen);
	mutex_destroy(&smp->sm_hashlock);
	free(smp, M_SMBFSDATA);
	return 0;
}
Beispiel #3
0
/* Unmount the filesystem described by mp. */
static int
smbfs_unmount(struct mount *mp, int mntflags)
{
	struct smbmount *smp = VFSTOSMBFS(mp);
	struct smb_cred scred;
	int error, flags;

	SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
	flags = 0;
	if (mntflags & MNT_FORCE)
		flags |= FORCECLOSE;
	/*
	 * Keep trying to flush the vnode list for the mount while 
	 * some are still busy and we are making progress towards
	 * making them not busy. This is needed because smbfs vnodes
	 * reference their parent directory but may appear after their
	 * parent in the list; one pass over the vnode list is not
	 * sufficient in this case.
	 */
	do {
		smp->sm_didrele = 0;
		/* There is 1 extra root vnode reference from smbfs_mount(). */
		error = vflush(mp, 1, flags);
	} while (error == EBUSY && smp->sm_didrele != 0);
	if (error)
		return error;
	smb_makescred(&scred, curthread, smp->sm_cred);
	error = smb_share_lock(smp->sm_share, LK_EXCLUSIVE);
	if (error)
		goto out;
	smb_share_put(smp->sm_share, &scred);
	mp->mnt_data = (qaddr_t)0;

	if (smp->sm_cred)
		crfree(smp->sm_cred);
	if (smp->sm_hash)
		hashdestroy(smp->sm_hash, M_SMBFSHASH, smp->sm_hashlen);
	lockdestroy(&smp->sm_hashlock);
	kfree(smp, M_SMBFSDATA);
	mp->mnt_flag &= ~MNT_LOCAL;
out:
	return error;
}
Beispiel #4
0
int
smbfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
{
	struct lwp *l = curlwp;
	struct smbfs_args *args = data; 	  /* holds data from mount request */
	struct smbmount *smp = NULL;
	struct smb_vc *vcp;
	struct smb_share *ssp = NULL;
	struct smb_cred scred;
	char *fromname;
	int error;

	if (*data_len < sizeof *args)
		return EINVAL;

	if (mp->mnt_flag & MNT_GETARGS) {
		smp = VFSTOSMBFS(mp);
		if (smp == NULL)
			return EIO;
		*args = smp->sm_args;
		*data_len = sizeof *args;
		return 0;
	}

	if (mp->mnt_flag & MNT_UPDATE)
		return EOPNOTSUPP;

	if (args->version != SMBFS_VERSION) {
		SMBVDEBUG("mount version mismatch: kernel=%d, mount=%d\n",
		    SMBFS_VERSION, args->version);
		return EINVAL;
	}

	smb_makescred(&scred, l, l->l_cred);
	error = smb_dev2share(args->dev_fd, SMBM_EXEC, &scred, &ssp);
	if (error)
		return error;
	smb_share_unlock(ssp);	/* keep ref, but unlock */
	vcp = SSTOVC(ssp);

	fromname = kmem_zalloc(MNAMELEN, KM_SLEEP);
	snprintf(fromname, MNAMELEN,
	    "//%s@%s/%s", vcp->vc_username, vcp->vc_srvname, ssp->ss_name);
	error = set_statvfs_info(path, UIO_USERSPACE, fromname, UIO_SYSSPACE,
	    mp->mnt_op->vfs_name, mp, l);
	kmem_free(fromname, MNAMELEN);
	if (error) {
		smb_share_lock(ssp);
		smb_share_put(ssp, &scred);
		return error;
	}

	mp->mnt_stat.f_iosize = vcp->vc_txmax;
	mp->mnt_stat.f_namemax =
	    (vcp->vc_hflags2 & SMB_FLAGS2_KNOWS_LONG_NAMES) ? 255 : 12;

	smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK|M_ZERO);
	mp->mnt_data = smp;

	smp->sm_hash = hashinit(desiredvnodes, HASH_LIST, true,
	    &smp->sm_hashlen);

	mutex_init(&smp->sm_hashlock, MUTEX_DEFAULT, IPL_NONE);
	smp->sm_share = ssp;
	smp->sm_root = NULL;
	smp->sm_args = *args;
	smp->sm_caseopt = args->caseopt;
	smp->sm_args.file_mode = (smp->sm_args.file_mode &
			    (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
	smp->sm_args.dir_mode  = (smp->sm_args.dir_mode &
			    (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;

	vfs_getnewfsid(mp);
	return (0);
}