/*
 * Deallocate a tree: release all resources associated with a tree and
 * remove the tree from the user's tree list.
 *
 * The tree being destroyed must be in the "destroying" state and the
 * reference count must be zero. This function assumes it's single threaded
 * i.e. only one thread will attempt to destroy a specific tree, which
 * should be the case if the tree is in disconnected and has a reference
 * count of zero.
 */
static void
smb_tree_dealloc(smb_tree_t *tree)
{
	ASSERT(tree);
	ASSERT(tree->t_magic == SMB_TREE_MAGIC);
	ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
	ASSERT(tree->t_refcnt == 0);

	/*
	 * Remove the tree from the user's tree list.  This must be done
	 * before any resources associated with the tree are released.
	 */
	smb_llist_enter(&tree->t_user->u_tree_list, RW_WRITER);
	smb_llist_remove(&tree->t_user->u_tree_list, tree);
	smb_llist_exit(&tree->t_user->u_tree_list);

	tree->t_magic = (uint32_t)~SMB_TREE_MAGIC;
	smb_idpool_free(&tree->t_user->u_tid_pool, tree->t_tid);
	atomic_dec_32(&tree->t_session->s_tree_cnt);

	if (tree->t_snode)
		smb_node_release(tree->t_snode);

	mutex_destroy(&tree->t_mutex);

	/*
	 * The list of open files and open directories should be empty.
	 */
	smb_llist_destructor(&tree->t_ofile_list);
	smb_llist_destructor(&tree->t_odir_list);
	smb_idpool_destructor(&tree->t_fid_pool);
	smb_idpool_destructor(&tree->t_odid_pool);
	kmem_cache_free(tree->t_server->si_cache_tree, tree);
}
Beispiel #2
0
/*
 * Delete an odir.
 *
 * Remove the odir from the tree list before freeing resources
 * associated with the odir.
 */
void
smb_odir_delete(void *arg)
{
	smb_tree_t	*tree;
	smb_odir_t	*od = (smb_odir_t *)arg;

	SMB_ODIR_VALID(od);
	ASSERT(od->d_refcnt == 0);
	ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED);

	tree = od->d_tree;
	smb_llist_enter(&tree->t_odir_list, RW_WRITER);
	smb_llist_remove(&tree->t_odir_list, od);
	smb_idpool_free(&tree->t_odid_pool, od->d_odid);
	atomic_dec_32(&tree->t_session->s_dir_cnt);
	smb_llist_exit(&tree->t_odir_list);

	mutex_enter(&od->d_mutex);
	mutex_exit(&od->d_mutex);

	od->d_magic = 0;
	smb_node_release(od->d_dnode);
	smb_user_release(od->d_user);
	mutex_destroy(&od->d_mutex);
	kmem_cache_free(smb_cache_odir, od);
}
Beispiel #3
0
/*
 * smb_vfs_rele_all()
 *
 * Release all holds on root vnodes of file systems which were taken
 * due to the existence of at least one enabled share on the file system.
 * Called at driver close time.
 */
void
smb_vfs_rele_all(smb_export_t *se)
{
	smb_vfs_t	*smb_vfs;

	smb_llist_enter(&se->e_vfs_list, RW_WRITER);
	while ((smb_vfs = smb_llist_head(&se->e_vfs_list)) != NULL) {

		ASSERT(smb_vfs->sv_magic == SMB_VFS_MAGIC);
		DTRACE_PROBE1(smb_vfs_rele_all_hit, smb_vfs_t *, smb_vfs);
		smb_llist_remove(&se->e_vfs_list, smb_vfs);
		smb_vfs_destroy(smb_vfs);
	}
	smb_llist_exit(&se->e_vfs_list);
}
/*
 * Delete an ofile.
 *
 * Remove the ofile from the tree list before freeing resources
 * associated with the ofile.
 */
void
smb_ofile_delete(void *arg)
{
	smb_tree_t	*tree;
	smb_ofile_t	*of = (smb_ofile_t *)arg;

	SMB_OFILE_VALID(of);
	ASSERT(of->f_refcnt == 0);
	ASSERT(of->f_state == SMB_OFILE_STATE_CLOSED);
	ASSERT(!SMB_OFILE_OPLOCK_GRANTED(of));

	tree = of->f_tree;
	smb_llist_enter(&tree->t_ofile_list, RW_WRITER);
	smb_llist_remove(&tree->t_ofile_list, of);
	smb_idpool_free(&tree->t_fid_pool, of->f_fid);
	atomic_dec_32(&tree->t_session->s_file_cnt);
	smb_llist_exit(&tree->t_ofile_list);

	mutex_enter(&of->f_mutex);
	mutex_exit(&of->f_mutex);

	switch (of->f_ftype) {
	case SMB_FTYPE_BYTE_PIPE:
	case SMB_FTYPE_MESG_PIPE:
		smb_opipe_dealloc(of->f_pipe);
		of->f_pipe = NULL;
		break;
	case SMB_FTYPE_DISK:
		if (of->f_odir != NULL)
			smb_odir_release(of->f_odir);
		smb_node_rem_ofile(of->f_node, of);
		smb_node_release(of->f_node);
		break;
	default:
		ASSERT(!"f_ftype");
		break;
	}

	of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
	mutex_destroy(&of->f_mutex);
	crfree(of->f_cr);
	smb_user_release(of->f_user);
	kmem_cache_free(smb_cache_ofile, of);
}
Beispiel #5
0
/*
 * smb_vfs_rele
 *
 * Decrements the reference count of the fs passed in. If the reference count
 * drops to zero the smb_vfs_t structure associated with the fs is freed.
 */
void
smb_vfs_rele(smb_export_t *se, vfs_t *vfsp)
{
	smb_vfs_t	*smb_vfs;

	ASSERT(vfsp);

	smb_llist_enter(&se->e_vfs_list, RW_WRITER);
	smb_vfs = smb_vfs_find(se, vfsp);
	DTRACE_PROBE1(smb_vfs_release, smb_vfs_t *, smb_vfs);
	if (smb_vfs) {
		ASSERT(smb_vfs->sv_refcnt);
		if (--smb_vfs->sv_refcnt == 0) {
			smb_llist_remove(&se->e_vfs_list, smb_vfs);
			smb_llist_exit(&se->e_vfs_list);
			smb_vfs_destroy(smb_vfs);
			return;
		}
	}
	smb_llist_exit(&se->e_vfs_list);
}