Beispiel #1
0
/*
 * If a hold on the specified VFS has already been taken
 * then only increment the reference count of the corresponding
 * smb_vfs_t structure. If no smb_vfs_t structure has been created
 * yet for the specified VFS then create one and take a hold on
 * the VFS.
 */
int
smb_vfs_hold(smb_export_t *se, vfs_t *vfsp)
{
	smb_vfs_t	*smb_vfs;
	vnode_t 	*rootvp;
	int		rc;

	if (se == NULL || vfsp == NULL)
		return (EINVAL);

	smb_llist_enter(&se->e_vfs_list, RW_WRITER);

	if ((smb_vfs = smb_vfs_find(se, vfsp)) != NULL) {
		smb_vfs->sv_refcnt++;
		DTRACE_PROBE1(smb_vfs_hold_hit, smb_vfs_t *, smb_vfs);
		smb_llist_exit(&se->e_vfs_list);
		return (0);
	}

	if ((rc = VFS_ROOT(vfsp, &rootvp)) != 0) {
		smb_llist_exit(&se->e_vfs_list);
		return (rc);
	}

	smb_vfs = kmem_cache_alloc(smb_kshare_cache_vfs, KM_SLEEP);

	bzero(smb_vfs, sizeof (smb_vfs_t));

	smb_vfs->sv_magic = SMB_VFS_MAGIC;
	smb_vfs->sv_refcnt = 1;
	smb_vfs->sv_vfsp = vfsp;
	/*
	 * We have a hold on the root vnode of the file system
	 * from the VFS_ROOT call above.
	 */
	smb_vfs->sv_rootvp = rootvp;

	smb_llist_insert_head(&se->e_vfs_list, smb_vfs);
	DTRACE_PROBE1(smb_vfs_hold_miss, smb_vfs_t *, smb_vfs);
	smb_llist_exit(&se->e_vfs_list);

	return (0);
}
/*
 * Allocate a tree.
 */
static smb_tree_t *
smb_tree_alloc(
    smb_user_t		*user,
    const smb_share_t	*si,
    int32_t		stype,
    smb_node_t		*snode,
    uint32_t access)
{
	smb_tree_t	*tree;
	uint16_t	tid;

	if (smb_idpool_alloc(&user->u_tid_pool, &tid))
		return (NULL);

	tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP);
	bzero(tree, sizeof (smb_tree_t));

	if (STYPE_ISDSK(stype)) {
		if (smb_tree_getattr(si, snode, tree) != 0) {
			smb_idpool_free(&user->u_tid_pool, tid);
			kmem_cache_free(user->u_server->si_cache_tree, tree);
			return (NULL);
		}
	}

	if (smb_idpool_constructor(&tree->t_fid_pool)) {
		smb_idpool_free(&user->u_tid_pool, tid);
		kmem_cache_free(user->u_server->si_cache_tree, tree);
		return (NULL);
	}

	if (smb_idpool_constructor(&tree->t_odid_pool)) {
		smb_idpool_destructor(&tree->t_fid_pool);
		smb_idpool_free(&user->u_tid_pool, tid);
		kmem_cache_free(user->u_server->si_cache_tree, tree);
		return (NULL);
	}

	smb_llist_constructor(&tree->t_ofile_list, sizeof (smb_ofile_t),
	    offsetof(smb_ofile_t, f_lnd));

	smb_llist_constructor(&tree->t_odir_list, sizeof (smb_odir_t),
	    offsetof(smb_odir_t, d_lnd));

	(void) strlcpy(tree->t_sharename, si->shr_name,
	    sizeof (tree->t_sharename));
	(void) strlcpy(tree->t_resource, si->shr_path,
	    sizeof (tree->t_resource));

	mutex_init(&tree->t_mutex, NULL, MUTEX_DEFAULT, NULL);

	tree->t_user = user;
	tree->t_session = user->u_session;
	tree->t_server = user->u_server;
	tree->t_refcnt = 1;
	tree->t_tid = tid;
	tree->t_res_type = stype;
	tree->t_state = SMB_TREE_STATE_CONNECTED;
	tree->t_magic = SMB_TREE_MAGIC;
	tree->t_access = access;
	tree->t_connect_time = gethrestime_sec();

	/* if FS is readonly, enforce that here */
	if (tree->t_flags & SMB_TREE_READONLY)
		tree->t_access &= ~ACE_ALL_WRITE_PERMS;

	if (STYPE_ISDSK(stype)) {
		smb_node_ref(snode);
		tree->t_snode = snode;
		tree->t_acltype = smb_fsop_acltype(snode);
	}

	smb_llist_enter(&user->u_tree_list, RW_WRITER);
	smb_llist_insert_head(&user->u_tree_list, tree);
	smb_llist_exit(&user->u_tree_list);
	atomic_inc_32(&user->u_session->s_tree_cnt);
	atomic_inc_32(&user->u_server->sv_open_trees);

	return (tree);
}