summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs')
-rw-r--r--usr/src/uts/common/fs/lookup.c21
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv.c15
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c6
-rw-r--r--usr/src/uts/common/fs/proc/prcontrol.c4
-rw-r--r--usr/src/uts/common/fs/proc/prsubr.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_open.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_delete.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_dispatch.c22
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_find.c8
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_odir.c31
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_ofile.c108
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_opipe.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_process_exit.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_server.c103
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_session.c310
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_find.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c157
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree_connect.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_user.c370
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_dataset.c15
24 files changed, 651 insertions, 556 deletions
diff --git a/usr/src/uts/common/fs/lookup.c b/usr/src/uts/common/fs/lookup.c
index 6819509d00..55ffb94805 100644
--- a/usr/src/uts/common/fs/lookup.c
+++ b/usr/src/uts/common/fs/lookup.c
@@ -20,6 +20,7 @@
*/
/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -217,7 +218,6 @@ lookuppnvp(
cred_t *cr) /* user's credential */
{
vnode_t *cvp; /* current component vp */
- vnode_t *tvp; /* addressable temp ptr */
char component[MAXNAMELEN]; /* buffer for component (incl null) */
int error;
int nlink;
@@ -373,7 +373,7 @@ checkforroot:
/*
* Perform a lookup in the current directory.
*/
- error = VOP_LOOKUP(vp, component, &tvp, pnp, lookup_flags,
+ error = VOP_LOOKUP(vp, component, &cvp, pnp, lookup_flags,
rootvp, cr, NULL, NULL, pp);
/*
@@ -391,10 +391,9 @@ checkforroot:
* directory inside NFS FS.
*/
if ((error == EACCES) && retry_with_kcred)
- error = VOP_LOOKUP(vp, component, &tvp, pnp, lookup_flags,
+ error = VOP_LOOKUP(vp, component, &cvp, pnp, lookup_flags,
rootvp, zone_kcred(), NULL, NULL, pp);
- cvp = tvp;
if (error) {
cvp = NULL;
/*
@@ -440,20 +439,8 @@ checkforroot:
* be atomic!)
*/
if (vn_mountedvfs(cvp) != NULL) {
- tvp = cvp;
- if ((error = traverse(&tvp)) != 0) {
- /*
- * It is required to assign cvp here, because
- * traverse() will return a held vnode which
- * may different than the vnode that was passed
- * in (even in the error case). If traverse()
- * changes the vnode it releases the original,
- * and holds the new one.
- */
- cvp = tvp;
+ if ((error = traverse(&cvp)) != 0)
goto bad;
- }
- cvp = tvp;
}
/*
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c
index 127d9e3f29..fe1a10b966 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c
@@ -18,10 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -869,7 +870,7 @@ static nfsstat4
do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
{
int error, different_export = 0;
- vnode_t *dvp, *vp, *tvp;
+ vnode_t *dvp, *vp;
struct exportinfo *exi = NULL;
fid_t fid;
uint_t count, i;
@@ -950,14 +951,12 @@ do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
* If it's a mountpoint, then traverse it.
*/
if (vn_ismntpt(vp)) {
- tvp = vp;
- if ((error = traverse(&tvp)) != 0) {
+ if ((error = traverse(&vp)) != 0) {
VN_RELE(vp);
return (puterrno4(error));
}
/* remember that we had to traverse mountpoint */
did_traverse = TRUE;
- vp = tvp;
different_export = 1;
} else if (vp->v_vfsp != dvp->v_vfsp) {
/*
@@ -2610,7 +2609,7 @@ do_rfs4_op_lookup(char *nm, struct svc_req *req, struct compound_state *cs)
{
int error;
int different_export = 0;
- vnode_t *vp, *tvp, *pre_tvp = NULL, *oldvp = NULL;
+ vnode_t *vp, *pre_tvp = NULL, *oldvp = NULL;
struct exportinfo *exi = NULL, *pre_exi = NULL;
nfsstat4 stat;
fid_t fid;
@@ -2708,13 +2707,11 @@ do_rfs4_op_lookup(char *nm, struct svc_req *req, struct compound_state *cs)
* need pre_tvp below if checkexport4 fails
*/
VN_HOLD(pre_tvp);
- tvp = vp;
- if ((error = traverse(&tvp)) != 0) {
+ if ((error = traverse(&vp)) != 0) {
VN_RELE(vp);
VN_RELE(pre_tvp);
return (puterrno4(error));
}
- vp = tvp;
different_export = 1;
} else if (vp->v_vfsp != cs->vp->v_vfsp) {
/*
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c b/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
index 3069a98835..276d3b4f19 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
@@ -18,6 +18,11 @@
*
* CDDL HEADER END
*/
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -149,6 +154,7 @@ nfs4_readdir_getvp(vnode_t *dvp, char *d_name, vnode_t **vpp,
VN_HOLD(pre_tvp);
if ((error = traverse(&vp)) != 0) {
+ VN_RELE(vp);
VN_RELE(pre_tvp);
return (error);
}
diff --git a/usr/src/uts/common/fs/proc/prcontrol.c b/usr/src/uts/common/fs/proc/prcontrol.c
index a5679a8afb..7e99d23b97 100644
--- a/usr/src/uts/common/fs/proc/prcontrol.c
+++ b/usr/src/uts/common/fs/proc/prcontrol.c
@@ -25,7 +25,7 @@
*/
/*
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2015, Joyent, Inc.
*/
#include <sys/types.h>
@@ -1481,7 +1481,7 @@ pr_setsig(prnode_t *pnp, siginfo_t *sip)
} else if (t->t_state == TS_STOPPED && sig == SIGKILL) {
/* If SIGKILL, set stopped lwp running */
p->p_stopsig = 0;
- t->t_schedflag |= TS_XSTART | TS_PSTART;
+ t->t_schedflag |= TS_XSTART | TS_PSTART | TS_BSTART;
t->t_dtrace_stop = 0;
setrun_locked(t);
}
diff --git a/usr/src/uts/common/fs/proc/prsubr.c b/usr/src/uts/common/fs/proc/prsubr.c
index 7801fd0ac8..284bf8cb88 100644
--- a/usr/src/uts/common/fs/proc/prsubr.c
+++ b/usr/src/uts/common/fs/proc/prsubr.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2015, Joyent, Inc.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -201,6 +201,7 @@ prchoose(proc_t *p)
case PR_SYSEXIT:
case PR_SIGNALLED:
case PR_FAULTED:
+ case PR_BRAND:
/*
* Make an lwp calling exit() be the
* last lwp seen in the process.
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
index 3fa43d43cb..5eaa5865c6 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
@@ -820,8 +820,8 @@ smb_open_subr(smb_request_t *sr)
status = NT_STATUS_SUCCESS;
- of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK,
- uniq_fid, &err);
+ of = smb_ofile_open(sr, node, sr->smb_pid, op, SMB_FTYPE_DISK, uniq_fid,
+ &err);
if (of == NULL) {
smbsr_error(sr, err.status, err.errcls, err.errcode);
status = err.status;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c
index 4930f741ef..14eff73896 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_delete.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c
@@ -297,7 +297,7 @@ smb_delete_multiple_files(smb_request_t *sr, smb_error_t *err)
if (odid == 0)
return (-1);
- if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL)
+ if ((od = smb_tree_lookup_odir(sr, odid)) == NULL)
return (-1);
for (;;) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
index 1afcf18b28..9b1fed6f9a 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
@@ -20,8 +20,8 @@
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -694,16 +694,13 @@ andx_more:
}
sr->user_cr = smb_user_getcred(sr->uid_user);
-
- if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID) &&
- (sr->tid_tree == NULL)) {
- sr->tid_tree = smb_user_lookup_tree(
- sr->uid_user, sr->smb_tid);
- if (sr->tid_tree == NULL) {
- smbsr_error(sr, 0, ERRSRV, ERRinvnid);
- smbsr_cleanup(sr);
- goto report_error;
- }
+ }
+ if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID) && (sr->tid_tree == NULL)) {
+ sr->tid_tree = smb_session_lookup_tree(session, sr->smb_tid);
+ if (sr->tid_tree == NULL) {
+ smbsr_error(sr, 0, ERRSRV, ERRinvnid);
+ smbsr_cleanup(sr);
+ goto report_error;
}
}
@@ -1116,8 +1113,7 @@ void
smbsr_lookup_file(smb_request_t *sr)
{
if (sr->fid_ofile == NULL)
- sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree,
- sr->smb_fid);
+ sr->fid_ofile = smb_ofile_lookup_by_fid(sr, sr->smb_fid);
}
static int
diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c
index 1dae4e8cb5..eecbeff4df 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_find.c
@@ -306,7 +306,7 @@ smb_com_search(smb_request_t *sr)
}
}
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
@@ -452,7 +452,7 @@ smb_com_find(smb_request_t *sr)
}
}
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
@@ -575,7 +575,7 @@ smb_com_find_close(smb_request_t *sr)
return (SDRC_ERROR);
}
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
@@ -649,7 +649,7 @@ smb_com_find_unique(struct smb_request *sr)
odid = smb_odir_open(sr, pn->pn_path, sattr, 0);
if (odid == 0)
return (SDRC_ERROR);
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL)
return (SDRC_ERROR);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index 2f4545e966..c64313fdbf 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -805,7 +805,7 @@ smb_fsop_remove_streams(smb_request_t *sr, cred_t *cr, smb_node_t *fnode)
return (-1);
}
- if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL) {
+ if ((od = smb_tree_lookup_odir(sr, odid)) == NULL) {
smbsr_errno(sr, ENOENT);
return (-1);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
index c77c175fc1..037c1373b5 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
@@ -264,8 +264,7 @@ smb_com_nt_create_andx(struct smb_request *sr)
if (op->rootdirfid == 0) {
op->fqi.fq_dnode = sr->tid_tree->t_snode;
} else {
- op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
- (uint16_t)op->rootdirfid);
+ op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
if (op->dir == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERRbadfid);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
index fcc12f2fc8..dcfa469617 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
@@ -173,8 +173,7 @@ smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
if (op->rootdirfid == 0) {
op->fqi.fq_dnode = sr->tid_tree->t_snode;
} else {
- op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
- (uint16_t)op->rootdirfid);
+ op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
if (op->dir == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERRbadfid);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_odir.c b/usr/src/uts/common/fs/smbsrv/smb_odir.c
index b8435d191a..16fffa6692 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_odir.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_odir.c
@@ -39,15 +39,15 @@
* +-------------------+ +-------------------+ +-------------------+
* | SESSION |<----->| SESSION |......| SESSION |
* +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
- * +-------------------+ +-------------------+ +-------------------+
- * | USER |<----->| USER |......| USER |
- * +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
+ * | |
+ * | |
+ * | v
+ * | +-------------------+ +-------------------+ +-------------------+
+ * | | USER |<--->| USER |...| USER |
+ * | +-------------------+ +-------------------+ +-------------------+
+ * |
+ * |
+ * v
* +-------------------+ +-------------------+ +-------------------+
* | TREE |<----->| TREE |......| TREE |
* +-------------------+ +-------------------+ +-------------------+
@@ -153,7 +153,7 @@
* and add it into the tree's list of odirs.
* Return an identifier (odid) uniquely identifying the created odir.
*
- * smb_odir_t *odir = smb_tree_lookup_odir(odid)
+ * smb_odir_t *odir = smb_tree_lookup_odir(..., odid)
* Find the odir corresponding to the specified odid in the tree's
* list of odirs. Place a hold on the odir.
*
@@ -312,9 +312,9 @@ smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr, uint32_t flags)
}
if (flags & SMB_ODIR_OPENF_BACKUP_INTENT)
- cr = smb_user_getprivcred(tree->t_user);
+ cr = smb_user_getprivcred(sr->uid_user);
else
- cr = tree->t_user->u_cred;
+ cr = sr->uid_user->u_cred;
odid = smb_odir_create(sr, dnode, pattern, sattr, cr);
smb_node_release(dnode);
@@ -888,6 +888,12 @@ smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
od->d_opened_by_pid = sr->smb_pid;
od->d_session = tree->t_session;
od->d_cred = cr;
+ /*
+ * grab a ref for od->d_user
+ * released in smb_odir_delete()
+ */
+ smb_user_hold_internal(sr->uid_user);
+ od->d_user = sr->uid_user;
od->d_tree = tree;
od->d_dnode = dnode;
smb_node_ref(dnode);
@@ -947,6 +953,7 @@ smb_odir_delete(void *arg)
od->d_magic = 0;
smb_node_release(od->d_dnode);
+ smb_user_release(od->d_user);
mutex_destroy(&od->d_mutex);
kmem_cache_free(od->d_tree->t_server->si_cache_odir, od);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
index 8987da2950..ee45f13c8b 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
@@ -39,15 +39,15 @@
* +-------------------+ +-------------------+ +-------------------+
* | SESSION |<----->| SESSION |......| SESSION |
* +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
- * +-------------------+ +-------------------+ +-------------------+
- * | USER |<----->| USER |......| USER |
- * +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
+ * | |
+ * | |
+ * | v
+ * | +-------------------+ +-------------------+ +-------------------+
+ * | | USER |<--->| USER |...| USER |
+ * | +-------------------+ +-------------------+ +-------------------+
+ * |
+ * |
+ * v
* +-------------------+ +-------------------+ +-------------------+
* | TREE |<----->| TREE |......| TREE |
* +-------------------+ +-------------------+ +-------------------+
@@ -175,7 +175,7 @@ static void smb_ofile_netinfo_fini(smb_netfileinfo_t *);
*/
smb_ofile_t *
smb_ofile_open(
- smb_tree_t *tree,
+ smb_request_t *sr,
smb_node_t *node,
uint16_t pid,
struct open_param *op,
@@ -183,10 +183,13 @@ smb_ofile_open(
uint32_t uniqid,
smb_error_t *err)
{
+ smb_tree_t *tree = sr->tid_tree;
smb_ofile_t *of;
uint16_t fid;
smb_attr_t attr;
int rc;
+ enum errstates { EMPTY, FIDALLOC, CRHELD, MUTEXINIT };
+ enum errstates state = EMPTY;
if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) {
err->status = NT_STATUS_TOO_MANY_OPENED_FILES;
@@ -194,6 +197,7 @@ smb_ofile_open(
err->errcode = ERROR_TOO_MANY_OPEN_FILES;
return (NULL);
}
+ state = FIDALLOC;
of = kmem_cache_alloc(tree->t_server->si_cache_ofile, KM_SLEEP);
bzero(of, sizeof (smb_ofile_t));
@@ -206,16 +210,23 @@ smb_ofile_open(
of->f_share_access = op->share_access;
of->f_create_options = op->create_options;
of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ?
- smb_user_getprivcred(tree->t_user) : tree->t_user->u_cred;
+ smb_user_getprivcred(sr->uid_user) : sr->uid_user->u_cred;
crhold(of->f_cr);
+ state = CRHELD;
of->f_ftype = ftype;
of->f_server = tree->t_server;
- of->f_session = tree->t_user->u_session;
- of->f_user = tree->t_user;
+ of->f_session = tree->t_session;
+ /*
+ * grab a ref for of->f_user
+ * released in smb_ofile_delete()
+ */
+ smb_user_hold_internal(sr->uid_user);
+ of->f_user = sr->uid_user;
of->f_tree = tree;
of->f_node = node;
mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
+ state = MUTEXINIT;
of->f_state = SMB_OFILE_STATE_OPEN;
if (ftype == SMB_FTYPE_MESG_PIPE) {
@@ -232,15 +243,10 @@ smb_ofile_open(
attr.sa_mask = SMB_AT_UID | SMB_AT_DOSATTR;
rc = smb_node_getattr(NULL, node, of->f_cr, NULL, &attr);
if (rc != 0) {
- of->f_magic = 0;
- mutex_destroy(&of->f_mutex);
- crfree(of->f_cr);
- smb_idpool_free(&tree->t_fid_pool, of->f_fid);
- kmem_cache_free(tree->t_server->si_cache_ofile, of);
err->status = NT_STATUS_INTERNAL_ERROR;
err->errcls = ERRDOS;
err->errcode = ERROR_INTERNAL_ERROR;
- return (NULL);
+ goto errout;
}
if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) {
/*
@@ -254,16 +260,10 @@ smb_ofile_open(
of->f_mode =
smb_fsop_amask_to_omode(of->f_granted_access);
if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) {
- of->f_magic = 0;
- mutex_destroy(&of->f_mutex);
- crfree(of->f_cr);
- smb_idpool_free(&tree->t_fid_pool, of->f_fid);
- kmem_cache_free(tree->t_server->si_cache_ofile,
- of);
err->status = NT_STATUS_ACCESS_DENIED;
err->errcls = ERRDOS;
err->errcode = ERROR_ACCESS_DENIED;
- return (NULL);
+ goto errout;
}
}
@@ -290,6 +290,25 @@ smb_ofile_open(
atomic_inc_32(&tree->t_open_files);
atomic_inc_32(&of->f_session->s_file_cnt);
return (of);
+
+errout:
+ switch (state) {
+ case MUTEXINIT:
+ mutex_destroy(&of->f_mutex);
+ smb_user_release(of->f_user);
+ /*FALLTHROUGH*/
+ case CRHELD:
+ crfree(of->f_cr);
+ of->f_magic = 0;
+ kmem_cache_free(tree->t_server->si_cache_ofile, of);
+ /*FALLTHROUGH*/
+ case FIDALLOC:
+ smb_idpool_free(&tree->t_fid_pool, fid);
+ /*FALLTHROUGH*/
+ case EMPTY:
+ break;
+ }
+ return (NULL);
}
/*
@@ -601,9 +620,10 @@ smb_ofile_request_complete(smb_ofile_t *of)
*/
smb_ofile_t *
smb_ofile_lookup_by_fid(
- smb_tree_t *tree,
+ smb_request_t *sr,
uint16_t fid)
{
+ smb_tree_t *tree = sr->tid_tree;
smb_llist_t *of_list;
smb_ofile_t *of;
@@ -616,19 +636,32 @@ smb_ofile_lookup_by_fid(
while (of) {
ASSERT(of->f_magic == SMB_OFILE_MAGIC);
ASSERT(of->f_tree == tree);
- if (of->f_fid == fid) {
- mutex_enter(&of->f_mutex);
- if (of->f_state != SMB_OFILE_STATE_OPEN) {
- mutex_exit(&of->f_mutex);
- smb_llist_exit(of_list);
- return (NULL);
- }
- of->f_refcnt++;
- mutex_exit(&of->f_mutex);
+ if (of->f_fid == fid)
break;
- }
of = smb_llist_next(of_list, of);
}
+ if (of == NULL)
+ goto out;
+
+ /*
+ * Only allow use of a given FID with the same UID that
+ * was used to open it. MS-CIFS 3.3.5.14
+ */
+ if (of->f_user != sr->uid_user) {
+ of = NULL;
+ goto out;
+ }
+
+ mutex_enter(&of->f_mutex);
+ if (of->f_state != SMB_OFILE_STATE_OPEN) {
+ mutex_exit(&of->f_mutex);
+ of = NULL;
+ goto out;
+ }
+ of->f_refcnt++;
+ mutex_exit(&of->f_mutex);
+
+out:
smb_llist_exit(of_list);
return (of);
}
@@ -921,6 +954,7 @@ smb_ofile_delete(void *arg)
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(of->f_tree->t_server->si_cache_ofile, of);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_opipe.c b/usr/src/uts/common/fs/smbsrv/smb_opipe.c
index bb178f3952..90cb25aaa0 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_opipe.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_opipe.c
@@ -130,8 +130,8 @@ smb_opipe_open(smb_request_t *sr)
op->create_options = 0;
- of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op,
- SMB_FTYPE_MESG_PIPE, SMB_UNIQ_FID(), &err);
+ of = smb_ofile_open(sr, NULL, sr->smb_pid, op, SMB_FTYPE_MESG_PIPE,
+ SMB_UNIQ_FID(), &err);
if (of == NULL)
return (err.status);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c
index b8c835cd57..2839ca2807 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c
@@ -85,11 +85,11 @@ smb_com_process_exit(smb_request_t *sr)
* to be the only thing that sends this request these days and
* it doesn't provide a TID.
*/
- sr->tid_tree = smb_user_lookup_tree(sr->uid_user, sr->smb_tid);
+ sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
if (sr->tid_tree != NULL)
smb_tree_close_pid(sr->tid_tree, sr->smb_pid);
else
- smb_user_close_pid(sr->uid_user, sr->smb_pid);
+ smb_session_close_pid(sr->session, sr->smb_pid);
rc = smbsr_encode_empty_result(sr);
return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
index bef69e7f61..70ac2e7b24 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
@@ -662,7 +662,7 @@ smb_encode_stream_info(smb_request_t *sr, smb_xa_t *xa, smb_queryinfo_t *qinfo)
odid = smb_odir_openat(sr, fnode);
if (odid != 0)
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od != NULL)
rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c
index 3654744569..8687d42b18 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c
@@ -240,7 +240,8 @@ static void smb_event_cancel(smb_server_t *, uint32_t);
static uint32_t smb_event_alloc_txid(void);
static void smb_server_disconnect_share(smb_llist_t *, const char *);
-static void smb_server_enum_private(smb_llist_t *, smb_svcenum_t *);
+static void smb_server_enum_users(smb_llist_t *, smb_svcenum_t *);
+static void smb_server_enum_trees(smb_llist_t *, smb_svcenum_t *);
static int smb_server_session_disconnect(smb_llist_t *, const char *,
const char *);
static int smb_server_fclose(smb_llist_t *, uint32_t);
@@ -833,15 +834,6 @@ smb_server_enum(smb_ioc_svcenum_t *ioc)
smb_server_t *sv;
int rc;
- switch (svcenum->se_type) {
- case SMB_SVCENUM_TYPE_USER:
- case SMB_SVCENUM_TYPE_TREE:
- case SMB_SVCENUM_TYPE_FILE:
- break;
- default:
- return (EINVAL);
- }
-
if ((rc = smb_server_lookup(&sv)) != 0)
return (rc);
@@ -849,11 +841,26 @@ smb_server_enum(smb_ioc_svcenum_t *ioc)
svcenum->se_bused = 0;
svcenum->se_nitems = 0;
- smb_server_enum_private(&sv->sv_nbt_daemon.ld_session_list, svcenum);
- smb_server_enum_private(&sv->sv_tcp_daemon.ld_session_list, svcenum);
+ switch (svcenum->se_type) {
+ case SMB_SVCENUM_TYPE_USER:
+ smb_server_enum_users(&sv->sv_nbt_daemon.ld_session_list,
+ svcenum);
+ smb_server_enum_users(&sv->sv_tcp_daemon.ld_session_list,
+ svcenum);
+ break;
+ case SMB_SVCENUM_TYPE_TREE:
+ case SMB_SVCENUM_TYPE_FILE:
+ smb_server_enum_trees(&sv->sv_nbt_daemon.ld_session_list,
+ svcenum);
+ smb_server_enum_trees(&sv->sv_tcp_daemon.ld_session_list,
+ svcenum);
+ break;
+ default:
+ rc = EINVAL;
+ }
smb_server_release(sv);
- return (0);
+ return (rc);
}
/*
@@ -1694,7 +1701,7 @@ smb_server_release(smb_server_t *sv)
* Enumerate the users associated with a session list.
*/
static void
-smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum)
+smb_server_enum_users(smb_llist_t *ll, smb_svcenum_t *svcenum)
{
smb_session_t *sn;
smb_llist_t *ulist;
@@ -1714,6 +1721,8 @@ smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum)
if (smb_user_hold(user)) {
rc = smb_user_enum(user, svcenum);
smb_user_release(user);
+ if (rc != 0)
+ break;
}
user = smb_llist_next(ulist, user);
@@ -1731,6 +1740,48 @@ smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum)
}
/*
+ * Enumerate the trees/files associated with a session list.
+ */
+static void
+smb_server_enum_trees(smb_llist_t *ll, smb_svcenum_t *svcenum)
+{
+ smb_session_t *sn;
+ smb_llist_t *tlist;
+ smb_tree_t *tree;
+ int rc = 0;
+
+ smb_llist_enter(ll, RW_READER);
+ sn = smb_llist_head(ll);
+
+ while (sn != NULL) {
+ SMB_SESSION_VALID(sn);
+ tlist = &sn->s_tree_list;
+ smb_llist_enter(tlist, RW_READER);
+ tree = smb_llist_head(tlist);
+
+ while (tree != NULL) {
+ if (smb_tree_hold(tree)) {
+ rc = smb_tree_enum(tree, svcenum);
+ smb_tree_release(tree);
+ if (rc != 0)
+ break;
+ }
+
+ tree = smb_llist_next(tlist, tree);
+ }
+
+ smb_llist_exit(tlist);
+
+ if (rc != 0)
+ break;
+
+ sn = smb_llist_next(ll, sn);
+ }
+
+ smb_llist_exit(ll);
+}
+
+/*
* Disconnect sessions associated with the specified client and username.
* Empty strings are treated as wildcards.
*/
@@ -1796,8 +1847,8 @@ static int
smb_server_fclose(smb_llist_t *ll, uint32_t uniqid)
{
smb_session_t *sn;
- smb_llist_t *ulist;
- smb_user_t *user;
+ smb_llist_t *tlist;
+ smb_tree_t *tree;
int rc = ENOENT;
smb_llist_enter(ll, RW_READER);
@@ -1805,20 +1856,20 @@ smb_server_fclose(smb_llist_t *ll, uint32_t uniqid)
while ((sn != NULL) && (rc == ENOENT)) {
SMB_SESSION_VALID(sn);
- ulist = &sn->s_user_list;
- smb_llist_enter(ulist, RW_READER);
- user = smb_llist_head(ulist);
-
- while ((user != NULL) && (rc == ENOENT)) {
- if (smb_user_hold(user)) {
- rc = smb_user_fclose(user, uniqid);
- smb_user_release(user);
+ tlist = &sn->s_tree_list;
+ smb_llist_enter(tlist, RW_READER);
+ tree = smb_llist_head(tlist);
+
+ while ((tree != NULL) && (rc == ENOENT)) {
+ if (smb_tree_hold(tree)) {
+ rc = smb_tree_fclose(tree, uniqid);
+ smb_tree_release(tree);
}
- user = smb_llist_next(ulist, user);
+ tree = smb_llist_next(tlist, tree);
}
- smb_llist_exit(ulist);
+ smb_llist_exit(tlist);
sn = smb_llist_next(ll, sn);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_session.c b/usr/src/uts/common/fs/smbsrv/smb_session.c
index 0fdac10ca6..b8284b372f 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c
@@ -43,6 +43,7 @@ static int smb_session_message(smb_session_t *);
static int smb_session_xprt_puthdr(smb_session_t *, smb_xprt_t *,
uint8_t *, size_t);
static smb_user_t *smb_session_lookup_user(smb_session_t *, char *, char *);
+static smb_tree_t *smb_session_get_tree(smb_session_t *, smb_tree_t *);
static void smb_session_logoff(smb_session_t *);
static void smb_request_init_command_mbuf(smb_request_t *sr);
void dump_smb_inaddr(smb_inaddr_t *ipaddr);
@@ -624,6 +625,11 @@ smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
kmem_cache_free(sv->si_cache_session, session);
return (NULL);
}
+ if (smb_idpool_constructor(&session->s_tid_pool)) {
+ smb_idpool_destructor(&session->s_uid_pool);
+ kmem_cache_free(sv->si_cache_session, session);
+ return (NULL);
+ }
now = ddi_get_lbolt64();
@@ -642,6 +648,9 @@ smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t),
offsetof(smb_user_t, u_lnd));
+ smb_llist_constructor(&session->s_tree_list, sizeof (smb_tree_t),
+ offsetof(smb_tree_t, t_lnd));
+
smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t),
offsetof(smb_xa_t, xa_lnd));
@@ -719,6 +728,7 @@ smb_session_delete(smb_session_t *session)
list_destroy(&session->s_oplock_brkreqs);
smb_slist_destructor(&session->s_req_list);
+ smb_llist_destructor(&session->s_tree_list);
smb_llist_destructor(&session->s_user_list);
smb_llist_destructor(&session->s_xa_list);
@@ -726,6 +736,7 @@ smb_session_delete(smb_session_t *session)
ASSERT(session->s_file_cnt == 0);
ASSERT(session->s_dir_cnt == 0);
+ smb_idpool_destructor(&session->s_tid_pool);
smb_idpool_destructor(&session->s_uid_pool);
if (session->sock != NULL) {
if (session->s_local_port == IPPORT_NETBIOS_SSN)
@@ -928,45 +939,306 @@ smb_session_post_user(smb_session_t *session, smb_user_t *user)
}
/*
- * Logoff all users associated with the specified session.
+ * Find a tree by tree-id.
*/
-static void
-smb_session_logoff(smb_session_t *session)
+smb_tree_t *
+smb_session_lookup_tree(
+ smb_session_t *session,
+ uint16_t tid)
+
{
- smb_user_t *user;
+ smb_tree_t *tree;
SMB_SESSION_VALID(session);
- smb_llist_enter(&session->s_user_list, RW_READER);
+ smb_llist_enter(&session->s_tree_list, RW_READER);
+ tree = smb_llist_head(&session->s_tree_list);
- user = smb_llist_head(&session->s_user_list);
- while (user) {
- SMB_USER_VALID(user);
- ASSERT(user->u_session == session);
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
- if (smb_user_hold(user)) {
- smb_user_logoff(user);
- smb_user_release(user);
+ if (tree->t_tid == tid) {
+ if (smb_tree_hold(tree)) {
+ smb_llist_exit(&session->s_tree_list);
+ return (tree);
+ } else {
+ smb_llist_exit(&session->s_tree_list);
+ return (NULL);
+ }
}
- user = smb_llist_next(&session->s_user_list, user);
+ tree = smb_llist_next(&session->s_tree_list, tree);
}
- smb_llist_exit(&session->s_user_list);
+ smb_llist_exit(&session->s_tree_list);
+ return (NULL);
+}
+
+/*
+ * Find the first connected tree that matches the specified sharename.
+ * If the specified tree is NULL the search starts from the beginning of
+ * the user's tree list. If a tree is provided the search starts just
+ * after that tree.
+ */
+smb_tree_t *
+smb_session_lookup_share(
+ smb_session_t *session,
+ const char *sharename,
+ smb_tree_t *tree)
+{
+ SMB_SESSION_VALID(session);
+ ASSERT(sharename);
+
+ smb_llist_enter(&session->s_tree_list, RW_READER);
+
+ if (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ tree = smb_llist_next(&session->s_tree_list, tree);
+ } else {
+ tree = smb_llist_head(&session->s_tree_list);
+ }
+
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ if (smb_strcasecmp(tree->t_sharename, sharename, 0) == 0) {
+ if (smb_tree_hold(tree)) {
+ smb_llist_exit(&session->s_tree_list);
+ return (tree);
+ }
+ }
+ tree = smb_llist_next(&session->s_tree_list, tree);
+ }
+
+ smb_llist_exit(&session->s_tree_list);
+ return (NULL);
+}
+
+/*
+ * Find the first connected tree that matches the specified volume name.
+ * If the specified tree is NULL the search starts from the beginning of
+ * the user's tree list. If a tree is provided the search starts just
+ * after that tree.
+ */
+smb_tree_t *
+smb_session_lookup_volume(
+ smb_session_t *session,
+ const char *name,
+ smb_tree_t *tree)
+{
+ SMB_SESSION_VALID(session);
+ ASSERT(name);
+
+ smb_llist_enter(&session->s_tree_list, RW_READER);
+
+ if (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ tree = smb_llist_next(&session->s_tree_list, tree);
+ } else {
+ tree = smb_llist_head(&session->s_tree_list);
+ }
+
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+
+ if (smb_strcasecmp(tree->t_volume, name, 0) == 0) {
+ if (smb_tree_hold(tree)) {
+ smb_llist_exit(&session->s_tree_list);
+ return (tree);
+ }
+ }
+
+ tree = smb_llist_next(&session->s_tree_list, tree);
+ }
+
+ smb_llist_exit(&session->s_tree_list);
+ return (NULL);
+}
+
+/*
+ * Disconnect all trees that match the specified client process-id.
+ */
+void
+smb_session_close_pid(
+ smb_session_t *session,
+ uint16_t pid)
+{
+ smb_tree_t *tree;
+
+ SMB_SESSION_VALID(session);
+
+ tree = smb_session_get_tree(session, NULL);
+ while (tree) {
+ smb_tree_t *next;
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ smb_tree_close_pid(tree, pid);
+ next = smb_session_get_tree(session, tree);
+ smb_tree_release(tree);
+ tree = next;
+ }
+}
+
+static void
+smb_session_tree_dtor(void *t)
+{
+ smb_tree_t *tree = (smb_tree_t *)t;
+
+ smb_tree_disconnect(tree, B_TRUE);
+ /* release the ref acquired during the traversal loop */
+ smb_tree_release(tree);
}
+
/*
- * Disconnect any trees associated with the specified share.
- * Iterate through the users on this session and tell each user
- * to disconnect from the share.
+ * Disconnect all trees that this user has connected.
*/
void
-smb_session_disconnect_share(smb_session_t *session, const char *sharename)
+smb_session_disconnect_owned_trees(
+ smb_session_t *session,
+ smb_user_t *owner)
+{
+ smb_tree_t *tree;
+ smb_llist_t *tree_list = &session->s_tree_list;
+
+ SMB_SESSION_VALID(session);
+ SMB_USER_VALID(owner);
+
+ smb_llist_enter(tree_list, RW_READER);
+
+ tree = smb_llist_head(tree_list);
+ while (tree) {
+ if ((tree->t_owner == owner) &&
+ smb_tree_hold(tree)) {
+ /*
+ * smb_tree_hold() succeeded, hence we are in state
+ * SMB_TREE_STATE_CONNECTED; schedule this tree
+ * for asynchronous disconnect, which will fire
+ * after we drop the llist traversal lock.
+ */
+ smb_llist_post(tree_list, tree, smb_session_tree_dtor);
+ }
+ tree = smb_llist_next(tree_list, tree);
+ }
+
+ /* drop the lock and flush the dtor queue */
+ smb_llist_exit(tree_list);
+}
+
+/*
+ * Disconnect all trees that this user has connected.
+ */
+void
+smb_session_disconnect_trees(
+ smb_session_t *session)
+{
+ smb_tree_t *tree;
+
+ SMB_SESSION_VALID(session);
+
+ tree = smb_session_get_tree(session, NULL);
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ smb_tree_disconnect(tree, B_TRUE);
+ smb_tree_release(tree);
+ tree = smb_session_get_tree(session, NULL);
+ }
+}
+
+/*
+ * Disconnect all trees that match the specified share name.
+ */
+void
+smb_session_disconnect_share(
+ smb_session_t *session,
+ const char *sharename)
+{
+ smb_tree_t *tree;
+ smb_tree_t *next;
+
+ SMB_SESSION_VALID(session);
+
+ tree = smb_session_lookup_share(session, sharename, NULL);
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ smb_session_cancel_requests(session, tree, NULL);
+ smb_tree_disconnect(tree, B_TRUE);
+ next = smb_session_lookup_share(session, sharename, tree);
+ smb_tree_release(tree);
+ tree = next;
+ }
+}
+
+void
+smb_session_post_tree(smb_session_t *session, smb_tree_t *tree)
+{
+ SMB_SESSION_VALID(session);
+ SMB_TREE_VALID(tree);
+ ASSERT0(tree->t_refcnt);
+ ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
+ ASSERT(tree->t_session == session);
+
+ smb_llist_post(&session->s_tree_list, tree, smb_tree_dealloc);
+}
+
+/*
+ * Get the next connected tree in the list. A reference is taken on
+ * the tree, which can be released later with smb_tree_release().
+ *
+ * If the specified tree is NULL the search starts from the beginning of
+ * the tree list. If a tree is provided the search starts just after
+ * that tree.
+ *
+ * Returns NULL if there are no connected trees in the list.
+ */
+static smb_tree_t *
+smb_session_get_tree(
+ smb_session_t *session,
+ smb_tree_t *tree)
+{
+ smb_llist_t *tree_list;
+
+ SMB_SESSION_VALID(session);
+ tree_list = &session->s_tree_list;
+
+ smb_llist_enter(tree_list, RW_READER);
+
+ if (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ tree = smb_llist_next(tree_list, tree);
+ } else {
+ tree = smb_llist_head(tree_list);
+ }
+
+ while (tree) {
+ if (smb_tree_hold(tree))
+ break;
+
+ tree = smb_llist_next(tree_list, tree);
+ }
+
+ smb_llist_exit(tree_list);
+ return (tree);
+}
+
+/*
+ * Logoff all users associated with the specified session.
+ */
+static void
+smb_session_logoff(smb_session_t *session)
{
smb_user_t *user;
SMB_SESSION_VALID(session);
+ smb_session_disconnect_trees(session);
+
smb_llist_enter(&session->s_user_list, RW_READER);
user = smb_llist_head(&session->s_user_list);
@@ -975,7 +1247,7 @@ smb_session_disconnect_share(smb_session_t *session, const char *sharename)
ASSERT(user->u_session == session);
if (smb_user_hold(user)) {
- smb_user_disconnect_share(user, sharename);
+ smb_user_logoff(user);
smb_user_release(user);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
index 037b2a3b36..d0d60cea5d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
@@ -332,7 +332,7 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa)
return (SDRC_ERROR);
}
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL)
return (SDRC_ERROR);
@@ -463,7 +463,7 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa)
if (args.fa_maxdata == 0)
return (SDRC_ERROR);
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
@@ -943,7 +943,7 @@ smb_com_find_close2(smb_request_t *sr)
if (smbsr_decode_vwv(sr, "w", &odid) != 0)
return (SDRC_ERROR);
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c
index 13adc2d803..b225c67623 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -40,15 +40,15 @@
* +-------------------+ +-------------------+ +-------------------+
* | SESSION |<----->| SESSION |......| SESSION |
* +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
- * +-------------------+ +-------------------+ +-------------------+
- * | USER |<----->| USER |......| USER |
- * +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
+ * | |
+ * | |
+ * | v
+ * | +-------------------+ +-------------------+ +-------------------+
+ * | | USER |<--->| USER |...| USER |
+ * | +-------------------+ +-------------------+ +-------------------+
+ * |
+ * |
+ * v
* +-------------------+ +-------------------+ +-------------------+
* | TREE |<----->| TREE |......| TREE |
* +-------------------+ +-------------------+ +-------------------+
@@ -175,7 +175,7 @@ static smb_tree_t *smb_tree_connect_core(smb_request_t *);
static smb_tree_t *smb_tree_connect_disk(smb_request_t *, const char *);
static smb_tree_t *smb_tree_connect_printq(smb_request_t *, const char *);
static smb_tree_t *smb_tree_connect_ipc(smb_request_t *, const char *);
-static smb_tree_t *smb_tree_alloc(smb_user_t *, const smb_kshare_t *,
+static smb_tree_t *smb_tree_alloc(smb_request_t *, const smb_kshare_t *,
smb_node_t *, uint32_t, uint32_t);
static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
static boolean_t smb_tree_is_disconnected(smb_tree_t *);
@@ -269,6 +269,7 @@ smb_tree_connect_core(smb_request_t *sr)
}
smb_kshare_release(si);
+
return (tree);
}
@@ -361,7 +362,7 @@ smb_tree_release(
smb_llist_flush(&tree->t_odir_list);
if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0))
- smb_user_post_tree(tree->t_user, tree);
+ smb_session_post_tree(tree->t_session, tree);
mutex_exit(&tree->t_mutex);
}
@@ -428,7 +429,7 @@ smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
{
smb_ofile_t *of;
smb_ofile_t *next;
- int rc;
+ int rc = 0;
ASSERT(tree);
ASSERT(tree->t_magic == SMB_TREE_MAGIC);
@@ -712,8 +713,7 @@ smb_tree_connect_disk(smb_request_t *sr, const char *sharename)
if (!smb_shortnames)
sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
- tree = smb_tree_alloc(user, si, snode, access,
- sr->sr_cfg->skc_execflags);
+ tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
smb_node_release(snode);
@@ -805,8 +805,7 @@ smb_tree_connect_printq(smb_request_t *sr, const char *sharename)
sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS;
- tree = smb_tree_alloc(user, si, snode, access,
- sr->sr_cfg->skc_execflags);
+ tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
smb_node_release(snode);
@@ -846,7 +845,7 @@ smb_tree_connect_ipc(smb_request_t *sr, const char *name)
sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS;
- tree = smb_tree_alloc(user, si, NULL, ACE_ALL_PERMS, 0);
+ tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
if (tree == NULL) {
smb_tree_log(sr, name, "access denied");
smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess);
@@ -859,41 +858,45 @@ smb_tree_connect_ipc(smb_request_t *sr, const char *name)
* Allocate a tree.
*/
static smb_tree_t *
-smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *snode,
- uint32_t access, uint32_t execflags)
+smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
+ smb_node_t *snode, uint32_t access, uint32_t execflags)
{
+ smb_session_t *session = sr->session;
smb_tree_t *tree;
uint32_t stype = si->shr_type;
uint16_t tid;
- if (smb_idpool_alloc(&user->u_tid_pool, &tid))
+ if (smb_idpool_alloc(&session->s_tid_pool, &tid))
return (NULL);
- tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP);
+ tree = kmem_cache_alloc(session->s_server->si_cache_tree, KM_SLEEP);
bzero(tree, sizeof (smb_tree_t));
- tree->t_user = user;
- tree->t_session = user->u_session;
- tree->t_server = user->u_server;
+ tree->t_session = session;
+ tree->t_server = session->s_server;
+
+ /* grab a ref for tree->t_owner */
+ smb_user_hold_internal(sr->uid_user);
+ tree->t_owner = sr->uid_user;
if (STYPE_ISDSK(stype) || STYPE_ISPRN(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);
+ smb_idpool_free(&session->s_tid_pool, tid);
+ kmem_cache_free(session->s_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);
+ smb_idpool_free(&session->s_tid_pool, tid);
+ kmem_cache_free(session->s_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);
+ smb_idpool_free(&session->s_tid_pool, tid);
+ kmem_cache_free(session->s_server->si_cache_tree, tree);
return (NULL);
}
@@ -929,11 +932,11 @@ smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *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);
- smb_server_inc_trees(user->u_server);
+ smb_llist_enter(&session->s_tree_list, RW_WRITER);
+ smb_llist_insert_head(&session->s_tree_list, tree);
+ smb_llist_exit(&session->s_tree_list);
+ atomic_inc_32(&session->s_tree_cnt);
+ smb_server_inc_trees(session->s_server);
return (tree);
}
@@ -947,19 +950,19 @@ smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *snode,
void
smb_tree_dealloc(void *arg)
{
- smb_user_t *user;
+ smb_session_t *session;
smb_tree_t *tree = (smb_tree_t *)arg;
SMB_TREE_VALID(tree);
ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
ASSERT(tree->t_refcnt == 0);
- user = tree->t_user;
- smb_llist_enter(&user->u_tree_list, RW_WRITER);
- smb_llist_remove(&user->u_tree_list, tree);
- smb_idpool_free(&user->u_tid_pool, tree->t_tid);
- atomic_dec_32(&tree->t_session->s_tree_cnt);
- smb_llist_exit(&user->u_tree_list);
+ session = tree->t_session;
+ smb_llist_enter(&session->s_tree_list, RW_WRITER);
+ smb_llist_remove(&session->s_tree_list, tree);
+ smb_idpool_free(&session->s_tid_pool, tree->t_tid);
+ atomic_dec_32(&session->s_tree_cnt);
+ smb_llist_exit(&session->s_tree_list);
mutex_enter(&tree->t_mutex);
mutex_exit(&tree->t_mutex);
@@ -974,6 +977,10 @@ smb_tree_dealloc(void *arg)
smb_llist_destructor(&tree->t_odir_list);
smb_idpool_destructor(&tree->t_fid_pool);
smb_idpool_destructor(&tree->t_odid_pool);
+
+ SMB_USER_VALID(tree->t_owner);
+ smb_user_release(tree->t_owner);
+
kmem_cache_free(tree->t_server->si_cache_tree, tree);
}
@@ -1234,27 +1241,38 @@ smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...)
* Returns NULL if odir not found or a hold cannot be obtained.
*/
smb_odir_t *
-smb_tree_lookup_odir(smb_tree_t *tree, uint16_t odid)
+smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid)
{
smb_odir_t *od;
smb_llist_t *od_list;
+ smb_tree_t *tree = sr->tid_tree;
- ASSERT(tree);
ASSERT(tree->t_magic == SMB_TREE_MAGIC);
od_list = &tree->t_odir_list;
- smb_llist_enter(od_list, RW_READER);
+ smb_llist_enter(od_list, RW_READER);
od = smb_llist_head(od_list);
while (od) {
- if (od->d_odid == odid) {
- if (!smb_odir_hold(od))
- od = NULL;
+ if (od->d_odid == odid)
break;
- }
od = smb_llist_next(od_list, od);
}
+ if (od == NULL)
+ goto out;
+
+ /*
+ * Only allow use of a given Search ID with the same UID that
+ * was used to create it. MS-CIFS 3.3.5.14
+ */
+ if (od->d_user != sr->uid_user) {
+ od = NULL;
+ goto out;
+ }
+ if (!smb_odir_hold(od))
+ od = NULL;
+out:
smb_llist_exit(od_list);
return (od);
}
@@ -1377,15 +1395,16 @@ smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid)
}
static void
-smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec, int exec_type)
+smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
+ int exec_type)
{
exec->e_sharename = tree->t_sharename;
- exec->e_winname = tree->t_user->u_name;
- exec->e_userdom = tree->t_user->u_domain;
+ exec->e_winname = tree->t_owner->u_name;
+ exec->e_userdom = tree->t_owner->u_domain;
exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
exec->e_cli_ipaddr = tree->t_session->ipaddr;
exec->e_cli_netbiosname = tree->t_session->workstation;
- exec->e_uid = crgetuid(tree->t_user->u_cred);
+ exec->e_uid = crgetuid(tree->t_owner->u_cred);
exec->e_type = exec_type;
}
@@ -1438,6 +1457,26 @@ smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
return (rc);
}
+static void
+smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen)
+{
+ smb_user_t *user = tree->t_owner;
+
+ /*
+ * u_domain_len and u_name_len include the '\0' in their
+ * lengths, hence the sum of the two lengths gives us room
+ * for both the '\\' and '\0' chars.
+ */
+ ASSERT(namestr);
+ ASSERT(namelen);
+ ASSERT(user->u_domain_len > 0);
+ ASSERT(user->u_name_len > 0);
+ *namelen = user->u_domain_len + user->u_name_len;
+ *namestr = kmem_alloc(*namelen, KM_SLEEP);
+ (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain,
+ user->u_name);
+}
+
/*
* Note: ci_numusers should be the number of users connected to
* the share rather than the number of references on the tree but
@@ -1446,8 +1485,6 @@ smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
static void
smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
{
- smb_user_t *user;
-
ASSERT(tree);
info->ci_id = tree->t_tid;
@@ -1459,13 +1496,7 @@ smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
info->ci_sharelen = strlen(tree->t_sharename) + 1;
info->ci_share = smb_mem_strdup(tree->t_sharename);
- user = tree->t_user;
- ASSERT(user);
-
- info->ci_namelen = user->u_domain_len + user->u_name_len + 2;
- info->ci_username = kmem_alloc(info->ci_namelen, KM_SLEEP);
- (void) snprintf(info->ci_username, info->ci_namelen, "%s\\%s",
- user->u_domain, user->u_name);
+ smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen);
}
static void
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c
index 1ce9720f5d..19b857e834 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
@@ -362,8 +363,7 @@ smb_sdrc_t
smb_pre_tree_disconnect(smb_request_t *sr)
{
sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
- if (sr->uid_user != NULL)
- sr->tid_tree = smb_user_lookup_tree(sr->uid_user, sr->smb_tid);
+ sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr);
return (SDRC_SUCCESS);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_user.c b/usr/src/uts/common/fs/smbsrv/smb_user.c
index cc3fde7f38..09eaba699c 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_user.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_user.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -38,15 +39,15 @@
* +-------------------+ +-------------------+ +-------------------+
* | SESSION |<----->| SESSION |......| SESSION |
* +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
- * +-------------------+ +-------------------+ +-------------------+
- * | USER |<----->| USER |......| USER |
- * +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
+ * | |
+ * | |
+ * | v
+ * | +-------------------+ +-------------------+ +-------------------+
+ * | | USER |<--->| USER |...| USER |
+ * | +-------------------+ +-------------------+ +-------------------+
+ * |
+ * |
+ * v
* +-------------------+ +-------------------+ +-------------------+
* | TREE |<----->| TREE |......| TREE |
* +-------------------+ +-------------------+ +-------------------+
@@ -170,7 +171,6 @@
static boolean_t smb_user_is_logged_in(smb_user_t *);
static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
-static smb_tree_t *smb_user_get_tree(smb_llist_t *, smb_tree_t *);
static void smb_user_setcred(smb_user_t *, cred_t *, uint32_t);
static void smb_user_nonauth_logon(uint32_t);
static void smb_user_auth_logoff(uint32_t);
@@ -210,20 +210,15 @@ smb_user_login(
user->u_audit_sid = audit_sid;
if (!smb_idpool_alloc(&session->s_uid_pool, &user->u_uid)) {
- if (!smb_idpool_constructor(&user->u_tid_pool)) {
- smb_llist_constructor(&user->u_tree_list,
- sizeof (smb_tree_t), offsetof(smb_tree_t, t_lnd));
- mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
- smb_user_setcred(user, cr, privileges);
- user->u_state = SMB_USER_STATE_LOGGED_IN;
- user->u_magic = SMB_USER_MAGIC;
- smb_llist_enter(&session->s_user_list, RW_WRITER);
- smb_llist_insert_tail(&session->s_user_list, user);
- smb_llist_exit(&session->s_user_list);
- smb_server_inc_users(session->s_server);
- return (user);
- }
- smb_idpool_free(&session->s_uid_pool, user->u_uid);
+ mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
+ smb_user_setcred(user, cr, privileges);
+ user->u_state = SMB_USER_STATE_LOGGED_IN;
+ user->u_magic = SMB_USER_MAGIC;
+ smb_llist_enter(&session->s_user_list, RW_WRITER);
+ smb_llist_insert_tail(&session->s_user_list, user);
+ smb_llist_exit(&session->s_user_list);
+ smb_server_inc_users(session->s_server);
+ return (user);
}
smb_mem_free(user->u_name);
smb_mem_free(user->u_domain);
@@ -279,10 +274,7 @@ smb_user_logoff(
*/
user->u_state = SMB_USER_STATE_LOGGING_OFF;
mutex_exit(&user->u_mutex);
- /*
- * All the trees hanging off of this user are disconnected.
- */
- smb_user_disconnect_trees(user);
+ smb_session_disconnect_owned_trees(user->u_session, user);
smb_user_auth_logoff(user->u_audit_sid);
mutex_enter(&user->u_mutex);
user->u_state = SMB_USER_STATE_LOGGED_OFF;
@@ -301,13 +293,13 @@ smb_user_logoff(
}
/*
- * Take a reference on a user.
+ * Take a reference on a user. Do not return a reference unless the user is in
+ * the logged-in state.
*/
boolean_t
smb_user_hold(smb_user_t *user)
{
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
+ SMB_USER_VALID(user);
mutex_enter(&user->u_mutex);
@@ -322,6 +314,19 @@ smb_user_hold(smb_user_t *user)
}
/*
+ * Unconditionally take a reference on a user.
+ */
+void
+smb_user_hold_internal(smb_user_t *user)
+{
+ SMB_USER_VALID(user);
+
+ mutex_enter(&user->u_mutex);
+ user->u_refcnt++;
+ mutex_exit(&user->u_mutex);
+}
+
+/*
* Release a reference on a user. If the reference count falls to
* zero and the user has logged off, post the object for deletion.
* Object deletion is deferred to avoid modifying a list while an
@@ -337,9 +342,6 @@ smb_user_release(
ASSERT(user->u_refcnt);
user->u_refcnt--;
- /* flush the tree list's delete queue */
- smb_llist_flush(&user->u_tree_list);
-
switch (user->u_state) {
case SMB_USER_STATE_LOGGED_OFF:
if (user->u_refcnt == 0)
@@ -357,248 +359,6 @@ smb_user_release(
mutex_exit(&user->u_mutex);
}
-void
-smb_user_post_tree(smb_user_t *user, smb_tree_t *tree)
-{
- SMB_USER_VALID(user);
- SMB_TREE_VALID(tree);
- ASSERT(tree->t_refcnt == 0);
- ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
- ASSERT(tree->t_user == user);
-
- smb_llist_post(&user->u_tree_list, tree, smb_tree_dealloc);
-}
-
-
-/*
- * Find a tree by tree-id.
- */
-smb_tree_t *
-smb_user_lookup_tree(
- smb_user_t *user,
- uint16_t tid)
-
-{
- smb_tree_t *tree;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
-
- smb_llist_enter(&user->u_tree_list, RW_READER);
- tree = smb_llist_head(&user->u_tree_list);
-
- while (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
-
- if (tree->t_tid == tid) {
- if (smb_tree_hold(tree)) {
- smb_llist_exit(&user->u_tree_list);
- return (tree);
- } else {
- smb_llist_exit(&user->u_tree_list);
- return (NULL);
- }
- }
-
- tree = smb_llist_next(&user->u_tree_list, tree);
- }
-
- smb_llist_exit(&user->u_tree_list);
- return (NULL);
-}
-
-/*
- * Find the first connected tree that matches the specified sharename.
- * If the specified tree is NULL the search starts from the beginning of
- * the user's tree list. If a tree is provided the search starts just
- * after that tree.
- */
-smb_tree_t *
-smb_user_lookup_share(
- smb_user_t *user,
- const char *sharename,
- smb_tree_t *tree)
-{
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
- ASSERT(sharename);
-
- smb_llist_enter(&user->u_tree_list, RW_READER);
-
- if (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
- tree = smb_llist_next(&user->u_tree_list, tree);
- } else {
- tree = smb_llist_head(&user->u_tree_list);
- }
-
- while (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
- if (smb_strcasecmp(tree->t_sharename, sharename, 0) == 0) {
- if (smb_tree_hold(tree)) {
- smb_llist_exit(&user->u_tree_list);
- return (tree);
- }
- }
- tree = smb_llist_next(&user->u_tree_list, tree);
- }
-
- smb_llist_exit(&user->u_tree_list);
- return (NULL);
-}
-
-/*
- * Find the first connected tree that matches the specified volume name.
- * If the specified tree is NULL the search starts from the beginning of
- * the user's tree list. If a tree is provided the search starts just
- * after that tree.
- */
-smb_tree_t *
-smb_user_lookup_volume(
- smb_user_t *user,
- const char *name,
- smb_tree_t *tree)
-{
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
- ASSERT(name);
-
- smb_llist_enter(&user->u_tree_list, RW_READER);
-
- if (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
- tree = smb_llist_next(&user->u_tree_list, tree);
- } else {
- tree = smb_llist_head(&user->u_tree_list);
- }
-
- while (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
-
- if (smb_strcasecmp(tree->t_volume, name, 0) == 0) {
- if (smb_tree_hold(tree)) {
- smb_llist_exit(&user->u_tree_list);
- return (tree);
- }
- }
-
- tree = smb_llist_next(&user->u_tree_list, tree);
- }
-
- smb_llist_exit(&user->u_tree_list);
- return (NULL);
-}
-
-/*
- * Disconnect all trees that match the specified client process-id.
- */
-void
-smb_user_close_pid(
- smb_user_t *user,
- uint16_t pid)
-{
- smb_tree_t *tree;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
-
- tree = smb_user_get_tree(&user->u_tree_list, NULL);
- while (tree) {
- smb_tree_t *next;
- ASSERT(tree->t_user == user);
- smb_tree_close_pid(tree, pid);
- next = smb_user_get_tree(&user->u_tree_list, tree);
- smb_tree_release(tree);
- tree = next;
- }
-}
-
-/*
- * Disconnect all trees that this user has connected.
- */
-void
-smb_user_disconnect_trees(
- smb_user_t *user)
-{
- smb_tree_t *tree;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
-
- tree = smb_user_get_tree(&user->u_tree_list, NULL);
- while (tree) {
- ASSERT(tree->t_user == user);
- smb_tree_disconnect(tree, B_TRUE);
- smb_tree_release(tree);
- tree = smb_user_get_tree(&user->u_tree_list, NULL);
- }
-}
-
-/*
- * Disconnect all trees that match the specified share name.
- */
-void
-smb_user_disconnect_share(
- smb_user_t *user,
- const char *sharename)
-{
- smb_tree_t *tree;
- smb_tree_t *next;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
- ASSERT(user->u_refcnt);
-
- tree = smb_user_lookup_share(user, sharename, NULL);
- while (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- smb_session_cancel_requests(user->u_session, tree, NULL);
- smb_tree_disconnect(tree, B_TRUE);
- next = smb_user_lookup_share(user, sharename, tree);
- smb_tree_release(tree);
- tree = next;
- }
-}
-
-/*
- * Close a file by its unique id.
- */
-int
-smb_user_fclose(smb_user_t *user, uint32_t uniqid)
-{
- smb_llist_t *tree_list;
- smb_tree_t *tree;
- int rc = ENOENT;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
-
- tree_list = &user->u_tree_list;
- ASSERT(tree_list);
-
- smb_llist_enter(tree_list, RW_READER);
- tree = smb_llist_head(tree_list);
-
- while ((tree != NULL) && (rc == ENOENT)) {
- ASSERT(tree->t_user == user);
-
- if (smb_tree_hold(tree)) {
- rc = smb_tree_fclose(tree, uniqid);
- smb_tree_release(tree);
- }
-
- tree = smb_llist_next(tree_list, tree);
- }
-
- smb_llist_exit(tree_list);
- return (rc);
-}
-
/*
* Determine whether or not the user is an administrator.
* Members of the administrators group have administrative rights.
@@ -688,9 +448,7 @@ smb_user_namecmp(smb_user_t *user, const char *name)
int
smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
{
- smb_tree_t *tree;
- smb_tree_t *next;
- int rc;
+ int rc = 0;
ASSERT(user);
ASSERT(user->u_magic == SMB_USER_MAGIC);
@@ -698,21 +456,6 @@ smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
return (smb_user_enum_private(user, svcenum));
- tree = smb_user_get_tree(&user->u_tree_list, NULL);
- while (tree) {
- ASSERT(tree->t_user == user);
-
- rc = smb_tree_enum(tree, svcenum);
- if (rc != 0) {
- smb_tree_release(tree);
- break;
- }
-
- next = smb_user_get_tree(&user->u_tree_list, tree);
- smb_tree_release(tree);
- tree = next;
- }
-
return (rc);
}
@@ -769,8 +512,6 @@ smb_user_delete(void *arg)
user->u_magic = (uint32_t)~SMB_USER_MAGIC;
mutex_destroy(&user->u_mutex);
- smb_llist_destructor(&user->u_tree_list);
- smb_idpool_destructor(&user->u_tid_pool);
if (user->u_cred)
crfree(user->u_cred);
if (user->u_privcred)
@@ -780,43 +521,6 @@ smb_user_delete(void *arg)
kmem_cache_free(user->u_server->si_cache_user, user);
}
-/*
- * Get the next connected tree in the list. A reference is taken on
- * the tree, which can be released later with smb_tree_release().
- *
- * If the specified tree is NULL the search starts from the beginning of
- * the tree list. If a tree is provided the search starts just after
- * that tree.
- *
- * Returns NULL if there are no connected trees in the list.
- */
-static smb_tree_t *
-smb_user_get_tree(
- smb_llist_t *tree_list,
- smb_tree_t *tree)
-{
- ASSERT(tree_list);
-
- smb_llist_enter(tree_list, RW_READER);
-
- if (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- tree = smb_llist_next(tree_list, tree);
- } else {
- tree = smb_llist_head(tree_list);
- }
-
- while (tree) {
- if (smb_tree_hold(tree))
- break;
-
- tree = smb_llist_next(tree_list, tree);
- }
-
- smb_llist_exit(tree_list);
- return (tree);
-}
-
cred_t *
smb_user_getcred(smb_user_t *user)
{
diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c
index ba9c766c65..b4ab4ec3fd 100644
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c
@@ -363,8 +363,19 @@ dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx,
boolean_t
dsl_dataset_try_add_ref(dsl_pool_t *dp, dsl_dataset_t *ds, void *tag)
{
- return (dmu_buf_try_add_ref(ds->ds_dbuf, dp->dp_meta_objset,
- ds->ds_object, DMU_BONUS_BLKID, tag));
+ dmu_buf_t *dbuf = ds->ds_dbuf;
+ boolean_t result = B_FALSE;
+
+ if (dbuf != NULL && dmu_buf_try_add_ref(dbuf, dp->dp_meta_objset,
+ ds->ds_object, DMU_BONUS_BLKID, tag)) {
+
+ if (ds == dmu_buf_get_user(dbuf))
+ result = B_TRUE;
+ else
+ dmu_buf_rele(dbuf, tag);
+ }
+
+ return (result);
}
int