diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-04-05 12:46:44 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-04-05 12:46:44 +0000 |
commit | 7d4764a8704691712ae06535d720ae917acb4699 (patch) | |
tree | 5e93e2143f060a1eaf3377e68c06576199d912f5 /usr/src | |
parent | 414afefe58a0a3292d2689bd10360ebb4b505ca6 (diff) | |
download | illumos-joyent-7d4764a8704691712ae06535d720ae917acb4699.tar.gz |
[illumos-gate merge]
commit e89016e771abb6871cb08b54316d9a1a826a9193
9044 Need support for mpt_sas tri-mode parts
9045 Clean up mpt_sas compiler warnings
9046 mptsas_handle_topo_change can return without its locks held
9047 workaround SAS3408 firmware issue
commit 7d815089a43a963b49eaddf97e514194ec29805b
3328 smbutil view does't work with Win2008 and later
commit 3299f39fdcbdab4be7a9c70daa3873f2b78a398d
1575 untangle libmlrpc from SMB server
commit f78cdc34af236a6199dd9e21376f4a46348c0d56
9112 Improve allocation performance on high-end systems
Conflicts:
usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c
Diffstat (limited to 'usr/src')
111 files changed, 3328 insertions, 1832 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master index 2e5fd4b51b..70faac9962 100644 --- a/usr/src/Makefile.master +++ b/usr/src/Makefile.master @@ -178,6 +178,7 @@ FLEX= /usr/bin/flex YACC= /usr/ccs/bin/yacc BISON= /usr/bin/bison CPP= /usr/lib/cpp +ANSI_CPP= $(GCC_ROOT)/bin/cpp JAVAC= $(JAVA_ROOT)/bin/javac JAVAH= $(JAVA_ROOT)/bin/javah JAVADOC= $(JAVA_ROOT)/bin/javadoc diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile b/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile index 5b751cce22..e20054c772 100644 --- a/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/Makefile @@ -23,6 +23,8 @@ # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2013 Nexenta Systems, Inc. All rights reserved. +# # # cmd/fs.d/smbclnt/smbutil/Makefile @@ -30,18 +32,22 @@ PROG= smbutil -include $(SRC)/cmd/Makefile.cmd - -OBJS= smbutil.o login.o lookup.o print.o status.o view.o +OBJS= smbutil.o info.o login.o lookup.o print.o status.o view.o \ + shares_rap.o shares_rpc.o srvsvc1_clnt.o srvsvc1_ndr.o SRCS= $(OBJS:%.o=%.c) + +include $(SRC)/cmd/Makefile.cmd + POFILE= smbutil_all.po POFILES= $(OBJS:%.o=%.po) + +CLEANFILES += srvsvc1_ndr.c CLOBBERFILES+= $(POFILE) $(POFILES) CSTD= $(CSTD_GNU99) -LDLIBS += -lsmbfs -lnsl +LDLIBS += -lmlrpc -lsmbfs -lnsl CPPFLAGS += -I$(SRC)/lib/libsmbfs \ -I$(SRC)/uts/common/smbclnt -I$(SRC)/uts/common @@ -78,9 +84,12 @@ $(POFILE): $(POFILES) lint: lint_SRCS -clean : - $(RM) $(OBJS) - -.KEEP_STATE: +clean: + $(RM) $(OBJS) $(CLEANFILES) include ../../../Makefile.targ + +srvsvc1_ndr.c : srvsvc1.ndl + $(NDRGEN) -Y $(ANSI_CPP) $(CPPFLAGS) srvsvc1.ndl + +.KEEP_STATE: diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/common.h b/usr/src/cmd/fs.d/smbclnt/smbutil/common.h index 24cb1436a0..aea093c0ea 100644 --- a/usr/src/cmd/fs.d/smbclnt/smbutil/common.h +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/common.h @@ -30,6 +30,10 @@ * SUCH DAMAGE. */ +/* + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + #ifndef _SMBUTIL_COMMON_H #define _SMBUTIL_COMMON_H @@ -42,6 +46,7 @@ extern "C" { int cmd_crypt(int argc, char *argv[]); int cmd_help(int argc, char *argv[]); +int cmd_info(int argc, char *argv[]); int cmd_login(int argc, char *argv[]); int cmd_logout(int argc, char *argv[]); int cmd_logoutall(int argc, char *argv[]); @@ -50,8 +55,9 @@ int cmd_print(int argc, char *argv[]); int cmd_status(int argc, char *argv[]); int cmd_view(int argc, char *argv[]); -/* No crypt_usage? */ +void crypt_usage(void); void help_usage(void); +void info_usage(void); void login_usage(void); void logout_usage(void); void logoutall_usage(void); @@ -60,7 +66,10 @@ void print_usage(void); void status_usage(void); void view_usage(void); -extern int loadsmbvfs(); +/* See view.c */ +int share_enum_rap(struct smb_ctx *ctx); +int share_enum_rpc(struct smb_ctx *ctx, char *server); +void view_print_share(char *share, int type, char *comment); #ifdef __cplusplus } diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/info.c b/usr/src/cmd/fs.d/smbclnt/smbutil/info.c new file mode 100644 index 0000000000..600df1c1b9 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/info.c @@ -0,0 +1,212 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Show information about the remote server, as offered by + * NetServerGetInfo with SERVER_INFO_101 + */ + +#include <sys/types.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libintl.h> + +#include <libmlrpc/libmlrpc.h> +#include <netsmb/smb_lib.h> +#include "srvsvc1_clnt.h" +#include "common.h" + + +static int get_info(smb_ctx_t *); + +void +info_usage(void) +{ + printf(gettext("usage: smbutil info [connection options] //" + "[workgroup;][user[:password]@]server\n")); + exit(1); +} + +int +cmd_info(int argc, char *argv[]) +{ + struct smb_ctx *ctx; + int error, err2, opt; + + if (argc < 2) + info_usage(); + + error = smb_ctx_alloc(&ctx); + if (error) + return (error); + + error = smb_ctx_scan_argv(ctx, argc, argv, + SMBL_SERVER, SMBL_SERVER, USE_WILDCARD); + if (error) + goto out; + + error = smb_ctx_readrc(ctx); + if (error) + goto out; + + while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) { + if (opt == '?') + info_usage(); + error = smb_ctx_opt(ctx, opt, optarg); + if (error) + goto out; + } + + smb_ctx_setshare(ctx, "IPC$", USE_IPC); + + /* + * Resolve the server address, + * setup derived defaults. + */ + error = smb_ctx_resolve(ctx); + if (error) + goto out; + + /* + * Have server, share, etc. from above: + * smb_ctx_scan_argv, option settings. + * Get the session and tree. + */ +again: + error = smb_ctx_get_ssn(ctx); + if (error == EAUTH) { + err2 = smb_get_authentication(ctx); + if (err2 == 0) + goto again; + } + if (error) { + smb_error(gettext("//%s: login failed"), + error, ctx->ct_fullserver); + goto out; + } + + error = smb_ctx_get_tree(ctx); + if (error) { + smb_error(gettext("//%s/%s: tree connect failed"), + error, ctx->ct_fullserver, ctx->ct_origshare); + goto out; + } + + /* + * Have IPC$ tcon. Get the server info. + */ + error = get_info(ctx); + if (error) + smb_error("cannot get server info.", error); + +out: + smb_ctx_free(ctx); + return (error); +} + +int +get_info(smb_ctx_t *ctx) +{ + char pf_unk[32]; + mlrpc_handle_t handle; + ndr_service_t *svc; + union mslm_NetServerGetInfo_ru res; + struct mslm_SERVER_INFO_101 *sv101; + char *platform_name; + int err; + + /* + * Create an RPC handle using the smb_ctx we already have. + * Just local allocation and initialization. + */ + srvsvc1_initialize(); + svc = ndr_svc_lookup_name("srvsvc"); + if (svc == NULL) + return (ENOENT); + + err = mlrpc_clh_create(&handle, ctx); + if (err) + return (err); + + /* + * Try to bind to the RPC service. If it fails, + * just return the error and the caller will + * fall back to RAP. + */ + err = mlrpc_clh_bind(&handle, svc); + if (err) + goto out; + + err = srvsvc_net_server_getinfo(&handle, + ctx->ct_fullserver, 101, &res); + if (err) + goto out; + + sv101 = res.info101; + + switch (sv101->sv101_platform_id) { + case SV_PLATFORM_ID_DOS: + platform_name = "DOS"; + break; + case SV_PLATFORM_ID_OS2: + platform_name = "OS2"; + break; + case SV_PLATFORM_ID_NT: + platform_name = "NT"; + break; + case SV_PLATFORM_ID_OSF: + platform_name = "OSF"; + break; + case SV_PLATFORM_ID_VMS: + platform_name = "VMS"; + break; + default: + platform_name = pf_unk; + snprintf(pf_unk, sizeof (pf_unk), "(%d)", + sv101->sv101_platform_id); + break; + } + + printf("server info:\n"); + printf(" platform_id %s\n", platform_name); + printf(" vers.major %d\n", sv101->sv101_version_major); + printf(" vers.minor %d\n", sv101->sv101_version_minor); + + if (smb_verbose) + printf(" type_flags 0x%x\n", sv101->sv101_type); + + printf(" name \"%s\"\n", sv101->sv101_name); + printf(" comment \"%s\"\n", sv101->sv101_comment); + +out: + (void) mlrpc_clh_free(&handle); + return (err); +} diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rap.c b/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rap.c new file mode 100644 index 0000000000..f2235e2880 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rap.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2000-2002, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Id: view.c,v 1.9 2002/02/20 09:26:42 bp Exp + */ + +/* + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <netsmb/mchain.h> /* letohs, etc. */ +#include <netsmb/smb.h> +#include <netsmb/smb_lib.h> +#include <netsmb/smb_rap.h> + +#include "common.h" + +/* + * Enumerate shares using Remote Administration Protocol (RAP) + * Was in libsmbfs netshareenum.c + */ + +struct smb_share_info_1 { + char shi1_netname[13]; + char shi1_pad; + uint16_t shi1_type; + uint32_t shi1_remark; /* char * */ +}; + +static int +smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer, + int *cbBuffer, int *pcEntriesRead, int *pcTotalAvail) +{ + struct smb_rap *rap; + long lval = -1; + int error; + + error = smb_rap_create(0, "WrLeh", "B13BWz", &rap); + if (error) + return (error); + smb_rap_setNparam(rap, sLevel); /* W - sLevel */ + smb_rap_setPparam(rap, pbBuffer); /* r - pbBuffer */ + smb_rap_setNparam(rap, *cbBuffer); /* L - cbBuffer */ + error = smb_rap_request(rap, ctx); + if (error == 0) { + *pcEntriesRead = rap->r_entries; + error = smb_rap_getNparam(rap, &lval); + *pcTotalAvail = lval; + /* Copy the data length into the IN/OUT variable. */ + *cbBuffer = rap->r_rcvbuflen; + } + error = smb_rap_error(rap, error); + smb_rap_done(rap); + return (error); +} + +int +share_enum_rap(smb_ctx_t *ctx) +{ + struct smb_share_info_1 *shi; + void *rpbuf; + char *cp; + int error, bufsize, i, rcnt, total; + int lbound, rbound; + uint16_t type; + + bufsize = 0xffe0; /* samba notes win2k bug for 65535 */ + rpbuf = malloc(bufsize); + if (rpbuf == NULL) + return (errno); + + error = smb_rap_NetShareEnum(ctx, 1, rpbuf, &bufsize, &rcnt, &total); + if (error && + error != (ERROR_MORE_DATA | SMB_RAP_ERROR)) + goto out; + + /* + * Bounds for offsets to comments strings. + * After the array, and before the end. + */ + lbound = rcnt * (sizeof (struct smb_share_info_1)); + rbound = bufsize; + + /* Print the header line. */ + view_print_share(NULL, 0, NULL); + + for (shi = rpbuf, i = 0; i < rcnt; i++, shi++) { + type = letohs(shi->shi1_type); + + shi->shi1_pad = '\0'; /* ensure null termination */ + + /* + * Offsets to comment strings can be trash. + * Only print when the offset is valid. + */ + if (shi->shi1_remark >= lbound && + shi->shi1_remark < rbound) { + cp = (char *)rpbuf + shi->shi1_remark; + } else + cp = NULL; + + /* Convert from OEM to local codeset? */ + view_print_share(shi->shi1_netname, type, cp); + } + error = 0; + +out: + free(rpbuf); + return (error); +} diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rpc.c b/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rpc.c new file mode 100644 index 0000000000..221d6f077b --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/shares_rpc.c @@ -0,0 +1,83 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Share enumeration using Remote Procedure Call (RPC) + */ + +#include <sys/types.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libmlrpc/libmlrpc.h> +#include <netsmb/smbfs_api.h> +#include "srvsvc1_clnt.h" +#include "common.h" + +int +share_enum_rpc(struct smb_ctx *ctx, char *server) +{ + mlrpc_handle_t handle; + ndr_service_t *svc; + union mslm_NetShareEnum_ru res; + struct mslm_NetShareInfo_1 *nsi1; + int err, i, count; + + /* + * Create an RPC handle using the smb_ctx we already have. + * Just local allocation and initialization. + */ + srvsvc1_initialize(); + svc = ndr_svc_lookup_name("srvsvc"); + if (svc == NULL) + return (ENOENT); + + err = mlrpc_clh_create(&handle, ctx); + if (err) + return (err); + + /* + * Try to bind to the RPC service. If it fails, + * just return the error and the caller will + * fall back to RAP. + */ + err = mlrpc_clh_bind(&handle, svc); + if (err) + goto out; + + err = srvsvc_net_share_enum(&handle, server, 1, &res); + if (err) + goto out; + + /* Print the header line. */ + view_print_share(NULL, 0, NULL); + + /* Print the share list. */ + count = res.bufptr1->entriesread; + i = 0, nsi1 = res.bufptr1->entries; + while (i < count) { + /* Convert UTF-8 to local code set? */ + view_print_share((char *)nsi1->shi1_netname, + nsi1->shi1_type, (char *)nsi1->shi1_comment); + i++, nsi1++; + } + +out: + (void) mlrpc_clh_free(&handle); + return (err); +} diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c b/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c index 20cb3a2c86..9b09b87d64 100644 --- a/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c @@ -33,6 +33,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #include <sys/param.h> @@ -65,10 +67,11 @@ static struct commands { const char *name; cmd_fn_t *fn; cmd_usage_t *usage; - int flags; + int flags; } commands[] = { {"crypt", cmd_crypt, NULL, CMDFL_NO_KMOD}, {"help", cmd_help, help_usage, CMDFL_NO_KMOD}, + {"info", cmd_info, info_usage, 0}, {"login", cmd_login, login_usage, 0}, {"logout", cmd_logout, logout_usage, 0}, {"logoutall", cmd_logoutall, logoutall_usage, 0}, @@ -187,13 +190,14 @@ help(void) { printf(gettext("where subcommands are:\n" " crypt slightly obscure password\n" " help display help on specified subcommand\n" - /* " lc display active connections\n" */ + /* " lc display active connections\n" */ + " info display server type and version\n" " login login to specified host\n" - " logout logout from specified host\n" + " logout logout from specified host\n" " logoutall logout all users (requires privilege)\n" - " lookup resolve NetBIOS name to IP address\n" + " lookup resolve NetBIOS name to IP address\n" " print print file to the specified remote printer\n" - " status resolve IP address or DNS name to NetBIOS names\n" + " status resolve IP address or DNS name to NetBIOS names\n" " view list resources on specified host\n" "\n")); exit(1); diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1.ndl b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1.ndl new file mode 100644 index 0000000000..6712f05020 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1.ndl @@ -0,0 +1,177 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * SRVSVC - Server Service (partial) + * + * This module needs only NetShareEnum (levels 0, 1) + * and NetServerGetInfo (levels 100, 101) + */ + +#include <libmlrpc/ndrtypes.ndl> + +/* + * SRVSVC - Server Service + */ + +#define SRVSVC_OPNUM_NetShareEnum 0x0f +#define SRVSVC_OPNUM_NetServerGetInfo 0x15 + +/* + * SRVSVC NetShareEnum ( + * IN LPTSTR servername, + * IN DWORD level; + * OUT union switch(level) { + * case 0: struct { + * DWORD entriesread; + * [size_is(entriesread)] + * _SHARE_INFO_0 *entries; + * } *bufptr0; + * case 1: struct { + * DWORD entriesread; + * [size_is(entriesread)] + * _SHARE_INFO_1 *entries; + * } *bufptr1; + * ... + * } bufptr, + * IN DWORD prefmaxlen, + * OUT DWORD totalentries, + * IN OUT DWORD ?* resume_handle, + * OUT DWORD status + * ) + */ + +struct mslm_NetShareInfo_0 { + LPTSTR shi0_netname; +}; +struct mslm_NetShareInfo_0_result { + DWORD entriesread; + SIZE_IS(entriesread) + struct mslm_NetShareInfo_0 *entries; +}; + +struct mslm_NetShareInfo_1 { + LPTSTR shi1_netname; + DWORD shi1_type; /* type of resource such as IPC$ */ + LPTSTR shi1_comment; +}; +struct mslm_NetShareInfo_1_result { + DWORD entriesread; + SIZE_IS(entriesread) + struct mslm_NetShareInfo_1 *entries; +}; + +union mslm_NetShareEnum_ru { + CASE(0) struct mslm_NetShareInfo_0_result *bufptr0; + CASE(1) struct mslm_NetShareInfo_1_result *bufptr1; + DEFAULT char *nullptr; +}; +struct mslm_NetShareEnum_result { + DWORD level; + SWITCH(level) + union mslm_NetShareEnum_ru ru; +}; + + +OPERATION(SRVSVC_OPNUM_NetShareEnum) +struct mslm_NetShareEnum { + IN LPTSTR servername; + INOUT DWORD level; + INOUT struct mslm_NetShareEnum_result result; + IN DWORD prefmaxlen; + OUT DWORD totalentries; + INOUT DWORD *resume_handle; + OUT DWORD status; +}; + + +/* + * SRVSVC NetServerGetInfo ( + * IN LPTSTR servername, + * IN DWORD level, + * OUT union switch(level) { + * case 100: _SERVER_INFO_100 * p100; + * case 101: _SERVER_INFO_101 * p101; + * case 102: _SERVER_INFO_102 * p102; + * } bufptr, + * OUT DWORD status + * ) + */ + +/* for svX_platform (note: decimal!) */ +#define SV_PLATFORM_ID_DOS 300 +#define SV_PLATFORM_ID_OS2 400 +#define SV_PLATFORM_ID_NT 500 +#define SV_PLATFORM_ID_OSF 600 +#define SV_PLATFORM_ID_VMS 700 + +struct mslm_SERVER_INFO_100 { + DWORD sv100_platform_id; + LPTSTR sv100_name; +}; + +struct mslm_SERVER_INFO_101 { + DWORD sv101_platform_id; + LPTSTR sv101_name; + DWORD sv101_version_major; + DWORD sv101_version_minor; + DWORD sv101_type; + LPTSTR sv101_comment; +}; + +union mslm_NetServerGetInfo_ru { + CASE(100) struct mslm_SERVER_INFO_100 *info100; + CASE(101) struct mslm_SERVER_INFO_101 *info101; + DEFAULT char *nullptr; +}; + +struct mslm_NetServerGetInfo_result { + DWORD level; + SWITCH(level) + union mslm_NetServerGetInfo_ru ru; +}; + + +OPERATION(SRVSVC_OPNUM_NetServerGetInfo) +struct mslm_NetServerGetInfo { + IN LPTSTR servername; + IN DWORD level; + OUT struct mslm_NetServerGetInfo_result result; + OUT DWORD status; +}; + + +/* + * The SRVSVC interface + */ +INTERFACE(0) +union srvsvc_interface { + CASE(SRVSVC_OPNUM_NetShareEnum) + struct mslm_NetShareEnum NetShareEnum; + CASE(SRVSVC_OPNUM_NetServerGetInfo) + struct mslm_NetServerGetInfo NetServerGetInfo; +}; +typedef union srvsvc_interface srvsvc_interface_t; +EXTERNTYPEINFO(srvsvc_interface) diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.c b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.c new file mode 100644 index 0000000000..7ebe614ab6 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.c @@ -0,0 +1,138 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * A few excerpts from lib/smbsrv/libmlsvc + * See longer comment in srvsvc1.ndl + */ + +#include <sys/errno.h> +#include <stdio.h> +#include <time.h> +#include <strings.h> +#include <time.h> + +#include <libmlrpc/libmlrpc.h> +#include "srvsvc1_clnt.h" + +static ndr_service_t srvsvc_service = { + "SRVSVC", /* name */ + "Server services", /* desc */ + "\\srvsvc", /* endpoint */ + "\\PIPE\\ntsvcs", /* sec_addr_port */ + "4b324fc8-1670-01d3-1278-5a47bf6ee188", 3, /* abstract */ + NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ + 0, /* no bind_instance_size */ + 0, /* no bind_req() */ + 0, /* no unbind_and_close() */ + 0, /* use generic_call_stub() */ + &TYPEINFO(srvsvc_interface), /* interface_ti */ + NULL /* stub_table */ +}; + +/* + * srvsvc_initialize + * + * This function registers the SRVSVC RPC interface with the RPC runtime + * library. It must be called in order to use either the client side + * or the server side functions. + */ +void +srvsvc1_initialize(void) +{ + static int init_done; + if (init_done) + return; + init_done = 1; + (void) ndr_svc_register(&srvsvc_service); +} + +/* + * Client-side stub for NetServerGetInfo + */ +int +srvsvc_net_server_getinfo(mlrpc_handle_t *handle, char *server, + int level, union mslm_NetServerGetInfo_ru *resp) +{ + struct mslm_NetServerGetInfo arg; + int len, opnum, rc; + + opnum = SRVSVC_OPNUM_NetServerGetInfo; + bzero(&arg, sizeof (arg)); + + len = strlen(server) + 4; + arg.servername = ndr_rpc_malloc(handle, len); + if (arg.servername == NULL) + return (ENOMEM); + + (void) snprintf((char *)arg.servername, len, "\\\\%s", server); + arg.level = level; + + rc = ndr_rpc_call(handle, opnum, &arg); + if ((rc != 0) || (arg.status != 0)) + return (EIO); + + *resp = arg.result.ru; + return (0); +} + +/* + * Client-side stub for NetShareEnum + */ +int +srvsvc_net_share_enum(mlrpc_handle_t *handle, char *server, + int level, union mslm_NetShareEnum_ru *resp) +{ + /* Any enum result type is OK for nres. */ + struct mslm_NetShareInfo_0_result nres; + struct mslm_NetShareEnum arg; + int len, opnum, rc; + + opnum = SRVSVC_OPNUM_NetShareEnum; + bzero(&nres, sizeof (nres)); + bzero(&arg, sizeof (arg)); + + len = strlen(server) + 4; + arg.servername = ndr_rpc_malloc(handle, len); + if (arg.servername == NULL) + return (ENOMEM); + + (void) snprintf((char *)arg.servername, len, "\\\\%s", server); + arg.level = level; + arg.result.level = level; + arg.result.ru.bufptr0 = &nres; + arg.prefmaxlen = 0xFFFFFFFF; + arg.resume_handle = NULL; + + rc = ndr_rpc_call(handle, opnum, &arg); + if ((rc != 0) || (arg.status != 0)) + return (EIO); + + *resp = arg.result.ru; + return (0); +} diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.h b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.h new file mode 100644 index 0000000000..66e50a8ab5 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/srvsvc1_clnt.h @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SRVSVC1_CLNT_H +#define _SRVSVC1_CLNT_H + +/* + * Excerpts from lib/smbsrv/libmlsvc + * Just enough for share enumeration. + */ + +#include <libmlrpc/libmlrpc.h> +#include "srvsvc1.ndl" + +void srvsvc1_initialize(void); +int srvsvc_net_share_enum(mlrpc_handle_t *handle, char *server, + int level, union mslm_NetShareEnum_ru *resp); +int srvsvc_net_server_getinfo(mlrpc_handle_t *handle, char *server, + int level, union mslm_NetServerGetInfo_ru *resp); + +#endif /* _SRVSVC1_CLNT_H */ diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/view.c b/usr/src/cmd/fs.d/smbclnt/smbutil/view.c index baad53b00c..8622fb14be 100644 --- a/usr/src/cmd/fs.d/smbclnt/smbutil/view.c +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/view.c @@ -34,6 +34,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> @@ -48,12 +49,9 @@ #include <netsmb/smb.h> #include <netsmb/smb_lib.h> -#include <netsmb/smb_netshareenum.h> - #include "common.h" -int enum_shares(smb_ctx_t *); -void print_shares(int, int, struct share_info *); +static int use_rap; void view_usage(void) @@ -79,18 +77,27 @@ cmd_view(int argc, char *argv[]) error = smb_ctx_scan_argv(ctx, argc, argv, SMBL_SERVER, SMBL_SERVER, USE_WILDCARD); if (error) - return (error); + goto out; error = smb_ctx_readrc(ctx); if (error) - return (error); + goto out; while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) { if (opt == '?') view_usage(); + /* + * This is an undocumented option, just for testing. + * Use the old LanMan Remote API Protocol (RAP) for + * enumerating shares. + */ + if (opt == 'B') { + use_rap++; + continue; + } error = smb_ctx_opt(ctx, opt, optarg); if (error) - return (error); + goto out; } smb_ctx_setshare(ctx, "IPC$", USE_IPC); @@ -101,7 +108,7 @@ cmd_view(int argc, char *argv[]) */ error = smb_ctx_resolve(ctx); if (error) - return (error); + goto out; /* * Have server, share, etc. from above: @@ -118,24 +125,26 @@ again: if (error) { smb_error(gettext("//%s: login failed"), error, ctx->ct_fullserver); - return (error); + goto out; } error = smb_ctx_get_tree(ctx); if (error) { smb_error(gettext("//%s/%s: tree connect failed"), error, ctx->ct_fullserver, ctx->ct_origshare); - return (error); + goto out; } /* * Have IPC$ tcon, now list shares. - * This prints its own errors. + * Try RPC; if that fails, do RAP. */ - error = enum_shares(ctx); - if (error) - return (error); + if (!use_rap) + error = share_enum_rpc(ctx, ctx->ct_fullserver); + if (error || use_rap) + error = share_enum_rap(ctx); +out: smb_ctx_free(ctx); return (0); } @@ -145,7 +154,7 @@ static char *shtype[] = { gettext("disk"), gettext("printer"), gettext("device"), /* Communications device */ - gettext("IPC"), /* Inter process communication */ + gettext("IPC"), /* Inter process communication */ gettext("unknown") }; #else @@ -153,53 +162,34 @@ static char *shtype[] = { "disk", "printer", "device", /* Communications device */ - "IPC", /* IPC Inter process communication */ + "IPC", /* IPC Inter process communication */ "unknown" }; #endif -int -enum_shares(smb_ctx_t *ctx) +/* + * Print one line of the share list, or + * if SHARE is null, print the header line. + */ +void +view_print_share(char *share, int type, char *comment) { - struct share_info *share_info; - int error, entries, total; + char *stname; + int stindex; - /* - * XXX: Later, try RPC first, - * then fall back to RAP... - */ - error = smb_netshareenum(ctx, &entries, &total, &share_info); - if (error) { - smb_error(gettext("//%s failed to list shares"), - error, ctx->ct_fullserver); - return (error); + if (share == NULL) { + printf(gettext("Share Type Comment\n")); + printf("-------------------------------\n"); + return; } - print_shares(entries, total, share_info); - return (0); -} -void -print_shares(int entries, int total, - struct share_info *share_info) -{ - struct share_info *ep; - int i; - - printf(gettext("Share Type Comment\n")); - printf("-------------------------------\n"); - - for (ep = share_info, i = 0; i < entries; i++, ep++) { - int sti = ep->type & STYPE_MASK; - if (sti > STYPE_UNKNOWN) - sti = STYPE_UNKNOWN; - printf("%-12s %-10s %s\n", ep->netname, - gettext(shtype[sti]), - ep->remark ? ep->remark : ""); - free(ep->netname); - free(ep->remark); - } - printf(gettext("\n%d shares listed from %d available\n"), - entries, total); + stindex = type & STYPE_MASK; + if (stindex > STYPE_UNKNOWN) + stindex = STYPE_UNKNOWN; + stname = gettext(shtype[stindex]); + + if (comment == NULL) + comment = ""; - free(share_info); + printf("%-12s %-10s %s\n", share, stname, comment); } diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c index 5d3af7ff3c..ad66d688ea 100644 --- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c +++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c @@ -21,8 +21,8 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2017, Joyent, Inc. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -1727,6 +1727,7 @@ typedef struct mdb_metaslab_alloc_trace { uint64_t mat_weight; uint64_t mat_offset; uint32_t mat_dva_id; + int mat_allocator; } mdb_metaslab_alloc_trace_t; static void @@ -1799,8 +1800,9 @@ metaslab_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags)) { - mdb_printf("%<u>%6s %6s %8s %11s %18s %18s%</u>\n", - "MSID", "DVA", "ASIZE", "WEIGHT", "RESULT", "VDEV"); + mdb_printf("%<u>%6s %6s %8s %11s %11s %18s %18s%</u>\n", + "MSID", "DVA", "ASIZE", "ALLOCATOR", "WEIGHT", "RESULT", + "VDEV"); } if (mat.mat_msp != NULL) { @@ -1815,7 +1817,8 @@ metaslab_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf("%6s ", "-"); } - mdb_printf("%6d %8llx ", mat.mat_dva_id, mat.mat_size); + mdb_printf("%6d %8llx %11llx ", mat.mat_dva_id, mat.mat_size, + mat.mat_allocator); metaslab_print_weight(mat.mat_weight); diff --git a/usr/src/common/smbsrv/smb_door_legacy.c b/usr/src/common/smbsrv/smb_door_legacy.c index 985b83eb7a..ae1e557db8 100644 --- a/usr/src/common/smbsrv/smb_door_legacy.c +++ b/usr/src/common/smbsrv/smb_door_legacy.c @@ -39,7 +39,7 @@ #include <sys/errno.h> #endif -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #include <smbsrv/smb_share.h> #include <smbsrv/smb_door.h> #include <smbsrv/alloc.h> diff --git a/usr/src/common/smbsrv/smb_token_xdr.c b/usr/src/common/smbsrv/smb_token_xdr.c index fdad7ed5ca..b2f5a92352 100644 --- a/usr/src/common/smbsrv/smb_token_xdr.c +++ b/usr/src/common/smbsrv/smb_token_xdr.c @@ -32,7 +32,7 @@ #if !defined(_KERNEL) && !defined(_FAKE_KERNEL) #include <stdlib.h> #endif /* !_KERNEL */ -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #include <smbsrv/smb_sid.h> #include <smbsrv/smb_xdr.h> #include <smbsrv/smb_token.h> diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 0054c41e6d..445238f973 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -166,6 +166,7 @@ SUBDIRS += \ libmapid \ libmapmalloc \ libmd5 \ + libmlrpc \ libmtmalloc \ libmvec \ libndmp \ @@ -432,6 +433,7 @@ HDRSUBDIRS= \ libmail \ libmapid \ libmd \ + libmlrpc \ libmtmalloc \ libndmp \ libnsctl \ @@ -642,6 +644,7 @@ libkmf: libcryptoutil pkcs11 libkvm: ../cmd/sgs/libelf libldap5: libsasl libmapid: libresolv2 libscf +libmlrpc: libsmbfs libuuid libndmp: libscf libnisdb: libldap5 libnwam: libscf libbsm libdladm libipadm @@ -714,7 +717,7 @@ sasl_plugins: pkcs11 libgss libsasl scsi: libfru libumem libdevid libdevinfo smbsrv: libxnet libpthread librt libshare libidmap pkcs11 libsqlite \ libcryptoutil libreparse libcmdutils libresolv2 libsmbfs \ - libuuid libfakekernel libads libgss libldap5 krb5 + libuuid libfakekernel libads libgss libldap5 krb5 libmlrpc storage: libdevice libdevinfo libdevid sun_fc: libdevinfo libsysevent sun_sas: libdevinfo libsysevent libkstat libdevid diff --git a/usr/src/lib/libmlrpc/Makefile b/usr/src/lib/libmlrpc/Makefile new file mode 100644 index 0000000000..ae458ebc7a --- /dev/null +++ b/usr/src/lib/libmlrpc/Makefile @@ -0,0 +1,65 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2013 Nexenta Systems, Inc. All rights reserved. +# + +include $(SRC)/lib/Makefile.lib + +HDRS= libmlrpc.h ndr.h ndrtypes.ndl rpcpdu.ndl +HDRDIR= common + +ROOTHDRDIR= $(ROOT)/usr/include/libmlrpc +ROOTHDRS= $(HDRS:%=$(ROOTHDRDIR)/%) + +# ISA targets +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET = all +install := TARGET = install +clean := TARGET = clean +clobber := TARGET = clobber +lint := TARGET = lint + +.KEEP_STATE: + +all install clean clobber lint: $(SUBDIRS) + +install_h: $(ROOTHDRDIR) $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(ROOTHDRDIR)/%: % + $(INS.file) + +$(ROOTHDRDIR): + $(INS.dir) + +$(SUBDIRS): FRC + @cd $@; pwd; VERSION='$(VERSION)' $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/smbsrv/libmlrpc/Makefile.com b/usr/src/lib/libmlrpc/Makefile.com index fa45211464..1a2ecb4ddd 100644 --- a/usr/src/lib/smbsrv/libmlrpc/Makefile.com +++ b/usr/src/lib/libmlrpc/Makefile.com @@ -18,39 +18,58 @@ # # CDDL HEADER END # + # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2013 Nexenta Systems, Inc. All rights reserved. +# LIBRARY = libmlrpc.a -VERS = .1 +VERS = .2 -OBJS_COMMON = \ +OBJS_COMMON = \ + mlrpc_clh.o \ ndr_client.o \ ndr_heap.o \ ndr_marshal.o \ ndr_ops.o \ ndr_process.o \ ndr_server.o \ - ndr_svc.o + ndr_svc.o \ + ndr_wchar.o NDLLIST = rpcpdu -OBJECTS= $(OBJS_COMMON) $(OBJS_SHARED) $(NDLLIST:%=%_ndr.o) +OBJECTS= $(OBJS_COMMON) $(NDLLIST:%=%_ndr.o) +CLEANFILES += $(NDLLIST:%=%_ndr.c) -include ../../../Makefile.lib include ../../Makefile.lib -INCS += -I$(SRC)/common/smbsrv +LIBS= $(DYNLIB) $(LINTLIB) + +LDLIBS += -lsmbfs -luuid -lc + +SRCDIR= ../common +SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) -LDLIBS += $(MACH_LDLIBS) -LDLIBS += -lsmb -luuid -lc +NDLDIR = $(SRCDIR) +CFLAGS += $(CCVERBOSE) +INCS = -I. -I$(SRCDIR) CPPFLAGS += $(INCS) -D_REENTRANT -SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \ - $(OBJS_SHARED:%.o=$(SRC)/common/smbsrv/%.c) +all: $(LIBS) + +lint: lintcheck include ../../Makefile.targ -include ../../../Makefile.targ + +objs/%_ndr.o pics/%_ndr.o : %_ndr.c + +%_ndr.c : $(NDLDIR)/%.ndl + $(NDRGEN) -Y $(ANSI_CPP) $(CPPFLAGS) $< + +.KEEP_STATE: diff --git a/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile b/usr/src/lib/libmlrpc/amd64/Makefile index b3c4916b0c..087f0e1107 100644 --- a/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile +++ b/usr/src/lib/libmlrpc/amd64/Makefile @@ -22,14 +22,10 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) include ../Makefile.com -include ../../../Makefile.lib.64 - -DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) +include ../../Makefile.lib.64 install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h b/usr/src/lib/libmlrpc/common/libmlrpc.h index 5b55ce4c54..d020532cbe 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h +++ b/usr/src/lib/libmlrpc/common/libmlrpc.h @@ -28,10 +28,9 @@ #include <sys/types.h> #include <sys/uio.h> -#include <smbsrv/wintypes.h> -#include <smbsrv/ndr.h> -#include <smbsrv/smb_sid.h> -#include <smbsrv/smb_xdr.h> + +#include <smb/wintypes.h> +#include <libmlrpc/ndr.h> #ifdef __cplusplus extern "C" { @@ -247,9 +246,9 @@ typedef struct ndr_binding { #define NDR_N_BINDING_POOL 2 typedef struct ndr_pipe { - void *np_listener; + void *np_listener; const char *np_endpoint; - smb_netuserinfo_t *np_user; + struct smb_netuserinfo *np_user; int (*np_send)(struct ndr_pipe *, void *, size_t); int (*np_recv)(struct ndr_pipe *, void *, size_t); int np_fid; @@ -402,12 +401,12 @@ typedef struct ndr_vcbuf { ndr_heap_t *ndr_heap_create(void); void ndr_heap_destroy(ndr_heap_t *); +void *ndr_heap_dupmem(ndr_heap_t *, const void *, size_t); void *ndr_heap_malloc(ndr_heap_t *, unsigned); void *ndr_heap_strdup(ndr_heap_t *, const char *); int ndr_heap_mstring(ndr_heap_t *, const char *, ndr_mstring_t *); void ndr_heap_mkvcs(ndr_heap_t *, char *, ndr_vcstr_t *); void ndr_heap_mkvcb(ndr_heap_t *, uint8_t *, uint32_t, ndr_vcbuf_t *); -smb_sid_t *ndr_heap_siddup(ndr_heap_t *, smb_sid_t *); int ndr_heap_used(ndr_heap_t *); int ndr_heap_avail(ndr_heap_t *); @@ -416,7 +415,7 @@ int ndr_heap_avail(ndr_heap_t *); #define NDR_NEWN(XA, T, N) ndr_heap_malloc((XA)->heap, sizeof (T)*(N)) #define NDR_STRDUP(XA, S) ndr_heap_strdup((XA)->heap, (S)) #define NDR_MSTRING(XA, S, OUT) ndr_heap_mstring((XA)->heap, (S), (OUT)) -#define NDR_SIDDUP(XA, S) ndr_heap_siddup((XA)->heap, (S)) +#define NDR_SIDDUP(XA, S) ndr_heap_dupmem((XA)->heap, (S), smb_sid_len(S)) typedef struct ndr_xa { unsigned short ptype; /* high bits special */ @@ -488,7 +487,7 @@ void nds_destruct(ndr_stream_t *); void nds_show_state(ndr_stream_t *); /* ndr_client.c */ -int ndr_clnt_bind(ndr_client_t *, const char *, ndr_binding_t **); +int ndr_clnt_bind(ndr_client_t *, ndr_service_t *, ndr_binding_t **); int ndr_clnt_call(ndr_binding_t *, int, void *); void ndr_clnt_free_heap(ndr_client_t *); @@ -514,10 +513,6 @@ void ndr_pipe_worker(ndr_pipe_t *); int ndr_generic_call_stub(ndr_xa_t *); -boolean_t ndr_is_admin(ndr_xa_t *); -boolean_t ndr_is_poweruser(ndr_xa_t *); -int32_t ndr_native_os(ndr_xa_t *); - /* ndr_svc.c */ ndr_stub_table_t *ndr_svc_find_stub(ndr_service_t *, int); ndr_service_t *ndr_svc_lookup_name(const char *); @@ -538,6 +533,38 @@ void ndr_hdclose(ndr_pipe_t *); ssize_t ndr_uiomove(caddr_t, size_t, enum uio_rw, struct uio *); +/* + * An ndr_client_t is created while binding a client connection to hold + * the context for calls made using that connection. + * + * Handles are RPC call specific and we use an inheritance mechanism to + * ensure that each handle has a pointer to the client_t. When the top + * level (bind) handle is released, we close the connection. + * + * There are some places in libmlsvc where the code assumes that the + * handle member is first in this struct. careful + */ +typedef struct mlrpc_handle { + ndr_hdid_t handle; /* keep first */ + ndr_client_t *clnt; +} mlrpc_handle_t; + +int mlrpc_clh_create(mlrpc_handle_t *, void *); +uint32_t mlrpc_clh_bind(mlrpc_handle_t *, ndr_service_t *); +void mlrpc_clh_unbind(mlrpc_handle_t *); +void *mlrpc_clh_free(mlrpc_handle_t *); + +int ndr_rpc_call(mlrpc_handle_t *, int, void *); +int ndr_rpc_get_ssnkey(mlrpc_handle_t *, unsigned char *, size_t); +void *ndr_rpc_malloc(mlrpc_handle_t *, size_t); +ndr_heap_t *ndr_rpc_get_heap(mlrpc_handle_t *); +void ndr_rpc_release(mlrpc_handle_t *); +void ndr_rpc_set_nonull(mlrpc_handle_t *); + +boolean_t ndr_is_null_handle(mlrpc_handle_t *); +boolean_t ndr_is_bind_handle(mlrpc_handle_t *); +void ndr_inherit_handle(mlrpc_handle_t *, mlrpc_handle_t *); + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/smbsrv/libmlrpc/common/llib-lmlrpc b/usr/src/lib/libmlrpc/common/llib-lmlrpc index 1621e3c2f6..3345e6129a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/llib-lmlrpc +++ b/usr/src/lib/libmlrpc/common/llib-lmlrpc @@ -21,11 +21,11 @@ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /*LINTLIBRARY*/ /*PROTOLIB1*/ -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers b/usr/src/lib/libmlrpc/common/mapfile-vers index 5822d32711..241d8309d0 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers +++ b/usr/src/lib/libmlrpc/common/mapfile-vers @@ -42,47 +42,74 @@ $mapfile_version 2 SYMBOL_VERSION SUNWprivate { global: - ndr_buf_decode; - ndr_buf_fini; - ndr_buf_init; - ndr_clnt_bind; - ndr_clnt_call; - ndr_clnt_free_heap; + mlrpc_clh_bind; + mlrpc_clh_create; + mlrpc_clh_free; + mlrpc_clh_unbind; + + # Allow debug/test programs to provide these. + ndo_printf { FLAGS = NODIRECT }; + ndo_trace { FLAGS = NODIRECT }; + + ndr_buf_decode; + ndr_buf_fini; + ndr_buf_init; + ndr_clnt_bind; + ndr_clnt_call; + ndr_clnt_free_heap; ndr_generic_call_stub; - ndr_heap_avail; - ndr_heap_create; - ndr_heap_destroy; - ndr_heap_malloc; - ndr_heap_mkvcb; - ndr_heap_mkvcs; + ndr_heap_avail; + ndr_heap_create; + ndr_heap_destroy; + ndr_heap_dupmem; + ndr_heap_malloc; + ndr_heap_mkvcb; + ndr_heap_mkvcs; ndr_heap_mstring; - ndr_heap_siddup; - ndr_heap_strdup; - ndr_heap_used; + ndr_heap_strdup; + ndr_heap_used; ndr_hdalloc; + ndr_hdclose; ndr_hdfree; ndr_hdlookup; - ndr_inner; - ndr_is_admin; - ndr_is_poweruser; + ndr_inherit_handle; + ndr_inner; + ndr_is_bind_handle; + ndr_is_null_handle; ndr_mbstowcs; - ndr_mbtowc; - ndr_native_os; - ndr_params; + ndr_params; ndr_pipe_worker; - ndr_svc_binding_pool_init; + ndr_rpc_call; + ndr_rpc_get_heap; + ndr_rpc_get_ssnkey; + ndr_rpc_malloc; + ndr_rpc_release; + ndr_rpc_set_nonull; + ndr_svc_binding_pool_init; ndr_svc_lookup_name; - ndr_svc_register; - ndr_topmost; + ndr_svc_register; + ndr_topmost; ndr_uuid_parse; ndr_uuid_unparse; - nds_destruct; - nds_initialize; - ndt__char; - ndt_s_wchar; - ndt__uchar; - ndt__ulong; - ndt__ushort; + + nds_destruct; + nds_initialize; + + ndt__char; + ndt_s_char; + ndt__uchar; + ndt_s_uchar; + ndt__wchar; + ndt_s_wchar; + ndt__short; + ndt_s_short; + ndt__ushort; + ndt_s_ushort; + ndt__long; + ndt_s_long; + ndt__ulong; + ndt_s_ulong; + local: *; }; diff --git a/usr/src/lib/libmlrpc/common/mlrpc_clh.c b/usr/src/lib/libmlrpc/common/mlrpc_clh.c new file mode 100644 index 0000000000..72c051d675 --- /dev/null +++ b/usr/src/lib/libmlrpc/common/mlrpc_clh.c @@ -0,0 +1,578 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * ML-RPC Client handle interface and support functions. + */ + +#include <sys/types.h> +#include <sys/fcntl.h> +#include <sys/poll.h> + +#include <errno.h> +#include <strings.h> +#include <unistd.h> + +#include <netsmb/smbfs_api.h> +#include <smb/ntstatus.h> +#include <libmlrpc.h> + +#include <assert.h> + +static int ndr_xa_init(ndr_client_t *, ndr_xa_t *); +static int ndr_xa_exchange(ndr_client_t *, ndr_xa_t *); +static int ndr_xa_read(ndr_client_t *, ndr_xa_t *); +static void ndr_xa_preserve(ndr_client_t *, ndr_xa_t *); +static void ndr_xa_destruct(ndr_client_t *, ndr_xa_t *); +static void ndr_xa_release(ndr_client_t *); + +/* See notes in mlrpc_clh_bind */ +int rpc_pipe_open_retries = 10; + +/* + * Create an RPC client binding handle using the given smb_ctx. + * That context must already have a session and tree connected. + * + * Returns zero or an errno value. + */ +int +mlrpc_clh_create(mlrpc_handle_t *handle, void *ctx) +{ + ndr_client_t *clnt = NULL; + + if (ctx == NULL) + return (EINVAL); + + /* + * Allocate... + */ + if ((clnt = malloc(sizeof (*clnt))) == NULL) + return (ENOMEM); + bzero(clnt, sizeof (*clnt)); + + clnt->xa_fd = -1; + + /* + * Setup the transport functions. + * Always a named pipe (for now). + */ + clnt->xa_private = ctx; + clnt->xa_init = ndr_xa_init; + clnt->xa_exchange = ndr_xa_exchange; + clnt->xa_read = ndr_xa_read; + clnt->xa_preserve = ndr_xa_preserve; + clnt->xa_destruct = ndr_xa_destruct; + clnt->xa_release = ndr_xa_release; + + /* See _is_bind_handle */ + clnt->handle = &handle->handle; + + ndr_svc_binding_pool_init(&clnt->binding_list, + clnt->binding_pool, NDR_N_BINDING_POOL); + + if ((clnt->heap = ndr_heap_create()) == NULL) + goto nomem; + + /* success! */ + bzero(handle, sizeof (*handle)); + handle->clnt = clnt; + return (0); + +nomem: + free(clnt); + return (ENOMEM); +} + + +/* + * This call must be made to initialize an RPC client structure and bind + * to the remote service before any RPCs can be exchanged with that service. + * + * The mlrpc_handle_t is a wrapper that is used to associate an RPC handle + * with the client context for an instance of the interface. The handle + * is zeroed to ensure that it doesn't look like a valid handle - + * handle content is provided by the remove service. + * + * The client points to this top-level handle so that we know when to + * unbind and teardown the connection. As each handle is initialized it + * will inherit a reference to the client context. + * + * + * Similar to MSRPC RpcBindingBind() + * + * Returns 0 or an NT_STATUS: (failed in...) + * + * RPC_NT_SERVER_TOO_BUSY (open pipe) + * RPC_NT_SERVER_UNAVAILABLE (open pipe) + * NT_STATUS_ACCESS_DENIED (open pipe) + * NT_STATUS_INVALID_PARAMETER (rpc bind) + * NT_STATUS_INTERNAL_ERROR (bad args etc) + * NT_STATUS_NO_MEMORY + */ +uint32_t +mlrpc_clh_bind(mlrpc_handle_t *handle, ndr_service_t *svc) +{ + ndr_client_t *clnt = NULL; + struct smb_ctx *ctx = NULL; + uint32_t status = 0; + int fd = -1; + int rc, retries; + + if ((clnt = handle->clnt) == NULL) + return (NT_STATUS_INTERNAL_ERROR); + if ((ctx = clnt->xa_private) == NULL) + return (NT_STATUS_INTERNAL_ERROR); + if (clnt->xa_fd != -1) + return (NT_STATUS_INTERNAL_ERROR); + + /* + * Open the named pipe. + * + * Sometimes a DC may return NT_STATUS_PIPE_NOT_AVAILABLE for + * the first few seconds during service auto-start. The client + * translates that to EBUSY, so when we see that, wait a bit + * and retry the open for up to rpc_pipe_open_retries. If we + * fail even after retries, return RPC_NT_SERVER_TOO_BUSY, + * which is how callers of this layer expect that reported. + * We try up to 10 times, with a 0.5 sec. wait after each + * BUSY failure, giving a total wait here of 5 sec. + */ + retries = rpc_pipe_open_retries; +retry_open: + fd = smb_fh_open(ctx, svc->endpoint, O_RDWR); + if (fd < 0) { + rc = errno; + switch (rc) { + case EBUSY: + if (--retries > 0) { + (void) poll(NULL, 0, 500); + goto retry_open; + } + status = RPC_NT_SERVER_TOO_BUSY; + break; + case EACCES: + status = NT_STATUS_ACCESS_DENIED; + break; + default: + status = RPC_NT_SERVER_UNAVAILABLE; + break; + } + return (status); + } + + clnt->xa_fd = fd; + + /* Paranoia, in case of re-bind. */ + bzero(&handle->handle, sizeof (ndr_hdid_t)); + + /* + * Do the OtW RPC bind. + */ + rc = ndr_clnt_bind(clnt, svc, &clnt->binding); + switch (rc) { + case NDR_DRC_FAULT_OUT_OF_MEMORY: + status = NT_STATUS_NO_MEMORY; + break; + case NDR_DRC_FAULT_API_SERVICE_INVALID: + /* svc->..._uuid parse errors */ + status = NT_STATUS_INTERNAL_ERROR; + break; + default: + if (NDR_DRC_IS_FAULT(rc)) { + status = RPC_NT_PROTOCOL_ERROR; + break; + } + /* FALLTHROUGH */ + case NDR_DRC_OK: + status = NT_STATUS_SUCCESS; + } + + if (status != 0) { + if (fd != -1) + (void) smb_fh_close(fd); + clnt->xa_fd = -1; + } + + return (status); +} + +/* + * Unbind and close the pipe to an RPC service. + * + * Similar to MSRPC RpcBindingUnbind() + * This should be called after a dropped connection. + */ +void +mlrpc_clh_unbind(mlrpc_handle_t *handle) +{ + ndr_client_t *clnt = handle->clnt; + + if (clnt->xa_fd != -1) { + (void) smb_fh_close(clnt->xa_fd); + clnt->xa_fd = -1; + } +} + +/* + * If the heap has been preserved we need to go through an xa release. + * The heap is preserved during an RPC call because that's where data + * returned from the server is stored. + * + * Otherwise we destroy the heap directly. + * + * Returns the xa_private pointer (if non-NULL) to inform the caller + * that it can now be destroyed. + */ +void * +mlrpc_clh_free(mlrpc_handle_t *handle) +{ + ndr_client_t *clnt = handle->clnt; + void *private; + + if (clnt == NULL) + return (NULL); + + /* + * Should never get an unbind on inherited handles. + * Callers of ndr_inherit_handle() check handles + * with ndr_is_bind_handle() before calling this. + * + * Maybe make this function more tolerant? + */ + assert(handle->clnt->handle == &handle->handle); + + mlrpc_clh_unbind(handle); + + if (clnt->heap_preserved) + ndr_clnt_free_heap(clnt); /* xa_release */ + else + ndr_heap_destroy(clnt->heap); + + /* + * Note: Caller will free the smb_ctx stored in + * clnt->xa_private (or possibly reuse it). + */ + private = clnt->xa_private; + free(clnt); + bzero(handle, sizeof (*handle)); + return (private); +} + +/* + * Call the RPC function identified by opnum. The remote service is + * identified by the handle, which should have been initialized by + * ndr_rpc_bind. + * + * If the RPC call is successful (returns 0), the caller must call + * ndr_rpc_release to release the heap. Otherwise, we release the + * heap here. + */ +int +ndr_rpc_call(mlrpc_handle_t *handle, int opnum, void *params) +{ + ndr_client_t *clnt = handle->clnt; + int rc; + + if (ndr_rpc_get_heap(handle) == NULL) + return (-1); + + rc = ndr_clnt_call(clnt->binding, opnum, params); + + /* + * Always clear the nonull flag to ensure + * it is not applied to subsequent calls. + */ + clnt->nonull = B_FALSE; + + if (NDR_DRC_IS_FAULT(rc)) { + ndr_rpc_release(handle); + return (-1); + } + + return (0); +} + +/* + * Outgoing strings should not be null terminated. + */ +void +ndr_rpc_set_nonull(mlrpc_handle_t *handle) +{ + handle->clnt->nonull = B_TRUE; +} + +/* + * Get the session key from a bound RPC client handle. + * + * The key returned is the 16-byte "user session key" + * established by the underlying authentication protocol + * (either Kerberos or NTLM). This key is needed for + * SAM RPC calls such as SamrSetInformationUser, etc. + * See [MS-SAMR] sections: 2.2.3.3, 2.2.7.21, 2.2.7.25. + * + * Returns zero (success) or an errno. + */ +int +ndr_rpc_get_ssnkey(mlrpc_handle_t *handle, uchar_t *key, size_t len) +{ + ndr_client_t *clnt = handle->clnt; + + if (clnt == NULL || clnt->xa_fd == -1) + return (EINVAL); + + return (smb_fh_getssnkey(clnt->xa_fd, key, len)); +} + +void * +ndr_rpc_malloc(mlrpc_handle_t *handle, size_t size) +{ + ndr_heap_t *heap; + + if ((heap = ndr_rpc_get_heap(handle)) == NULL) + return (NULL); + + return (ndr_heap_malloc(heap, size)); +} + +ndr_heap_t * +ndr_rpc_get_heap(mlrpc_handle_t *handle) +{ + ndr_client_t *clnt = handle->clnt; + + if (clnt->heap == NULL) + clnt->heap = ndr_heap_create(); + + return (clnt->heap); +} + +/* + * Must be called by RPC clients to free the heap after a successful RPC + * call, i.e. ndr_rpc_call returned 0. The caller should take a copy + * of any data returned by the RPC prior to calling this function because + * returned data is in the heap. + */ +void +ndr_rpc_release(mlrpc_handle_t *handle) +{ + ndr_client_t *clnt = handle->clnt; + + if (clnt->heap_preserved) + ndr_clnt_free_heap(clnt); + else + ndr_heap_destroy(clnt->heap); + + clnt->heap = NULL; +} + +/* + * Returns true if the handle is null. + * Otherwise returns false. + */ +boolean_t +ndr_is_null_handle(mlrpc_handle_t *handle) +{ + static const ndr_hdid_t hdid0 = {0}; + + if (handle == NULL || handle->clnt == NULL) + return (B_TRUE); + + if (!memcmp(&handle->handle, &hdid0, sizeof (hdid0))) + return (B_TRUE); + + return (B_FALSE); +} + +/* + * Returns true if the handle is the top level bind handle. + * Otherwise returns false. + */ +boolean_t +ndr_is_bind_handle(mlrpc_handle_t *handle) +{ + return (handle->clnt->handle == &handle->handle); +} + +/* + * Pass the client reference from parent to child. + */ +void +ndr_inherit_handle(mlrpc_handle_t *child, mlrpc_handle_t *parent) +{ + child->clnt = parent->clnt; +} + +/* + * ndr_rpc_status remains in libmlsvc mlsvc_client.c + */ + +/* + * The following functions provide the client callback interface. + * If the caller hasn't provided a heap, create one here. + */ +static int +ndr_xa_init(ndr_client_t *clnt, ndr_xa_t *mxa) +{ + ndr_stream_t *recv_nds = &mxa->recv_nds; + ndr_stream_t *send_nds = &mxa->send_nds; + ndr_heap_t *heap = clnt->heap; + int rc; + + if (heap == NULL) { + if ((heap = ndr_heap_create()) == NULL) + return (-1); + + clnt->heap = heap; + } + + mxa->heap = heap; + + rc = nds_initialize(send_nds, 0, NDR_MODE_CALL_SEND, heap); + if (rc == 0) + rc = nds_initialize(recv_nds, NDR_PDU_SIZE_HINT_DEFAULT, + NDR_MODE_RETURN_RECV, heap); + + if (rc != 0) { + nds_destruct(&mxa->recv_nds); + nds_destruct(&mxa->send_nds); + ndr_heap_destroy(mxa->heap); + mxa->heap = NULL; + clnt->heap = NULL; + return (-1); + } + + if (clnt->nonull) + NDS_SETF(send_nds, NDS_F_NONULL); + + return (0); +} + +/* + * This is the entry pointy for an RPC client call exchange with + * a server, which will result in an smbrdr SmbTransact request. + * + * SmbTransact should return the number of bytes received, which + * we record as the PDU size, or a negative error code. + */ +static int +ndr_xa_exchange(ndr_client_t *clnt, ndr_xa_t *mxa) +{ + ndr_stream_t *recv_nds = &mxa->recv_nds; + ndr_stream_t *send_nds = &mxa->send_nds; + int err, more, nbytes; + + nbytes = recv_nds->pdu_max_size; + err = smb_fh_xactnp(clnt->xa_fd, + send_nds->pdu_size, (char *)send_nds->pdu_base_offset, + &nbytes, (char *)recv_nds->pdu_base_offset, &more); + if (err) { + recv_nds->pdu_size = 0; + return (-1); + } + + recv_nds->pdu_size = nbytes; + return (0); +} + +/* + * This entry point will be invoked if the xa-exchange response contained + * only the first fragment of a multi-fragment response. The RPC client + * code will then make repeated xa-read requests to obtain the remaining + * fragments, which will result in smbrdr SmbReadX requests. + * + * SmbReadX should return the number of bytes received, in which case we + * expand the PDU size to include the received data, or a negative error + * code. + */ +static int +ndr_xa_read(ndr_client_t *clnt, ndr_xa_t *mxa) +{ + ndr_stream_t *nds = &mxa->recv_nds; + int len; + int nbytes; + + if ((len = (nds->pdu_max_size - nds->pdu_size)) < 0) + return (-1); + + nbytes = smb_fh_read(clnt->xa_fd, 0, len, + (char *)nds->pdu_base_offset + nds->pdu_size); + + if (nbytes < 0) + return (-1); + + nds->pdu_size += nbytes; + + if (nds->pdu_size > nds->pdu_max_size) { + nds->pdu_size = nds->pdu_max_size; + return (-1); + } + + return (nbytes); +} + +/* + * Preserve the heap so that the client application has access to data + * returned from the server after an RPC call. + */ +static void +ndr_xa_preserve(ndr_client_t *clnt, ndr_xa_t *mxa) +{ + assert(clnt->heap == mxa->heap); + + clnt->heap_preserved = B_TRUE; + mxa->heap = NULL; +} + +/* + * Dispose of the transaction streams. If the heap has not been + * preserved, we can destroy it here. + */ +static void +ndr_xa_destruct(ndr_client_t *clnt, ndr_xa_t *mxa) +{ + nds_destruct(&mxa->recv_nds); + nds_destruct(&mxa->send_nds); + + if (!clnt->heap_preserved) { + ndr_heap_destroy(mxa->heap); + mxa->heap = NULL; + clnt->heap = NULL; + } +} + +/* + * Dispose of a preserved heap. + */ +static void +ndr_xa_release(ndr_client_t *clnt) +{ + if (clnt->heap_preserved) { + ndr_heap_destroy(clnt->heap); + clnt->heap = NULL; + clnt->heap_preserved = B_FALSE; + } +} diff --git a/usr/src/uts/common/smbsrv/ndr.h b/usr/src/lib/libmlrpc/common/ndr.h index 584c0798e4..f6af9a22cf 100644 --- a/usr/src/uts/common/smbsrv/ndr.h +++ b/usr/src/lib/libmlrpc/common/ndr.h @@ -40,18 +40,14 @@ * ogspecs@opengroup.org */ -#if defined(_KERNEL) || defined(_FAKE_KERNEL) -#error "not used in kernel code" -#else /* _KERNEL */ #include <sys/types.h> #include <sys/uio.h> -#include <syslog.h> #include <stdlib.h> #include <string.h> -#include <smbsrv/wintypes.h> -#include <smbsrv/ndl/rpcpdu.ndl> -#include <smbsrv/string.h> -#endif /* _KERNEL */ + +#include <smb/wintypes.h> +#include <libmlrpc/ndrtypes.ndl> +#include <libmlrpc/rpcpdu.ndl> #ifdef __cplusplus extern "C" { @@ -455,8 +451,7 @@ int ndr_inner_pointer(ndr_ref_t *); int ndr_inner_reference(ndr_ref_t *); int ndr_inner_array(ndr_ref_t *); -size_t ndr_mbstowcs(struct ndr_stream *, smb_wchar_t *, const char *, size_t); -int ndr_mbtowc(struct ndr_stream *, smb_wchar_t *, const char *, size_t); +size_t ndr_mbstowcs(struct ndr_stream *, ndr_wchar_t *, const char *, size_t); void nds_bswap(void *src, void *dst, size_t len); diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c b/usr/src/lib/libmlrpc/common/ndr_client.c index 7aaa35e6b5..56cc1847ef 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c +++ b/usr/src/lib/libmlrpc/common/ndr_client.c @@ -21,14 +21,15 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #include <sys/errno.h> #include <string.h> #include <strings.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> #define NDR_DEFAULT_FRAGSZ 8192 #define NDR_MULTI_FRAGSZ (60 * 1024) @@ -38,24 +39,19 @@ static int ndr_clnt_get_frags(ndr_client_t *, ndr_xa_t *); static int ndr_clnt_get_frag(ndr_client_t *, ndr_xa_t *, ndr_common_header_t *); int -ndr_clnt_bind(ndr_client_t *clnt, const char *service_name, +ndr_clnt_bind(ndr_client_t *clnt, ndr_service_t *msvc, ndr_binding_t **ret_binding_p) { - ndr_service_t *msvc; ndr_binding_t *mbind; ndr_xa_t mxa; ndr_bind_hdr_t *bhdr; - ndr_p_cont_elem_t *pce; + ndr_p_cont_elem_t *pce; ndr_bind_ack_hdr_t *bahdr; ndr_p_result_t *pre; int rc; bzero(&mxa, sizeof (mxa)); - msvc = ndr_svc_lookup_name(service_name); - if (msvc == NULL) - return (NDR_DRC_FAULT_API_SERVICE_INVALID); - mxa.binding_list = clnt->binding_list; if ((mbind = ndr_svc_new_binding(&mxa)) == NULL) return (NDR_DRC_FAULT_API_BIND_NO_SLOTS); @@ -140,16 +136,12 @@ int ndr_clnt_call(ndr_binding_t *mbind, int opnum, void *params) { ndr_client_t *clnt = mbind->clnt; - ndr_service_t *msvc = mbind->service; ndr_xa_t mxa; ndr_request_hdr_t *reqhdr; ndr_common_header_t *rsphdr; unsigned long recv_pdu_scan_offset; int rc; - if (ndr_svc_lookup_name(msvc->name) == NULL) - return (NDR_DRC_FAULT_API_SERVICE_INVALID); - bzero(&mxa, sizeof (mxa)); mxa.ptype = NDR_PTYPE_REQUEST; mxa.opnum = opnum; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c b/usr/src/lib/libmlrpc/common/ndr_heap.c index 73a453b00e..5ec8a5aa77 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c +++ b/usr/src/lib/libmlrpc/common/ndr_heap.c @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ /* @@ -46,9 +48,8 @@ #include <strings.h> #include <sys/uio.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> -#include <smbsrv/smb_sid.h> +#include <libmlrpc.h> +#include <ndr_wchar.h> /* * Allocate a heap structure and the first heap block. For many RPC @@ -154,6 +155,23 @@ ndr_heap_malloc(ndr_heap_t *heap, unsigned size) } /* + * Convenience function to copy some memory into the heap. + */ +void * +ndr_heap_dupmem(ndr_heap_t *heap, const void *mem, size_t len) +{ + void *p; + + if (mem == NULL) + return (NULL); + + if ((p = ndr_heap_malloc(heap, len)) != NULL) + (void) memcpy(p, mem, len); + + return (p); +} + +/* * Convenience function to do heap strdup. */ void * @@ -171,8 +189,7 @@ ndr_heap_strdup(ndr_heap_t *heap, const char *s) if ((len = strlen(s)) == 0) return (""); - if ((p = ndr_heap_malloc(heap, len+1)) != NULL) - (void) strcpy((char *)p, s); + p = ndr_heap_dupmem(heap, s, len+1); return (p); } @@ -183,11 +200,21 @@ ndr_heap_strdup(ndr_heap_t *heap, const char *s) int ndr_heap_mstring(ndr_heap_t *heap, const char *s, ndr_mstring_t *out) { + size_t slen; + if (s == NULL || out == NULL) return (-1); - out->length = smb_wcequiv_strlen(s); - out->allosize = out->length + sizeof (smb_wchar_t); + /* + * Determine the WC strlen of s + * Was ndr__wcequiv_strlen(s) + */ + slen = ndr__mbstowcs(NULL, s, NDR_STRING_MAX); + if (slen == (size_t)-1) + return (-1); + + out->length = slen * sizeof (ndr_wchar_t); + out->allosize = out->length + sizeof (ndr_wchar_t); if ((out->str = ndr_heap_strdup(heap, s)) == NULL) return (-1); @@ -207,20 +234,31 @@ ndr_heap_mstring(ndr_heap_t *heap, const char *s, ndr_mstring_t *out) void ndr_heap_mkvcs(ndr_heap_t *heap, char *s, ndr_vcstr_t *vc) { + size_t slen; int mlen; - vc->wclen = smb_wcequiv_strlen(s); - vc->wcsize = vc->wclen; + /* + * Determine the WC strlen of s + * Was ndr__wcequiv_strlen(s) + */ + slen = ndr__mbstowcs(NULL, s, NDR_STRING_MAX); + if (slen == (size_t)-1) + slen = 0; - mlen = sizeof (ndr_vcs_t) + vc->wcsize + sizeof (smb_wchar_t); + vc->wclen = slen * sizeof (ndr_wchar_t); + vc->wcsize = vc->wclen; + /* + * alloc one extra wchar for a null + * See slen + 1 arg for mbstowcs + */ + mlen = sizeof (ndr_vcs_t) + vc->wcsize + sizeof (ndr_wchar_t); vc->vcs = ndr_heap_malloc(heap, mlen); if (vc->vcs) { vc->vcs->vc_first_is = 0; - vc->vcs->vc_length_is = vc->wclen / sizeof (smb_wchar_t); - (void) smb_mbstowcs((smb_wchar_t *)vc->vcs->buffer, s, - vc->vcs->vc_length_is); + vc->vcs->vc_length_is = slen; + (void) ndr__mbstowcs(vc->vcs->buffer, s, slen + 1); } } @@ -250,25 +288,8 @@ ndr_heap_mkvcb(ndr_heap_t *heap, uint8_t *data, uint32_t datalen, } /* - * Duplcate a SID in the heap. + * Removed ndr_heap_siddup(), now using ndr_heap_dupmem(). */ -smb_sid_t * -ndr_heap_siddup(ndr_heap_t *heap, smb_sid_t *sid) -{ - smb_sid_t *new_sid; - unsigned size; - - if (sid == NULL) - return (NULL); - - size = smb_sid_len(sid); - - if ((new_sid = ndr_heap_malloc(heap, size)) == NULL) - return (NULL); - - bcopy(sid, new_sid, size); - return (new_sid); -} int ndr_heap_used(ndr_heap_t *heap) diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c b/usr/src/lib/libmlrpc/common/ndr_marshal.c index a690dfb2e9..4d34030d2a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c +++ b/usr/src/lib/libmlrpc/common/ndr_marshal.c @@ -20,14 +20,14 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #include <assert.h> #include <strings.h> #include <sys/param.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> #ifdef _BIG_ENDIAN static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c b/usr/src/lib/libmlrpc/common/ndr_ops.c index 0cbcdc6e90..4ca1cb6295 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c +++ b/usr/src/lib/libmlrpc/common/ndr_ops.c @@ -49,8 +49,7 @@ #include <string.h> #include <assert.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> #define NDOBUFSZ 128 diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c b/usr/src/lib/libmlrpc/common/ndr_process.c index 945b02e699..3188500a8b 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c +++ b/usr/src/lib/libmlrpc/common/ndr_process.c @@ -22,6 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ /* @@ -34,13 +35,11 @@ #include <strings.h> #include <assert.h> #include <string.h> +#include <stdio.h> #include <stdlib.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/string.h> -#include <smbsrv/libmlrpc.h> - -#define NDR_STRING_MAX 4096 +#include <libmlrpc.h> +#include <ndr_wchar.h> #define NDR_IS_UNION(T) \ (((T)->type_flags & NDR_F_TYPEOP_MASK) == NDR_F_UNION) @@ -1210,17 +1209,22 @@ ndr_outer_string(ndr_ref_t *outer_ref) /* * size_is is the number of characters in the * (multibyte) string, including the null. + * In other words, symbols, not bytes. */ - size_is = smb_wcequiv_strlen(valp) / - sizeof (smb_wchar_t); - - if (!(nds->flags & NDS_F_NONULL)) - ++size_is; - - if (size_is > NDR_STRING_MAX) { + size_t wlen; + wlen = ndr__mbstowcs(NULL, valp, NDR_STRING_MAX); + if (wlen == (size_t)-1) { + /* illegal sequence error? */ NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN); return (0); } + if ((nds->flags & NDS_F_NONULL) == 0) + wlen++; + if (wlen > NDR_STRING_MAX) { + NDR_SET_ERROR(outer_ref, NDR_ERR_STRLEN); + return (0); + } + size_is = wlen; } else { valp = outer_ref->datum; n_zeroes = 0; @@ -1288,7 +1292,7 @@ ndr_outer_string(ndr_ref_t *outer_ref) * be nice to use mbequiv_strlen but the string * may not be null terminated. */ - n_alloc = (size_is + 1) * MTS_MB_CHAR_MAX; + n_alloc = (size_is + 1) * NDR_MB_CHAR_MAX; } else { n_alloc = (size_is + 1) * is_varlen; } @@ -1741,7 +1745,7 @@ ndr_inner_array(ndr_ref_t *encl_ref) myref.inner_flags = NDR_F_NONE; for (i = 0; i < n_elem; i++) { - (void) sprintf(name, "[%lu]", i); + (void) snprintf(name, sizeof (name), "[%lu]", i); myref.name = name; myref.pdu_offset = pdu_offset + i * ti->pdu_size_fixed_part; myref.datum = encl_ref->datum + i * ti->c_size_fixed_part; @@ -1796,20 +1800,20 @@ ndr_inner_array(ndr_ref_t *encl_ref) int ndr_basic_integer(ndr_ref_t *, unsigned); int ndr_string_basic_integer(ndr_ref_t *, ndr_typeinfo_t *); +/* Comments to be nice to those searching for these types. */ +MAKE_BASIC_TYPE(_char, 1) /* ndt__char, ndt_s_char */ +MAKE_BASIC_TYPE(_uchar, 1) /* ndt__uchar, ndt_s_uchar */ +MAKE_BASIC_TYPE(_short, 2) /* ndt__short, ndt_s_short */ +MAKE_BASIC_TYPE(_ushort, 2) /* ndt__ushort, ndt_s_ushort */ +MAKE_BASIC_TYPE(_long, 4) /* ndt__long, ndt_s_long */ +MAKE_BASIC_TYPE(_ulong, 4) /* ndt__ulong, ndt_s_ulong */ -MAKE_BASIC_TYPE(_char, 1) -MAKE_BASIC_TYPE(_uchar, 1) -MAKE_BASIC_TYPE(_short, 2) -MAKE_BASIC_TYPE(_ushort, 2) -MAKE_BASIC_TYPE(_long, 4) -MAKE_BASIC_TYPE(_ulong, 4) - -MAKE_BASIC_TYPE_BASE(_wchar, 2) +MAKE_BASIC_TYPE_BASE(_wchar, 2) /* ndt__wchar, ndt_s_wchar */ int ndr_basic_integer(ndr_ref_t *ref, unsigned size) { - ndr_stream_t *nds = ref->stream; + ndr_stream_t *nds = ref->stream; char *valp = (char *)ref->datum; int rc; @@ -1854,7 +1858,7 @@ ndr_string_basic_integer(ndr_ref_t *encl_ref, ndr_typeinfo_t *type_under) myref.name = name; for (i = 0; i < NDR_STRING_MAX; i++) { - (void) sprintf(name, "[%lu]", i); + (void) snprintf(name, sizeof (name), "[%lu]", i); myref.pdu_offset = pdu_offset + i * size; valp = encl_ref->datum + i * size; myref.datum = valp; @@ -1897,27 +1901,27 @@ ndr_typeinfo_t ndt_s_wchar = { * multi-byte to wide characters. During NDR_M_OP_UNMARSHALL, we * convert from wide characters to multi-byte. * - * It appeared that NT would sometimes leave a spurious character - * in the data stream before the null wide_char, which would get - * included in the string decode because we processed until the - * null character. It now looks like NT does not always terminate - * RPC Unicode strings and the terminating null is a side effect - * of field alignment. So now we rely on the strlen_is (set up in - * ndr_outer_string) of the enclosing reference. This may or may - * not include the null but it doesn't matter, the algorithm will - * get it right. + * The most critical thing to get right in this function is to + * marshall or unmarshall _exactly_ the number of elements the + * OtW length specifies, as saved by the caller in: strlen_is. + * Doing otherwise would leave us positioned at the wrong place + * in the data stream for whatever follows this. Note that the + * string data covered by strlen_is may or may not include any + * null termination, but the converted string provided by the + * caller or returned always has a null terminator. */ int ndr_s_wchar(ndr_ref_t *encl_ref) { ndr_stream_t *nds = encl_ref->stream; - unsigned short wide_char; - char *valp; + char *valp = encl_ref->datum; ndr_ref_t myref; - unsigned long i; char name[30]; - int count; - int char_count = 0; + ndr_wchar_t wcs[NDR_STRING_MAX+1]; + size_t i, slen, wlen; + + /* This is enforced in ndr_outer_string() */ + assert(encl_ref->strlen_is <= NDR_STRING_MAX); if (nds->m_op == NDR_M_OP_UNMARSHALL) { /* @@ -1930,59 +1934,60 @@ ndr_s_wchar(ndr_ref_t *encl_ref) } } + /* + * If we're marshalling, convert the given string + * from UTF-8 into a local UCS-2 string. + */ + if (nds->m_op == NDR_M_OP_MARSHALL) { + wlen = ndr__mbstowcs(wcs, valp, NDR_STRING_MAX); + if (wlen == (size_t)-1) + return (0); + /* + * Add a nulls to make strlen_is. + * (always zero or one of them) + * Then null terminate at wlen, + * just for debug convenience. + */ + while (wlen < encl_ref->strlen_is) + wcs[wlen++] = 0; + wcs[wlen] = 0; + } + + /* + * Copy wire data to or from the local wc string. + * Always exactly strlen_is elements. + */ bzero(&myref, sizeof (myref)); myref.enclosing = encl_ref; myref.stream = encl_ref->stream; myref.packed_alignment = 0; myref.ti = &ndt__wchar; myref.inner_flags = NDR_F_NONE; - myref.datum = (char *)&wide_char; myref.name = name; myref.pdu_offset = encl_ref->pdu_offset; + myref.datum = (char *)wcs; + wlen = encl_ref->strlen_is; - valp = encl_ref->datum; - count = 0; - - for (i = 0; i < NDR_STRING_MAX; i++) { - (void) sprintf(name, "[%lu]", i); - - if (nds->m_op == NDR_M_OP_MARSHALL) { - count = smb_mbtowc((smb_wchar_t *)&wide_char, valp, - MTS_MB_CHAR_MAX); - if (count < 0) { - return (0); - } else if (count == 0) { - if (encl_ref->strlen_is != encl_ref->size_is) - break; - - /* - * If the input char is 0, mbtowc - * returns 0 without setting wide_char. - * Set wide_char to 0 and a count of 1. - */ - wide_char = *valp; - count = 1; - } - } - + for (i = 0; i < wlen; i++) { + (void) snprintf(name, sizeof (name), "[%lu]", i); if (!ndr_inner(&myref)) return (0); + myref.pdu_offset += sizeof (ndr_wchar_t); + myref.datum += sizeof (ndr_wchar_t); + } - if (nds->m_op == NDR_M_OP_UNMARSHALL) { - count = smb_wctomb(valp, wide_char); - - if ((++char_count) == encl_ref->strlen_is) { - valp += count; - *valp = '\0'; - break; - } - } - - if (!wide_char) - break; - - myref.pdu_offset += sizeof (wide_char); - valp += count; + /* + * If this is unmarshall, convert the local UCS-2 string + * into a UTF-8 string in the caller's buffer. The caller + * previously determined the space required and provides a + * buffer of sufficient size. + */ + if (nds->m_op == NDR_M_OP_UNMARSHALL) { + wcs[wlen] = 0; + slen = ndr__wcstombs(valp, wcs, wlen); + if (slen == (size_t)-1) + return (0); + valp[slen] = '\0'; } return (1); @@ -1997,51 +2002,20 @@ ndr_s_wchar(ndr_ref_t *encl_ref) * any terminating null wide character. Returns -1 if an invalid * multibyte character is encountered. */ +/* ARGSUSED */ size_t -ndr_mbstowcs(ndr_stream_t *nds, smb_wchar_t *wcs, const char *mbs, +ndr_mbstowcs(ndr_stream_t *nds, ndr_wchar_t *wcs, const char *mbs, size_t nwchars) { - smb_wchar_t *start = wcs; - int nbytes; - - while (nwchars--) { - nbytes = ndr_mbtowc(nds, wcs, mbs, MTS_MB_CHAR_MAX); - if (nbytes < 0) { - *wcs = 0; - return ((size_t)-1); - } - - if (*mbs == 0) - break; - - ++wcs; - mbs += nbytes; - } - - return (wcs - start); -} - -/* - * Converts a multibyte character to a little-endian, wide-char, which - * is stored in wcharp. Up to nbytes bytes are examined. - * - * If mbchar is valid, returns the number of bytes processed in mbchar. - * If mbchar is invalid, returns -1. See also smb_mbtowc(). - */ -/*ARGSUSED*/ -int -ndr_mbtowc(ndr_stream_t *nds, smb_wchar_t *wcharp, const char *mbchar, - size_t nbytes) -{ - int rc; - - if ((rc = smb_mbtowc(wcharp, mbchar, nbytes)) < 0) - return (rc); + size_t len; #ifdef _BIG_ENDIAN - if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND)) - *wcharp = BSWAP_16(*wcharp); + if (nds == NULL || NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND)) { + /* Make WC string in LE order. */ + len = ndr__mbstowcs_le(wcs, mbs, nwchars); + } else #endif + len = ndr__mbstowcs(wcs, mbs, nwchars); - return (rc); + return (len); } diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c b/usr/src/lib/libmlrpc/common/ndr_server.c index 198daa7d55..4a1e2c177a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c +++ b/usr/src/lib/libmlrpc/common/ndr_server.c @@ -36,9 +36,7 @@ #include <string.h> #include <thread.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> -#include <smbsrv/ntaccess.h> +#include <libmlrpc.h> #define NDR_PIPE_SEND(np, buf, len) \ ((np)->np_send)((np), (buf), (len)) @@ -132,42 +130,6 @@ out1: } /* - * Check whether or not the specified user has administrator privileges, - * i.e. is a member of Domain Admins or Administrators. - * Returns true if the user is an administrator, otherwise returns false. - */ -boolean_t -ndr_is_admin(ndr_xa_t *xa) -{ - smb_netuserinfo_t *ctx = xa->pipe->np_user; - - return (ctx->ui_flags & SMB_ATF_ADMIN); -} - -/* - * Check whether or not the specified user has power-user privileges, - * i.e. is a member of Domain Admins, Administrators or Power Users. - * This is typically required for operations such as managing shares. - * Returns true if the user is a power user, otherwise returns false. - */ -boolean_t -ndr_is_poweruser(ndr_xa_t *xa) -{ - smb_netuserinfo_t *ctx = xa->pipe->np_user; - - return ((ctx->ui_flags & SMB_ATF_ADMIN) || - (ctx->ui_flags & SMB_ATF_POWERUSER)); -} - -int32_t -ndr_native_os(ndr_xa_t *xa) -{ - smb_netuserinfo_t *ctx = xa->pipe->np_user; - - return (ctx->ui_native_os); -} - -/* * Receive an entire RPC request (all fragments) * Returns zero or an NDR fault code. */ diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c b/usr/src/lib/libmlrpc/common/ndr_svc.c index d5c5f95f01..1e000a27f1 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c +++ b/usr/src/lib/libmlrpc/common/ndr_svc.c @@ -34,8 +34,7 @@ #include <strings.h> #include <assert.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> +#include <libmlrpc.h> /* diff --git a/usr/src/lib/libmlrpc/common/ndr_wchar.c b/usr/src/lib/libmlrpc/common/ndr_wchar.c new file mode 100644 index 0000000000..81886f3250 --- /dev/null +++ b/usr/src/lib/libmlrpc/common/ndr_wchar.c @@ -0,0 +1,162 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Some wchar support functions used by this library. + * Mostlly just wrappers that call sys/u8_textprep.h + * functions: uconv_u8tou16, uconv_u16tou8. + */ + +#include <sys/types.h> +#include <sys/u8_textprep.h> +#include <string.h> + +#include "ndr_wchar.h" + +/* + * When we just want lengths, we need an output buffer to pass to the + * uconv_... functions. Nothing ever reads this output, so we can + * use shared space for the unwanted output. + */ +static uint16_t junk_wcs[NDR_STRING_MAX]; +static char junk_mbs[NDR_MB_CUR_MAX * NDR_STRING_MAX]; + +static size_t +ndr__mbstowcs_x(uint16_t *, const char *, size_t, int); + +/* + * Like mbstowcs(3C), but with UCS-2 wchar_t + */ +size_t +ndr__mbstowcs(uint16_t *wcs, const char *mbs, size_t nwchars) +{ + return (ndr__mbstowcs_x(wcs, mbs, nwchars, + UCONV_OUT_SYSTEM_ENDIAN)); +} + +/* + * Like above, but put UCS-2 little-endian. + */ +size_t +ndr__mbstowcs_le(uint16_t *wcs, const char *mbs, size_t nwchars) +{ + return (ndr__mbstowcs_x(wcs, mbs, nwchars, + UCONV_OUT_LITTLE_ENDIAN)); +} + +/* + * Like mbstowcs(3C), but with UCS-2 wchar_t, and + * one extra arg for the byte order flags. + */ +static size_t +ndr__mbstowcs_x(uint16_t *wcs, const char *mbs, size_t nwchars, int flags) +{ + size_t obytes, mbslen, wcslen; + int err; + + /* NULL or empty input is allowed. */ + if (mbs == NULL || *mbs == '\0') { + if (wcs != NULL && nwchars > 0) + *wcs = 0; + return (0); + } + + /* + * If wcs == NULL, caller just wants the length. + * Convert into some throw-away space. + */ + obytes = nwchars * 2; + if (wcs == NULL) { + if (obytes > sizeof (junk_wcs)) + return ((size_t)-1); + wcs = junk_wcs; + } + + mbslen = strlen(mbs); + wcslen = nwchars; + err = uconv_u8tou16((const uchar_t *)mbs, &mbslen, + wcs, &wcslen, flags); + if (err != 0) + return ((size_t)-1); + + if (wcslen < nwchars) + wcs[wcslen] = 0; + + return (wcslen); +} + +/* + * Like wcstombs(3C), but with UCS-2 wchar_t. + */ +size_t +ndr__wcstombs(char *mbs, const uint16_t *wcs, size_t nbytes) +{ + size_t mbslen, wcslen; + int err; + + /* NULL or empty input is allowed. */ + if (wcs == NULL || *wcs == 0) { + if (mbs != NULL && nbytes > 0) + *mbs = '\0'; + return (0); + } + + /* + * If mbs == NULL, caller just wants the length. + * Convert into some throw-away space. + */ + if (mbs == NULL) { + if (nbytes > sizeof (junk_mbs)) + return ((size_t)-1); + mbs = junk_mbs; + } + + wcslen = ndr__wcslen(wcs); + mbslen = nbytes; + err = uconv_u16tou8(wcs, &wcslen, + (uchar_t *)mbs, &mbslen, UCONV_IN_SYSTEM_ENDIAN); + if (err != 0) + return ((size_t)-1); + + if (mbslen < nbytes) + mbs[mbslen] = '\0'; + + return (mbslen); +} + +/* + * Like wcslen(3C), but with UCS-2 wchar_t. + */ +size_t +ndr__wcslen(const uint16_t *wc) +{ + size_t len = 0; + while (*wc++) + len++; + return (len); +} diff --git a/usr/src/lib/libmlrpc/common/ndr_wchar.h b/usr/src/lib/libmlrpc/common/ndr_wchar.h new file mode 100644 index 0000000000..e5fe8a1054 --- /dev/null +++ b/usr/src/lib/libmlrpc/common/ndr_wchar.h @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _NDR_WCHAR_H +#define _NDR_WCHAR_H + +/* + * Some ndr_wchar_t support stuff. + */ + +#define NDR_MB_CUR_MAX 3 +#define NDR_MB_CHAR_MAX NDR_MB_CUR_MAX +#define NDR_STRING_MAX 4096 + +size_t ndr__mbstowcs(uint16_t *, const char *, size_t); +size_t ndr__mbstowcs_le(uint16_t *, const char *, size_t); + +size_t ndr__wcslen(const uint16_t *); +size_t ndr__wcstombs(char *, const uint16_t *, size_t); + +#endif /* _NDR_WCHAR_H */ diff --git a/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl b/usr/src/lib/libmlrpc/common/ndrtypes.ndl index 16bb4b8135..b7d5fdb716 100644 --- a/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl +++ b/usr/src/lib/libmlrpc/common/ndrtypes.ndl @@ -21,10 +21,17 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ -#ifndef _NDR_TYPES_NDL_ -#define _NDR_TYPES_NDL_ +#ifndef _NDRTYPES_NDL_ +#define _NDRTYPES_NDL_ + +/* + * Type definitions (and related) used in NDL files and the + * NDL run-time support libraries. See also: libmlrpc.h + */ #define TYPEINFO(TYPE) ndt__##TYPE @@ -69,20 +76,6 @@ #define LPWORD ushort * #define LPDWORD ulong * -/* - * Opaque context handle. - */ -#ifndef CONTEXT_HANDLE -#define CONTEXT_HANDLE(NAME) \ - struct NAME { \ - DWORD data1; \ - DWORD data2; \ - WORD data3[2]; \ - BYTE data4[8]; \ - }; \ - typedef struct NAME -#endif /* CONTEXT_HANDLE */ - #define EXTERNTYPEINFO(TYPE) #else /* NDRGEN */ @@ -116,7 +109,7 @@ /* * When not using ndrgen, get BYTE, WORD, DWORD definitions from wintypes.h. */ -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #define EXTERNTYPEINFO(TYPE) extern struct ndr_typeinfo TYPEINFO(TYPE); @@ -167,4 +160,18 @@ #define UNION_INFO_ENT(N,NAME) CASE(N) struct NAME##N info##N #define UNION_INFO_PTR(N,NAME) CASE(N) struct NAME##N *info##N -#endif /* _NDR_TYPES_NDL_ */ +/* + * Opaque context handle. + */ +#ifndef CONTEXT_HANDLE +#define CONTEXT_HANDLE(NAME) \ + struct NAME { \ + DWORD data1; \ + DWORD data2; \ + WORD data3[2]; \ + BYTE data4[8]; \ + }; \ + typedef struct NAME +#endif /* CONTEXT_HANDLE */ + +#endif /* _NDRTYPES_NDL_ */ diff --git a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl b/usr/src/lib/libmlrpc/common/rpcpdu.ndl index f1ea15cf00..f1ea15cf00 100644 --- a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl +++ b/usr/src/lib/libmlrpc/common/rpcpdu.ndl diff --git a/usr/src/lib/smbsrv/libmlrpc/i386/Makefile b/usr/src/lib/libmlrpc/i386/Makefile index 710c9eb3dd..6589e9941a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/i386/Makefile +++ b/usr/src/lib/libmlrpc/i386/Makefile @@ -22,11 +22,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# include ../Makefile.com -DYNFLAGS += -R/usr/lib/smbsrv - install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile b/usr/src/lib/libmlrpc/sparc/Makefile index 710c9eb3dd..6589e9941a 100644 --- a/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile +++ b/usr/src/lib/libmlrpc/sparc/Makefile @@ -22,11 +22,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# include ../Makefile.com -DYNFLAGS += -R/usr/lib/smbsrv - install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile b/usr/src/lib/libmlrpc/sparcv9/Makefile index b3c4916b0c..087f0e1107 100644 --- a/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile +++ b/usr/src/lib/libmlrpc/sparcv9/Makefile @@ -22,14 +22,10 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64) include ../Makefile.com -include ../../../Makefile.lib.64 - -DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64) +include ../../Makefile.lib.64 install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/libsmbfs/Makefile.com b/usr/src/lib/libsmbfs/Makefile.com index 0521eba951..8f8b118128 100644 --- a/usr/src/lib/libsmbfs/Makefile.com +++ b/usr/src/lib/libsmbfs/Makefile.com @@ -59,7 +59,6 @@ OBJ_LIB=\ nb_ssn.o \ nbns_rq.o \ negprot.o \ - netshareenum.o \ newvc.o \ nls.o \ ntlm.o \ diff --git a/usr/src/lib/libsmbfs/netsmb/smb_netshareenum.h b/usr/src/lib/libsmbfs/netsmb/smb_netshareenum.h deleted file mode 100644 index 14f2594df7..0000000000 --- a/usr/src/lib/libsmbfs/netsmb/smb_netshareenum.h +++ /dev/null @@ -1,18 +0,0 @@ - -#ifndef _NETSMB_SMB_NETSHAREENUM_H_ -#define _NETSMB_SMB_NETSHAREENUM_H_ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* This is from Apple. See ../smb/netshareenum.c */ - -struct share_info { - uint16_t type; - char *netname; - char *remark; -}; -typedef struct share_info share_info_t; - -int smb_netshareenum(struct smb_ctx *, int *, int *, struct share_info **); - -#endif /* _NETSMB_SMB_NETSHAREENUM_H_ */ diff --git a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h index 8436318b4c..b1f4b1e198 100644 --- a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h +++ b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h @@ -140,8 +140,8 @@ typedef void (*smb_ctx_close_hook_t)(struct smb_ctx *); void smb_ctx_set_close_hook(smb_ctx_close_hook_t); int smb_fh_close(int); int smb_fh_open(struct smb_ctx *ctx, const char *, int); -int smb_fh_read(int, off_t, size_t, char *); -int smb_fh_write(int, off_t, size_t, const char *); +int smb_fh_read(int, off64_t, size_t, char *); +int smb_fh_write(int, off64_t, size_t, const char *); int smb_fh_xactnp(int, int, const char *, int *, char *, int *); int smb_fh_getssnkey(int, uchar_t *, size_t); diff --git a/usr/src/lib/libsmbfs/smb/file.c b/usr/src/lib/libsmbfs/smb/file.c index 1c09532d61..8ca9d2cee1 100644 --- a/usr/src/lib/libsmbfs/smb/file.c +++ b/usr/src/lib/libsmbfs/smb/file.c @@ -204,7 +204,7 @@ smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag) } int -smb_fh_read(int fd, off_t offset, size_t count, +smb_fh_read(int fd, off64_t offset, size_t count, char *dst) { struct smbioc_rw rwrq; @@ -221,7 +221,7 @@ smb_fh_read(int fd, off_t offset, size_t count, } int -smb_fh_write(int fd, off_t offset, size_t count, +smb_fh_write(int fd, off64_t offset, size_t count, const char *src) { struct smbioc_rw rwrq; diff --git a/usr/src/lib/libsmbfs/smb/llib-lsmbfs b/usr/src/lib/libsmbfs/smb/llib-lsmbfs index 1096482541..7459db63be 100644 --- a/usr/src/lib/libsmbfs/smb/llib-lsmbfs +++ b/usr/src/lib/libsmbfs/smb/llib-lsmbfs @@ -34,7 +34,6 @@ #include <netsmb/smb_lib.h> #include <netsmb/smb_keychain.h> -#include <netsmb/smb_netshareenum.h> #include <netsmb/smb_rap.h> #include <netsmb/spnego.h> diff --git a/usr/src/lib/libsmbfs/smb/mapfile-vers b/usr/src/lib/libsmbfs/smb/mapfile-vers index 24bffec63d..68b38f46ed 100644 --- a/usr/src/lib/libsmbfs/smb/mapfile-vers +++ b/usr/src/lib/libsmbfs/smb/mapfile-vers @@ -111,7 +111,6 @@ SYMBOL_VERSION SUNWprivate { smb_iod_start; smb_iod_work; smb_lib_init; - smb_netshareenum; # will move to libnetapi smb_open_printer; smb_open_rcfile; smb_simplecrypt; diff --git a/usr/src/lib/libsmbfs/smb/netshareenum.c b/usr/src/lib/libsmbfs/smb/netshareenum.c deleted file mode 100644 index af5a0bb9bd..0000000000 --- a/usr/src/lib/libsmbfs/smb/netshareenum.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* BEGIN CSTYLED */ -/* - * @(#)ui.c * - * (c) 2004 Apple Computer, Inc. All Rights Reserved - * - * - * netshareenum.c -- Routines for getting a list of share information - * from a server. - * - * MODIFICATION HISTORY: - * 27-Nov-2004 Guy Harris New today - */ -/* END CSTYLED */ - -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> - -#include <netsmb/mchain.h> -#include <netsmb/smb.h> -#include <netsmb/smb_lib.h> -#include <netsmb/smb_rap.h> -#include <netsmb/smb_netshareenum.h> -#include <smb/charsets.h> - -#if 0 /* XXX see below */ -#include <dce/exc_handling.h> -#include <rpc/attrb.h> -#include "srvsvc.h" -#endif - -/* - * Don't want RPC client-side code in here. - * It's good code; just doesn't belong here. - * - * The API provided by this library should be - * just files and pipes (and not much more). - * It MAY be useful to provide some of the - * RAP (remote API) functions functions like - * rap_netshareenum below... - * - * XXX: Not sure this file belongs here at all. - * smb_rap.h looks like a reasonable API - * for this library to export. - */ -#if 0 /* XXX */ - -static int -rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp, - struct share_info **entries_listp) -{ - char ctx_string[2+16+1]; /* enough for 64-bit pointer, in hex */ - unsigned_char_p_t binding; - unsigned32 binding_status; - rpc_binding_handle_t binding_h; - int error, i, entries; - char *addrstr, *srvnamestr; - unsigned short *usrvnamestr; - unsigned32 level; - SHARE_ENUM_STRUCT share_info; - SHARE_INFO_1_CONTAINER share_info_1_container; - SHARE_INFO_1 *shares, *share; - unsigned32 total_entries; - unsigned32 status, free_status; - struct share_info *entry_list, *elp; - static EXCEPTION rpc_x_connect_rejected; - static int exceptions_initialized; - - sprintf(ctx_string, "%p", ctx); - rpc_string_binding_compose(NULL, "ncacn_np", ctx_string, - "srvsvc", NULL, &binding, &binding_status); - if (binding_status != rpc_s_ok) { - smb_error(dgettext(TEXT_DOMAIN, - "rpc_string_binding_compose failed with %d"), - 0, binding_status); - return (EINVAL); - } - rpc_binding_from_string_binding(binding, &binding_h, &status); - rpc_string_free(&binding, (unsigned32 *)&free_status); - if (binding_status != rpc_s_ok) { - smb_error(dgettext(TEXT_DOMAIN, - "rpc_binding_from_string_binding failed with %d"), 0, - binding_status); - return (EINVAL); - } - level = 1; - share_info.share_union.level = 1; - share_info.share_union.tagged_union.share1 = &share_info_1_container; - share_info_1_container.share_count = 0; - share_info_1_container.shares = NULL; - /* - * Convert the server IP address to a string, and send that as - * the "server name" - that's what Windows appears to do, and - * that avoids problems with NetBIOS names containing - * non-ASCII characters. - */ - addrstr = inet_ntoa(ctx->ct_srvinaddr.sin_addr); - srvnamestr = malloc(strlen(addrstr) + 3); - if (srvnamestr == NULL) { - status = errno; - smb_error(dgettext(TEXT_DOMAIN, - "can't allocate string for server address"), status); - rpc_binding_free(&binding_h, &free_status); - return (status); - } - strcpy(srvnamestr, "\\\\"); - strcat(srvnamestr, addrstr); - usrvnamestr = convert_utf8_to_leunicode(srvnamestr); - if (usrvnamestr == NULL) { - smb_error(dgettext(TEXT_DOMAIN, - "can't convert string for server address to Unicode"), 0); - rpc_binding_free(&binding_h, &free_status); - free(srvnamestr); - return (EINVAL); - } - if (!exceptions_initialized) { - EXCEPTION_INIT(rpc_x_connect_rejected); - exc_set_status(&rpc_x_connect_rejected, rpc_s_connect_rejected); - exceptions_initialized = 1; - } - /* printf("Calling NetrShareEnum.."); XXX */ - TRY - status = NetrShareEnum(binding_h, usrvnamestr, &level, - &share_info, 4294967295U, &total_entries, NULL); - if (status != 0) - smb_error(dgettext(TEXT_DOMAIN, - "error from NetrShareEnum call: status = 0x%08x"), - 0, status); - /*CSTYLED*/ - CATCH (rpc_x_connect_rejected) - /* - * This is what we get if we can't open the pipe. - * That's a normal occurrence when we're talking - * to a system that (presumably) doesn't support - * DCE RPC on the server side, such as Windows 95/98/Me, - * so we don't log an error. - */ - /*CSTYLED*/ - status = ENOTSUP; - CATCH_ALL - /* - * XXX - should we handle some exceptions differently, - * returning different errors, and try RAP only for - * ENOTSUP? - */ - smb_error(dgettext(TEXT_DOMAIN, - "error from NetrShareEnum call: exception = %u"), - 0, THIS_CATCH->match.value); - status = ENOTSUP; - ENDTRY - rpc_binding_free(&binding_h, &free_status); - free(srvnamestr); - free(usrvnamestr); - if (status != 0) - return (ENOTSUP); - - /* - * XXX - if the IDL is correct, it's not clear whether the - * unmarshalling code will properly handle the case where - * a packet where "share_count" and the max count for the - * array of shares don't match; a valid DCE RPC implementation - * won't marshal something like that, but there's no guarantee - * that the server we're talking to has a valid implementation - * (which could be a *malicious* implementation!). - */ - entries = share_info.share_union.tagged_union.share1->share_count; - shares = share_info.share_union.tagged_union.share1->shares; - entry_list = calloc(entries, sizeof (struct share_info)); - if (entry_list == NULL) { - error = errno; - goto cleanup_and_return; - } - for (share = shares, elp = entry_list, i = 0; i < entries; - i++, share++) { - elp->type = share->shi1_type; - elp->netname = convert_unicode_to_utf8(share->shi1_share); - if (elp->netname == NULL) - goto fail; - elp->remark = convert_unicode_to_utf8(share->shi1_remark); - if (elp->remark == NULL) - goto fail; - elp++; - } - *entriesp = entries; - *totalp = total_entries; - *entries_listp = entry_list; - error = 0; - goto cleanup_and_return; - -fail: - error = errno; - for (elp = entry_list, i = 0; i < entries; i++, elp++) { - /* - * elp->netname is set before elp->remark, so if - * elp->netname is null, elp->remark is also null. - * If either of them is null, we haven't done anything - * to any entries after this one. - */ - if (elp->netname == NULL) - break; - free(elp->netname); - if (elp->remark == NULL) - break; - free(elp->remark); - } - free(entry_list); - -cleanup_and_return: - for (share = shares, i = 0; i < entries; i++, share++) { - free(share->shi1_share); - free(share->shi1_remark); - } - free(shares); - /* - * XXX - "share1" should be a unique pointer, but we haven't - * changed the marshalling code to support non-full pointers - * in unions, so we leave it as a full pointer. - * - * That means that this might, or might not, be changed from - * pointing to "share_info_1_container" to pointing to a - * mallocated structure, according to the DCE RPC 1.1 IDL spec; - * we free it only if it's changed. - */ - if (share_info.share_union.tagged_union.share1 != - &share_info_1_container) - free(share_info.share_union.tagged_union.share1); - return (error); -} -#endif /* XXX */ - -/* - * Enumerate shares using RAP - */ - -struct smb_share_info_1 { - char shi1_netname[13]; - char shi1_pad; - uint16_t shi1_type; - uint32_t shi1_remark; /* char * */ -}; - -static int -smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer, - int *cbBuffer, int *pcEntriesRead, int *pcTotalAvail) -{ - struct smb_rap *rap; - long lval = -1; - int error; - - error = smb_rap_create(0, "WrLeh", "B13BWz", &rap); - if (error) - return (error); - (void) smb_rap_setNparam(rap, sLevel); /* W - sLevel */ - (void) smb_rap_setPparam(rap, pbBuffer); /* r - pbBuffer */ - (void) smb_rap_setNparam(rap, *cbBuffer); /* L - cbBuffer */ - error = smb_rap_request(rap, ctx); - if (error == 0) { - *pcEntriesRead = rap->r_entries; - error = smb_rap_getNparam(rap, &lval); - *pcTotalAvail = lval; - /* Copy the data length into the IN/OUT variable. */ - *cbBuffer = rap->r_rcvbuflen; - } - error = smb_rap_error(rap, error); - smb_rap_done(rap); - return (error); -} - -static int -rap_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp, - struct share_info **entries_listp) -{ - int error, bufsize, i, entries, total, nreturned; - struct smb_share_info_1 *rpbuf, *ep; - struct share_info *entry_list, *elp; - char *cp; - int lbound, rbound; - - bufsize = 0xffe0; /* samba notes win2k bug for 65535 */ - rpbuf = malloc(bufsize); - if (rpbuf == NULL) - return (errno); - - error = smb_rap_NetShareEnum(ctx, 1, rpbuf, &bufsize, &entries, &total); - if (error && - error != (ERROR_MORE_DATA | SMB_RAP_ERROR)) { - free(rpbuf); - return (error); - } - entry_list = malloc(entries * sizeof (struct share_info)); - if (entry_list == NULL) { - error = errno; - free(rpbuf); - return (error); - } - lbound = entries * (sizeof (struct smb_share_info_1)); - rbound = bufsize; - for (ep = rpbuf, elp = entry_list, i = 0, nreturned = 0; i < entries; - i++, ep++) { - elp->type = letohs(ep->shi1_type); - ep->shi1_pad = '\0'; /* ensure null termination */ - elp->netname = convert_wincs_to_utf8(ep->shi1_netname); - if (elp->netname == NULL) - continue; /* punt on this entry */ - /* - * Check for validity of offset. - */ - if (ep->shi1_remark >= lbound && ep->shi1_remark < rbound) { - cp = (char *)rpbuf + ep->shi1_remark; - elp->remark = convert_wincs_to_utf8(cp); - } else - elp->remark = NULL; - elp++; - nreturned++; - } - *entriesp = nreturned; - *totalp = total; - *entries_listp = entry_list; - free(rpbuf); - return (0); -} - -/* - * First we try the RPC-based NetrShareEnum, and, if that fails, we fall - * back on the RAP-based NetShareEnum. - */ -int -smb_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp, - struct share_info **entry_listp) -{ - int error; - -#ifdef NOTYETDEFINED - /* - * Try getting a list of shares with the SRVSVC RPC service. - */ - error = rpc_netshareenum(ctx, entriesp, totalp, entry_listp); - if (error == 0) - return (0); -#endif - - /* - * OK, that didn't work - try RAP. - * XXX - do so only if it failed because we couldn't open - * the pipe? - */ - error = rap_netshareenum(ctx, entriesp, totalp, entry_listp); - return (error); -} diff --git a/usr/src/lib/smbsrv/Makefile b/usr/src/lib/smbsrv/Makefile index 4213133a56..68353f10fe 100644 --- a/usr/src/lib/smbsrv/Makefile +++ b/usr/src/lib/smbsrv/Makefile @@ -29,14 +29,12 @@ include ../Makefile.lib SUBDIRS = \ libfksmbsrv \ libmlsvc \ - libmlrpc \ libsmb \ libsmbns \ libsmbrp include ./Makefile.subdirs -libmlrpc: libsmb libsmbns: libsmb -libmlsvc: libsmb libmlrpc libsmbns +libmlsvc: libsmb libsmbns libfksmbsrv: libsmb diff --git a/usr/src/lib/smbsrv/Makefile.targ b/usr/src/lib/smbsrv/Makefile.targ index 92a05ef243..9305212b3c 100644 --- a/usr/src/lib/smbsrv/Makefile.targ +++ b/usr/src/lib/smbsrv/Makefile.targ @@ -22,19 +22,22 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" +# Copyright 2013 Nexenta Systems, Inc. All rights reserved. +# # # Common targets for smbsrv Makefiles # %_ndr.c: $(NDLDIR)/%.ndl - $(NDRGEN) -Y $(CC) $< + $(NDRGEN) -Y $(ANSI_CPP) $(CPPFLAGS) $< pics/%.o: $(SRC)/common/smbsrv/%.c $(COMPILE.c) -o $@ $< $(POST_PROCESS_O) +pics/%.o := CPPFLAGS += -I$(ROOTSMBHDRDIR)/ndl + .KEEP_STATE: all: $(LIBS) diff --git a/usr/src/lib/smbsrv/libmlrpc/Makefile b/usr/src/lib/smbsrv/libmlrpc/Makefile deleted file mode 100644 index c5a61203cd..0000000000 --- a/usr/src/lib/smbsrv/libmlrpc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -HDRS= libmlrpc.h - -include ../Makefile.smbsrv diff --git a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c index 02b57b9328..f77c0bdf01 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c @@ -29,7 +29,7 @@ #include <string.h> #include <strings.h> -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #include <smbsrv/libsmb.h> #include <smbsrv/ndl/dssetup.ndl> #include <smbsrv/libmlsvc.h> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c index 07986c2c93..24b999e7c3 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_svc.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ /* @@ -32,8 +33,8 @@ #include <stdlib.h> #include <netdb.h> +#include <libmlrpc/libmlrpc.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/ndl/dssetup.ndl> #include <smbsrv/smbinfo.h> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c index 34438c6cae..35f9c856e9 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ /* @@ -29,8 +30,8 @@ #include <sys/utsname.h> #include <unistd.h> #include <strings.h> +#include <libmlrpc/libmlrpc.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/nmpipes.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/ndl/eventlog.ndl> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h index 381a2ea98c..838353b8e9 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h +++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h @@ -26,17 +26,22 @@ #ifndef _LIBMLSVC_H #define _LIBMLSVC_H -#include <uuid/uuid.h> #include <sys/param.h> #include <sys/types.h> #include <sys/uio.h> #include <sys/ksynch.h> +#include <uuid/uuid.h> + #include <time.h> #include <stdio.h> #include <string.h> +#include <syslog.h> #include <netdb.h> #include <libuutil.h> -#include <smbsrv/wintypes.h> + +#include <smb/wintypes.h> +#include <libmlrpc/libmlrpc.h> + #include <smbsrv/hash_table.h> #include <smbsrv/smb_token.h> #include <smbsrv/smb_privilege.h> @@ -44,8 +49,6 @@ #include <smbsrv/smb_xdr.h> #include <smbsrv/smb_dfs.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> -#include <smbsrv/ndl/lsarpc.ndl> #ifdef __cplusplus extern "C" { @@ -128,24 +131,6 @@ typedef struct ms_luid { } ms_luid_t; /* - * Information about a server as reported by NetServerGetInfo. - * The SV_PLATFORM and SV_TYPE definitions are in srvsvc.ndl. - */ -typedef struct srvsvc_server_info { - uint32_t sv_platform_id; - char *sv_name; - uint32_t sv_version_major; - uint32_t sv_version_minor; - uint32_t sv_type; - char *sv_comment; - uint32_t sv_os; -} srvsvc_server_info_t; - -int srvsvc_net_server_getinfo(char *, char *, srvsvc_server_info_t *); -int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *); - - -/* * A client_t is created while binding a client connection to hold the * context for calls made using that connection. * @@ -153,29 +138,23 @@ int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *); * ensure that each handle has a pointer to the client_t. When the top * level (bind) handle is released, we close the connection. */ -typedef struct mlsvc_handle { - ndr_hdid_t handle; - ndr_client_t *clnt; - srvsvc_server_info_t svinfo; -} mlsvc_handle_t; +typedef struct mlrpc_handle mlsvc_handle_t; +/* mlsvc_client.c */ void ndr_rpc_init(void); void ndr_rpc_fini(void); uint32_t ndr_rpc_bind(mlsvc_handle_t *, char *, char *, char *, const char *); void ndr_rpc_unbind(mlsvc_handle_t *); -int ndr_rpc_call(mlsvc_handle_t *, int, void *); -void ndr_rpc_set_nonull(mlsvc_handle_t *); -const srvsvc_server_info_t *ndr_rpc_server_info(mlsvc_handle_t *); -uint32_t ndr_rpc_server_os(mlsvc_handle_t *); -int ndr_rpc_get_ssnkey(mlsvc_handle_t *, unsigned char *, size_t); -void *ndr_rpc_malloc(mlsvc_handle_t *, size_t); -ndr_heap_t *ndr_rpc_get_heap(mlsvc_handle_t *); -void ndr_rpc_release(mlsvc_handle_t *); -boolean_t ndr_is_null_handle(mlsvc_handle_t *); -boolean_t ndr_is_bind_handle(mlsvc_handle_t *); -void ndr_inherit_handle(mlsvc_handle_t *, mlsvc_handle_t *); void ndr_rpc_status(mlsvc_handle_t *, int, uint32_t); +/* These three get info about the connected client. */ +boolean_t ndr_is_admin(ndr_xa_t *); +boolean_t ndr_is_poweruser(ndr_xa_t *); +int32_t ndr_native_os(ndr_xa_t *); + +/* SRVSVC */ +int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *); + /* SVCCTL service */ /* * Calculate the wide-char equivalent string length required to diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c index eeab7745f2..7524e2db55 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c @@ -383,7 +383,6 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info) lsar_lookup_names1 }; - const srvsvc_server_info_t *svinfo; lsa_names_t names; char *p; uint32_t length; @@ -396,20 +395,15 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info) bzero(info, sizeof (smb_account_t)); - svinfo = ndr_rpc_server_info(lsa_handle); - if (svinfo->sv_os == NATIVE_OS_WIN2000 && - svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) { - /* - * Windows 2000 doesn't like an LSA lookup for - * DOMAIN\Administrator. - */ - if ((p = strchr(name, '\\')) != 0) { - ++p; - - if (strcasecmp(p, "administrator") == 0) - name = p; - } + /* + * Windows 2000 (or later) doesn't like an LSA lookup for + * DOMAIN\Administrator. + */ + if ((p = strchr(name, '\\')) != 0) { + ++p; + if (strcasecmp(p, "administrator") == 0) + name = p; } length = smb_wcequiv_strlen(name); @@ -418,17 +412,12 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info) names.name[0].str = (unsigned char *)name; names.n_entry = 1; - if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) { - for (i = 0; i < n_op; ++i) { - ndr_rpc_set_nonull(lsa_handle); - status = (*ops[i])(lsa_handle, &names, info); - - if (status != NT_STATUS_INVALID_PARAMETER) - break; - } - } else { + for (i = 0; i < n_op; ++i) { ndr_rpc_set_nonull(lsa_handle); - status = lsar_lookup_names1(lsa_handle, &names, info); + status = (*ops[i])(lsa_handle, &names, info); + + if (status != NT_STATUS_INVALID_PARAMETER) + break; } if (status == NT_STATUS_SUCCESS) { @@ -726,10 +715,8 @@ lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid, smb_sid_tostr(sid, sidbuf); smb_tracef("%s", sidbuf); - if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) - status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, - account); - else + status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, account); + if (status == RPC_NT_PROCNUM_OUT_OF_RANGE) status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid, account); @@ -1167,8 +1154,7 @@ lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name, (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); length = smb_wcequiv_strlen(name); - if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) - length += sizeof (smb_wchar_t); + length += sizeof (smb_wchar_t); arg.name.length = length; arg.name.allosize = length; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c index 3864260e2c..28d5e73948 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_svc.c @@ -33,8 +33,8 @@ #include <pwd.h> #include <grp.h> +#include <libmlrpc/libmlrpc.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/ndl/lsarpc.ndl> #include <lsalib.h> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h index dcf2c5f0e7..2afc62a02d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc.h @@ -46,7 +46,6 @@ void netr_initialize(void); void samr_initialize(void); void svcctl_initialize(void); void winreg_initialize(void); -int srvsvc_gettime(unsigned long *); void msgsvcsend_initialize(void); void spoolss_initialize(void); void netdfs_initialize(void); @@ -64,7 +63,8 @@ int netr_setup_authenticator(struct netr_info *, struct netr_authenticator *, struct netr_authenticator *); DWORD netr_validate_chain(struct netr_info *, struct netr_authenticator *); -void ndr_srvsvc_timecheck(char *, char *); +int srvsvc_gettime(unsigned long *); +void srvsvc_timecheck(char *, char *); /* Generic functions to get/set windows Security Descriptors */ uint32_t srvsvc_sd_get(smb_share_t *, uint8_t *, uint32_t *); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c index ef3ca34bcd..c8879837b1 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c @@ -31,32 +31,22 @@ #include <sys/types.h> #include <sys/errno.h> #include <sys/fcntl.h> -#include <sys/tzfile.h> #include <time.h> #include <strings.h> #include <assert.h> #include <errno.h> #include <thread.h> -#include <unistd.h> #include <syslog.h> #include <synch.h> +#include <libmlrpc/libmlrpc.h> #include <netsmb/smbfs_api.h> + #include <smbsrv/libsmb.h> -#include <smbsrv/libsmbns.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> -#include <smbsrv/ndl/srvsvc.ndl> #include <libsmbrdr.h> #include <mlsvc.h> -static int ndr_xa_init(ndr_client_t *, ndr_xa_t *); -static int ndr_xa_exchange(ndr_client_t *, ndr_xa_t *); -static int ndr_xa_read(ndr_client_t *, ndr_xa_t *); -static void ndr_xa_preserve(ndr_client_t *, ndr_xa_t *); -static void ndr_xa_destruct(ndr_client_t *, ndr_xa_t *); -static void ndr_xa_release(ndr_client_t *); - /* * This call must be made to initialize an RPC client structure and bind @@ -71,13 +61,15 @@ static void ndr_xa_release(ndr_client_t *); * unbind and teardown the connection. As each handle is initialized it * will inherit a reference to the client context. * - * Returns 0 or an NT_STATUS: + * Returns 0 or an NT_STATUS: (failed in...) + * * NT_STATUS_BAD_NETWORK_PATH (get server addr) * NT_STATUS_NETWORK_ACCESS_DENIED (connect, auth) - * NT_STATUS_BAD_NETWORK_NAME (tcon, open) + * NT_STATUS_BAD_NETWORK_NAME (tcon) + * RPC_NT_SERVER_TOO_BUSY (open pipe) + * RPC_NT_SERVER_UNAVAILABLE (open pipe) * NT_STATUS_ACCESS_DENIED (open pipe) * NT_STATUS_INVALID_PARAMETER (rpc bind) - * * NT_STATUS_INTERNAL_ERROR (bad args etc) * NT_STATUS_NO_MEMORY */ @@ -86,11 +78,8 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain, char *username, const char *service) { struct smb_ctx *ctx = NULL; - ndr_client_t *clnt = NULL; ndr_service_t *svc; - srvsvc_server_info_t svinfo; DWORD status; - int fd = -1; int rc; if (handle == NULL || server == NULL || server[0] == '\0' || @@ -102,19 +91,6 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain, return (NT_STATUS_INTERNAL_ERROR); /* - * Set the default based on the assumption that most - * servers will be Windows 2000 or later. This used to - * try to get the actual server version, but that RPC - * is not necessarily allowed anymore, so don't bother. - */ - bzero(&svinfo, sizeof (srvsvc_server_info_t)); - svinfo.sv_platform_id = SV_PLATFORM_ID_NT; - svinfo.sv_version_major = 5; - svinfo.sv_version_minor = 0; - svinfo.sv_type = SV_TYPE_DEFAULT; - svinfo.sv_os = NATIVE_OS_WIN2000; - - /* * Some callers pass this when they want a NULL session. * Todo: have callers pass an empty string for that. */ @@ -136,296 +112,82 @@ ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain, "(Srv=%s Dom=%s User=%s), %s (0x%x)", server, domain, username, xlate_nt_status(status), status); - /* Tell the DC Locator this DC failed. */ - smb_ddiscover_bad_dc(server); - goto errout; - } - - /* - * Open the named pipe. - */ - fd = smb_fh_open(ctx, svc->endpoint, O_RDWR); - if (fd < 0) { - rc = errno; - syslog(LOG_DEBUG, "ndr_rpc_bind: " - "smb_fh_open (%s) err=%d", - svc->endpoint, rc); - switch (rc) { - case EACCES: - status = NT_STATUS_ACCESS_DENIED; - break; + /* + * If the error is one where changing to a new DC + * might help, try looking for a different DC. + */ + switch (status) { + case NT_STATUS_BAD_NETWORK_PATH: + case NT_STATUS_BAD_NETWORK_NAME: + /* Look for a new DC */ + smb_ddiscover_bad_dc(server); default: - status = NT_STATUS_BAD_NETWORK_NAME; break; } - goto errout; + return (status); } /* * Setup the RPC client handle. */ - if ((clnt = malloc(sizeof (ndr_client_t))) == NULL) { - status = NT_STATUS_NO_MEMORY; - goto errout; - } - bzero(clnt, sizeof (ndr_client_t)); - - clnt->handle = &handle->handle; - clnt->xa_init = ndr_xa_init; - clnt->xa_exchange = ndr_xa_exchange; - clnt->xa_read = ndr_xa_read; - clnt->xa_preserve = ndr_xa_preserve; - clnt->xa_destruct = ndr_xa_destruct; - clnt->xa_release = ndr_xa_release; - clnt->xa_private = ctx; - clnt->xa_fd = fd; - - ndr_svc_binding_pool_init(&clnt->binding_list, - clnt->binding_pool, NDR_N_BINDING_POOL); - - if ((clnt->heap = ndr_heap_create()) == NULL) { - status = NT_STATUS_NO_MEMORY; - goto errout; + rc = mlrpc_clh_create(handle, ctx); + if (rc != 0) { + syslog(LOG_ERR, "ndr_rpc_bind: mlrpc_clh_create: rc=%d", rc); + smbrdr_ctx_free(ctx); + switch (rc) { + case ENOMEM: + return (NT_STATUS_NO_MEMORY); + case EINVAL: + return (NT_STATUS_INVALID_PARAMETER); + default: + return (NT_STATUS_INTERNAL_ERROR); + } } /* - * Fill in the caller's handle. + * This does the pipe open and OtW RPC bind. + * Handles pipe open retries. */ - bzero(&handle->handle, sizeof (ndr_hdid_t)); - handle->clnt = clnt; - bcopy(&svinfo, &handle->svinfo, sizeof (srvsvc_server_info_t)); - - /* - * Do the OtW RPC bind. - */ - rc = ndr_clnt_bind(clnt, service, &clnt->binding); - switch (rc) { - case NDR_DRC_FAULT_OUT_OF_MEMORY: - status = NT_STATUS_NO_MEMORY; - break; - case NDR_DRC_FAULT_API_SERVICE_INVALID: /* not registered */ - status = NT_STATUS_INTERNAL_ERROR; - break; - default: - if (NDR_DRC_IS_FAULT(rc)) { - status = NT_STATUS_INVALID_PARAMETER; + status = mlrpc_clh_bind(handle, svc); + if (status != 0) { + syslog(LOG_DEBUG, "ndr_rpc_bind: " + "mlrpc_clh_bind, %s (0x%x)", + xlate_nt_status(status), status); + switch (status) { + case RPC_NT_SERVER_TOO_BUSY: + /* Look for a new DC */ + smb_ddiscover_bad_dc(server); + break; + default: break; } - /* FALLTHROUGH */ - case NDR_DRC_OK: - return (NT_STATUS_SUCCESS); - } - - syslog(LOG_DEBUG, "ndr_rpc_bind: " - "ndr_clnt_bind, %s (0x%x)", - xlate_nt_status(status), status); - -errout: - handle->clnt = NULL; - if (clnt != NULL) { - ndr_heap_destroy(clnt->heap); - free(clnt); - } - if (ctx != NULL) { - if (fd != -1) - (void) smb_fh_close(fd); - smbrdr_ctx_free(ctx); + ctx = mlrpc_clh_free(handle); + if (ctx != NULL) { + smbrdr_ctx_free(ctx); + } } return (status); } /* - * Unbind and close the pipe to an RPC service. - * - * If the heap has been preserved we need to go through an xa release. - * The heap is preserved during an RPC call because that's where data - * returned from the server is stored. + * Unbind and close the pipe to an RPC service + * and cleanup the smb_ctx. * - * Otherwise we destroy the heap directly. + * The heap may or may not be destroyed (see mlrpc_clh_free) */ void ndr_rpc_unbind(mlsvc_handle_t *handle) { - ndr_client_t *clnt = handle->clnt; - struct smb_ctx *ctx = clnt->xa_private; + struct smb_ctx *ctx; - if (clnt->heap_preserved) - ndr_clnt_free_heap(clnt); - else - ndr_heap_destroy(clnt->heap); + ctx = mlrpc_clh_free(handle); + if (ctx != NULL) + smbrdr_ctx_free(ctx); - (void) smb_fh_close(clnt->xa_fd); - smbrdr_ctx_free(ctx); - free(clnt); bzero(handle, sizeof (mlsvc_handle_t)); } -/* - * Call the RPC function identified by opnum. The remote service is - * identified by the handle, which should have been initialized by - * ndr_rpc_bind. - * - * If the RPC call is successful (returns 0), the caller must call - * ndr_rpc_release to release the heap. Otherwise, we release the - * heap here. - */ -int -ndr_rpc_call(mlsvc_handle_t *handle, int opnum, void *params) -{ - ndr_client_t *clnt = handle->clnt; - int rc; - - if (ndr_rpc_get_heap(handle) == NULL) - return (-1); - - rc = ndr_clnt_call(clnt->binding, opnum, params); - - /* - * Always clear the nonull flag to ensure - * it is not applied to subsequent calls. - */ - clnt->nonull = B_FALSE; - - if (NDR_DRC_IS_FAULT(rc)) { - ndr_rpc_release(handle); - return (-1); - } - - return (0); -} - -/* - * Outgoing strings should not be null terminated. - */ -void -ndr_rpc_set_nonull(mlsvc_handle_t *handle) -{ - handle->clnt->nonull = B_TRUE; -} - -/* - * Return a reference to the server info. - */ -const srvsvc_server_info_t * -ndr_rpc_server_info(mlsvc_handle_t *handle) -{ - return (&handle->svinfo); -} - -/* - * Return the RPC server OS level. - */ -uint32_t -ndr_rpc_server_os(mlsvc_handle_t *handle) -{ - return (handle->svinfo.sv_os); -} - -/* - * Get the session key from a bound RPC client handle. - * - * The key returned is the 16-byte "user session key" - * established by the underlying authentication protocol - * (either Kerberos or NTLM). This key is needed for - * SAM RPC calls such as SamrSetInformationUser, etc. - * See [MS-SAMR] sections: 2.2.3.3, 2.2.7.21, 2.2.7.25. - * - * Returns zero (success) or an errno. - */ -int -ndr_rpc_get_ssnkey(mlsvc_handle_t *handle, - unsigned char *ssn_key, size_t len) -{ - ndr_client_t *clnt = handle->clnt; - int rc; - - if (clnt == NULL) - return (EINVAL); - - rc = smb_fh_getssnkey(clnt->xa_fd, ssn_key, len); - return (rc); -} - -void * -ndr_rpc_malloc(mlsvc_handle_t *handle, size_t size) -{ - ndr_heap_t *heap; - - if ((heap = ndr_rpc_get_heap(handle)) == NULL) - return (NULL); - - return (ndr_heap_malloc(heap, size)); -} - -ndr_heap_t * -ndr_rpc_get_heap(mlsvc_handle_t *handle) -{ - ndr_client_t *clnt = handle->clnt; - - if (clnt->heap == NULL) - clnt->heap = ndr_heap_create(); - - return (clnt->heap); -} - -/* - * Must be called by RPC clients to free the heap after a successful RPC - * call, i.e. ndr_rpc_call returned 0. The caller should take a copy - * of any data returned by the RPC prior to calling this function because - * returned data is in the heap. - */ -void -ndr_rpc_release(mlsvc_handle_t *handle) -{ - ndr_client_t *clnt = handle->clnt; - - if (clnt->heap_preserved) - ndr_clnt_free_heap(clnt); - else - ndr_heap_destroy(clnt->heap); - - clnt->heap = NULL; -} - -/* - * Returns true if the handle is null. - * Otherwise returns false. - */ -boolean_t -ndr_is_null_handle(mlsvc_handle_t *handle) -{ - static ndr_hdid_t zero_handle; - - if (handle == NULL || handle->clnt == NULL) - return (B_TRUE); - - if (!memcmp(&handle->handle, &zero_handle, sizeof (ndr_hdid_t))) - return (B_TRUE); - - return (B_FALSE); -} - -/* - * Returns true if the handle is the top level bind handle. - * Otherwise returns false. - */ -boolean_t -ndr_is_bind_handle(mlsvc_handle_t *handle) -{ - return (handle->clnt->handle == &handle->handle); -} - -/* - * Pass the client reference from parent to child. - */ -void -ndr_inherit_handle(mlsvc_handle_t *child, mlsvc_handle_t *parent) -{ - child->clnt = parent->clnt; - bcopy(&parent->svinfo, &child->svinfo, sizeof (srvsvc_server_info_t)); -} - void ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status) { @@ -456,193 +218,3 @@ ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status) smb_tracef("%s[0x%02x]: %s: %s (0x%08x)", name, opnum, s, xlate_nt_status(status), status); } - -/* - * The following functions provide the client callback interface. - * If the caller hasn't provided a heap, create one here. - */ -static int -ndr_xa_init(ndr_client_t *clnt, ndr_xa_t *mxa) -{ - ndr_stream_t *recv_nds = &mxa->recv_nds; - ndr_stream_t *send_nds = &mxa->send_nds; - ndr_heap_t *heap = clnt->heap; - int rc; - - if (heap == NULL) { - if ((heap = ndr_heap_create()) == NULL) - return (-1); - - clnt->heap = heap; - } - - mxa->heap = heap; - - rc = nds_initialize(send_nds, 0, NDR_MODE_CALL_SEND, heap); - if (rc == 0) - rc = nds_initialize(recv_nds, NDR_PDU_SIZE_HINT_DEFAULT, - NDR_MODE_RETURN_RECV, heap); - - if (rc != 0) { - nds_destruct(&mxa->recv_nds); - nds_destruct(&mxa->send_nds); - ndr_heap_destroy(mxa->heap); - mxa->heap = NULL; - clnt->heap = NULL; - return (-1); - } - - if (clnt->nonull) - NDS_SETF(send_nds, NDS_F_NONULL); - - return (0); -} - -/* - * This is the entry pointy for an RPC client call exchange with - * a server, which will result in an smbrdr SmbTransact request. - * - * SmbTransact should return the number of bytes received, which - * we record as the PDU size, or a negative error code. - */ -static int -ndr_xa_exchange(ndr_client_t *clnt, ndr_xa_t *mxa) -{ - ndr_stream_t *recv_nds = &mxa->recv_nds; - ndr_stream_t *send_nds = &mxa->send_nds; - int err, more, nbytes; - - nbytes = recv_nds->pdu_max_size; - err = smb_fh_xactnp(clnt->xa_fd, - send_nds->pdu_size, (char *)send_nds->pdu_base_offset, - &nbytes, (char *)recv_nds->pdu_base_offset, &more); - if (err) { - recv_nds->pdu_size = 0; - return (-1); - } - - recv_nds->pdu_size = nbytes; - return (0); -} - -/* - * This entry point will be invoked if the xa-exchange response contained - * only the first fragment of a multi-fragment response. The RPC client - * code will then make repeated xa-read requests to obtain the remaining - * fragments, which will result in smbrdr SmbReadX requests. - * - * SmbReadX should return the number of bytes received, in which case we - * expand the PDU size to include the received data, or a negative error - * code. - */ -static int -ndr_xa_read(ndr_client_t *clnt, ndr_xa_t *mxa) -{ - ndr_stream_t *nds = &mxa->recv_nds; - int len; - int nbytes; - - if ((len = (nds->pdu_max_size - nds->pdu_size)) < 0) - return (-1); - - nbytes = smb_fh_read(clnt->xa_fd, 0, len, - (char *)nds->pdu_base_offset + nds->pdu_size); - - if (nbytes < 0) - return (-1); - - nds->pdu_size += nbytes; - - if (nds->pdu_size > nds->pdu_max_size) { - nds->pdu_size = nds->pdu_max_size; - return (-1); - } - - return (nbytes); -} - -/* - * Preserve the heap so that the client application has access to data - * returned from the server after an RPC call. - */ -static void -ndr_xa_preserve(ndr_client_t *clnt, ndr_xa_t *mxa) -{ - assert(clnt->heap == mxa->heap); - - clnt->heap_preserved = B_TRUE; - mxa->heap = NULL; -} - -/* - * Dispose of the transaction streams. If the heap has not been - * preserved, we can destroy it here. - */ -static void -ndr_xa_destruct(ndr_client_t *clnt, ndr_xa_t *mxa) -{ - nds_destruct(&mxa->recv_nds); - nds_destruct(&mxa->send_nds); - - if (!clnt->heap_preserved) { - ndr_heap_destroy(mxa->heap); - mxa->heap = NULL; - clnt->heap = NULL; - } -} - -/* - * Dispose of a preserved heap. - */ -static void -ndr_xa_release(ndr_client_t *clnt) -{ - if (clnt->heap_preserved) { - ndr_heap_destroy(clnt->heap); - clnt->heap = NULL; - clnt->heap_preserved = B_FALSE; - } -} - - -/* - * Compare the time here with the remote time on the server - * and report clock skew. - */ -void -ndr_srvsvc_timecheck(char *server, char *domain) -{ - char hostname[MAXHOSTNAMELEN]; - struct timeval dc_tv; - struct tm dc_tm; - struct tm *tm; - time_t tnow; - time_t tdiff; - int priority; - - if (srvsvc_net_remote_tod(server, domain, &dc_tv, &dc_tm) < 0) { - syslog(LOG_DEBUG, "srvsvc_net_remote_tod failed"); - return; - } - - tnow = time(NULL); - - if (tnow > dc_tv.tv_sec) - tdiff = (tnow - dc_tv.tv_sec) / SECSPERMIN; - else - tdiff = (dc_tv.tv_sec - tnow) / SECSPERMIN; - - if (tdiff != 0) { - (void) strlcpy(hostname, "localhost", MAXHOSTNAMELEN); - (void) gethostname(hostname, MAXHOSTNAMELEN); - - priority = (tdiff > 2) ? LOG_NOTICE : LOG_DEBUG; - syslog(priority, "DC [%s] clock skew detected: %u minutes", - server, tdiff); - - tm = gmtime(&dc_tv.tv_sec); - syslog(priority, "%-8s UTC: %s", server, asctime(tm)); - tm = gmtime(&tnow); - syslog(priority, "%-8s UTC: %s", hostname, asctime(tm)); - } -} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c index 794e6c9576..cdb6478f5b 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c @@ -111,7 +111,7 @@ mlsvc_timecheck(void *arg) if (!smb_domain_getinfo(&di)) continue; - ndr_srvsvc_timecheck(di.d_dci.dc_name, + srvsvc_timecheck(di.d_dci.dc_name, di.d_primary.di_nbname); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c index ad3565699b..b46cf99f87 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c @@ -425,3 +425,43 @@ mlsvc_disconnect(const char *server) { smbrdr_disconnect(server); } + +/* + * A few more helper functions for RPC services. + */ + +/* + * Check whether or not the specified user has administrator privileges, + * i.e. is a member of Domain Admins or Administrators. + * Returns true if the user is an administrator, otherwise returns false. + */ +boolean_t +ndr_is_admin(ndr_xa_t *xa) +{ + smb_netuserinfo_t *ctx = xa->pipe->np_user; + + return (ctx->ui_flags & SMB_ATF_ADMIN); +} + +/* + * Check whether or not the specified user has power-user privileges, + * i.e. is a member of Domain Admins, Administrators or Power Users. + * This is typically required for operations such as managing shares. + * Returns true if the user is a power user, otherwise returns false. + */ +boolean_t +ndr_is_poweruser(ndr_xa_t *xa) +{ + smb_netuserinfo_t *ctx = xa->pipe->np_user; + + return ((ctx->ui_flags & SMB_ATF_ADMIN) || + (ctx->ui_flags & SMB_ATF_POWERUSER)); +} + +int32_t +ndr_native_os(ndr_xa_t *xa) +{ + smb_netuserinfo_t *ctx = xa->pipe->np_user; + + return (ctx->ui_native_os); +} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c index 78538e6291..b49a3946ad 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/msgsvc_svc.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ /* @@ -30,8 +31,8 @@ #include <syslog.h> #include <stdlib.h> +#include <libmlrpc/libmlrpc.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/ndl/msgsvc.ndl> #include <smbsrv/smbinfo.h> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c index ea31c935ed..2b22744304 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c @@ -191,6 +191,10 @@ netr_server_req_challenge(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) return (0); } +uint32_t netr_server_auth2_flags = + NETR_NEGOTIATE_BASE_FLAGS | + NETR_NEGOTIATE_STRONGKEY_FLAG; + /* * netr_server_authenticate2 */ @@ -216,10 +220,9 @@ netr_server_authenticate2(mlsvc_handle_t *netr_handle, netr_info_t *netr_info) arg.account_name = (unsigned char *)account_name; arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE; arg.hostname = (unsigned char *)netr_info->hostname; - arg.negotiate_flags = NETR_NEGOTIATE_BASE_FLAGS; + arg.negotiate_flags = netr_server_auth2_flags; - if (ndr_rpc_server_os(netr_handle) == NATIVE_OS_WIN2000) { - arg.negotiate_flags |= NETR_NEGOTIATE_STRONGKEY_FLAG; + if (arg.negotiate_flags & NETR_NEGOTIATE_STRONGKEY_FLAG) { if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS) return (-1); } else { diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c index ab99db75f8..6fdd3a9ca4 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c @@ -37,8 +37,8 @@ #include <netdb.h> #include <thread.h> +#include <libmlrpc/libmlrpc.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/ndl/netlogon.ndl> #include <smbsrv/netrauth.h> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c index 289e8470cf..dd15469c15 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_clnt.c @@ -44,8 +44,8 @@ #include <netdb.h> #include <sys/param.h> +#include <libmlrpc/libmlrpc.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/smbinfo.h> #include <smbsrv/ntaccess.h> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c index 8835a8e00f..43ae0568e9 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c @@ -39,8 +39,8 @@ #include <netdb.h> #include <assert.h> #include <grp.h> +#include <libmlrpc/libmlrpc.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/smbinfo.h> #include <smbsrv/nmpipes.h> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c index ba1c9caece..302c7fb278 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c @@ -35,8 +35,8 @@ #include <strings.h> #include <fcntl.h> #include <errno.h> +#include <libmlrpc/libmlrpc.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/smb.h> #include <smbsrv/ndl/spoolss.ndl> diff --git a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c index def8ced54a..c7e5d60a6b 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c @@ -34,9 +34,11 @@ */ #include <sys/errno.h> +#include <sys/tzfile.h> #include <stdio.h> #include <time.h> #include <strings.h> +#include <unistd.h> #include <smbsrv/libsmb.h> #include <smbsrv/libmlsvc.h> @@ -348,65 +350,45 @@ srvsvc_net_connect_enum(char *server, char *domain, char *netname, int level) } /* - * Windows 95+ and Windows NT4.0 both report the version as 4.0. - * Windows 2000+ reports the version as 5.x. + * Compare the time here with the remote time on the server + * and report clock skew. */ -int -srvsvc_net_server_getinfo(char *server, char *domain, - srvsvc_server_info_t *svinfo) +void +srvsvc_timecheck(char *server, char *domain) { - mlsvc_handle_t handle; - struct mslm_NetServerGetInfo arg; - struct mslm_SERVER_INFO_101 *sv101; - int len, opnum, rc; - char user[SMB_USERNAME_MAXLEN]; + char hostname[MAXHOSTNAMELEN]; + struct timeval dc_tv; + struct tm dc_tm; + struct tm *tm; + time_t tnow; + time_t tdiff; + int priority; + + if (srvsvc_net_remote_tod(server, domain, &dc_tv, &dc_tm) < 0) { + syslog(LOG_DEBUG, "srvsvc_net_remote_tod failed"); + return; + } - smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); + tnow = time(NULL); - if (srvsvc_open(server, domain, user, &handle) != 0) - return (-1); + if (tnow > dc_tv.tv_sec) + tdiff = (tnow - dc_tv.tv_sec) / SECSPERMIN; + else + tdiff = (dc_tv.tv_sec - tnow) / SECSPERMIN; - opnum = SRVSVC_OPNUM_NetServerGetInfo; - bzero(&arg, sizeof (arg)); + if (tdiff != 0) { + (void) strlcpy(hostname, "localhost", MAXHOSTNAMELEN); + (void) gethostname(hostname, MAXHOSTNAMELEN); - len = strlen(server) + 4; - arg.servername = ndr_rpc_malloc(&handle, len); - if (arg.servername == NULL) - return (-1); + priority = (tdiff > 2) ? LOG_NOTICE : LOG_DEBUG; + syslog(priority, "DC [%s] clock skew detected: %u minutes", + server, tdiff); - (void) snprintf((char *)arg.servername, len, "\\\\%s", server); - arg.level = 101; - - rc = ndr_rpc_call(&handle, opnum, &arg); - if ((rc != 0) || (arg.status != 0)) { - srvsvc_close(&handle); - return (-1); + tm = gmtime(&dc_tv.tv_sec); + syslog(priority, "%-8s UTC: %s", server, asctime(tm)); + tm = gmtime(&tnow); + syslog(priority, "%-8s UTC: %s", hostname, asctime(tm)); } - - sv101 = arg.result.bufptr.bufptr101; - - bzero(svinfo, sizeof (srvsvc_server_info_t)); - svinfo->sv_platform_id = sv101->sv101_platform_id; - svinfo->sv_version_major = sv101->sv101_version_major; - svinfo->sv_version_minor = sv101->sv101_version_minor; - svinfo->sv_type = sv101->sv101_type; - if (sv101->sv101_name) - svinfo->sv_name = strdup((char *)sv101->sv101_name); - if (sv101->sv101_comment) - svinfo->sv_comment = strdup((char *)sv101->sv101_comment); - - if (svinfo->sv_type & SV_TYPE_WFW) - svinfo->sv_os = NATIVE_OS_WIN95; - if (svinfo->sv_type & SV_TYPE_WINDOWS) - svinfo->sv_os = NATIVE_OS_WIN95; - if ((svinfo->sv_type & SV_TYPE_NT) || - (svinfo->sv_type & SV_TYPE_SERVER_NT)) - svinfo->sv_os = NATIVE_OS_WINNT; - if (svinfo->sv_version_major > 4) - svinfo->sv_os = NATIVE_OS_WIN2000; - - srvsvc_close(&handle); - return (0); } /* @@ -544,39 +526,3 @@ srvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv, srvsvc_close(&handle); return (0); } - -void -srvsvc_net_test(char *server, char *domain, char *netname) -{ - smb_domainex_t di; - srvsvc_server_info_t svinfo; - - (void) smb_tracef("%s %s %s", server, domain, netname); - - if (smb_domain_getinfo(&di)) { - server = di.d_dci.dc_name; - domain = di.d_primary.di_nbname; - } - - if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) { - smb_tracef("NetServerGetInfo: %s %s (%d.%d) id=%d type=0x%08x", - svinfo.sv_name ? svinfo.sv_name : "NULL", - svinfo.sv_comment ? svinfo.sv_comment : "NULL", - svinfo.sv_version_major, svinfo.sv_version_minor, - svinfo.sv_platform_id, svinfo.sv_type); - - free(svinfo.sv_name); - free(svinfo.sv_comment); - } - - (void) srvsvc_net_share_get_info(server, domain, netname); -#if 0 - /* - * The NetSessionEnum server-side definition was updated. - * Disabled until the client-side has been updated. - */ - (void) srvsvc_net_session_enum(server, domain, netname); -#endif - (void) srvsvc_net_connect_enum(server, domain, netname, 0); - (void) srvsvc_net_connect_enum(server, domain, netname, 1); -} diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index fdda80dc2a..82d6bc1cc3 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -44,17 +44,18 @@ extern "C" { #include <synch.h> #include <stdarg.h> +#include <smb/nterror.h> +#include <smb/ntstatus.h> +#include <smb/wintypes.h> + #include <smbsrv/string.h> #include <smbsrv/smb_idmap.h> #include <smbsrv/netbios.h> #include <smbsrv/smb_share.h> -#include <smb/nterror.h> -#include <smb/ntstatus.h> #include <smbsrv/smb_door.h> #include <smbsrv/alloc.h> #include <smbsrv/hash_table.h> #include <smbsrv/msgbuf.h> -#include <smbsrv/wintypes.h> #include <smbsrv/smb_xdr.h> #include <smbsrv/smbinfo.h> #include <smbsrv/ntifs.h> diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c index e51f8bbca1..dfbbfd0483 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c @@ -33,8 +33,8 @@ #include <unistd.h> #include <errno.h> #include <sys/mman.h> +#include <smb/wintypes.h> #include <smbsrv/libsmb.h> -#include <smbsrv/wintypes.h> #include <smbsrv/smb_door.h> static int smb_door_call(uint32_t, void *, xdrproc_t, void *, xdrproc_t); diff --git a/usr/src/pkg/manifests/driver-storage-mpt_sas.mf b/usr/src/pkg/manifests/driver-storage-mpt_sas.mf index ae55dc9422..c0506e3307 100644 --- a/usr/src/pkg/manifests/driver-storage-mpt_sas.mf +++ b/usr/src/pkg/manifests/driver-storage-mpt_sas.mf @@ -71,8 +71,25 @@ driver name=mpt_sas class=scsi-self-identifying \ alias=pciex1000,95 \ alias=pciex1000,96 \ alias=pciex1000,97 \ + alias=pciex1000,aa \ + alias=pciex1000,ab \ + alias=pciex1000,ac \ + alias=pciex1000,ad \ + alias=pciex1000,ae \ + alias=pciex1000,af \ + alias=pciex1000,c0 \ + alias=pciex1000,c1 \ + alias=pciex1000,c2 \ + alias=pciex1000,c3 \ alias=pciex1000,c4 \ - alias=pciex1000,c9 + alias=pciex1000,c5 \ + alias=pciex1000,c6 \ + alias=pciex1000,c7 \ + alias=pciex1000,c8 \ + alias=pciex1000,c9 \ + alias=pciex1000,d0 \ + alias=pciex1000,d1 \ + alias=pciex1000,d2 file path=kernel/drv/$(ARCH64)/mpt_sas group=sys file path=kernel/drv/mpt_sas.conf group=sys \ original_name=SUNWmptsas:kernel/drv/mpt_sas.conf preserve=true @@ -81,3 +98,5 @@ legacy pkg=SUNWmptsas desc="LSI MPT SAS 2.0/2.5 Controller HBA Driver" \ name="LSI MPT SAS 2.0/2.5 Controller HBA Driver" license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL +license usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE \ + license=usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE diff --git a/usr/src/pkg/manifests/service-file-system-smb.mf b/usr/src/pkg/manifests/service-file-system-smb.mf index 4b349a26bc..ba5dedcd6d 100644 --- a/usr/src/pkg/manifests/service-file-system-smb.mf +++ b/usr/src/pkg/manifests/service-file-system-smb.mf @@ -83,7 +83,6 @@ file path=usr/lib/smbsrv/dtrace/smbd-pipesvc.d mode=0555 file path=usr/lib/smbsrv/dtrace/smbnode.d mode=0555 file path=usr/lib/smbsrv/dtrace/smbsrv.d mode=0555 file path=usr/lib/smbsrv/dtrace/smbvfs.d mode=0555 -file path=usr/lib/smbsrv/libmlrpc.so.1 file path=usr/lib/smbsrv/libmlsvc.so.1 file path=usr/lib/smbsrv/libsmb.so.1 file path=usr/lib/smbsrv/libsmbns.so.1 @@ -109,7 +108,3 @@ license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL link path=usr/lib/reparse/libreparse_smb.so target=libreparse_smb.so.1 link path=usr/lib/security/pam_smb_passwd.so target=pam_smb_passwd.so.1 -link path=usr/lib/smbsrv/libmlrpc.so target=libmlrpc.so.1 -link path=usr/lib/smbsrv/libmlsvc.so target=libmlsvc.so.1 -link path=usr/lib/smbsrv/libsmb.so target=libsmb.so.1 -link path=usr/lib/smbsrv/libsmbns.so target=libsmbns.so.1 diff --git a/usr/src/pkg/manifests/system-file-system-smb.mf b/usr/src/pkg/manifests/system-file-system-smb.mf index b68191317a..b5ff30e5ad 100644 --- a/usr/src/pkg/manifests/system-file-system-smb.mf +++ b/usr/src/pkg/manifests/system-file-system-smb.mf @@ -79,6 +79,7 @@ file path=usr/lib/fs/smbfs/mount mode=4555 file path=usr/lib/fs/smbfs/share mode=0555 file path=usr/lib/fs/smbfs/umount mode=4555 file path=usr/lib/fs/smbfs/unshare mode=0555 +file path=usr/lib/libmlrpc.so.2 file path=usr/lib/libsmbfs.so.1 file path=usr/lib/mdb/kvm/$(ARCH64)/nsmb.so mode=0555 file path=usr/lib/mdb/kvm/$(ARCH64)/smbfs.so mode=0555 diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh index 7b5870b8d6..1e86a66b7c 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh @@ -12,7 +12,7 @@ # # -# Copyright (c) 2017 by Delphix. All rights reserved. +# Copyright (c) 2016, 2018 by Delphix. All rights reserved. # . $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib @@ -49,6 +49,7 @@ function custom_cleanup set_vdev_validate_skip 0 cleanup log_must mdb_ctf_set_int vdev_min_ms_count 0t16 + log_must mdb_ctf_set_int spa_allocators 0t4 } log_onexit custom_cleanup @@ -207,6 +208,10 @@ increase_device_sizes $(( FILE_SIZE * 4 )) # reduce the chance of reusing a metaslab that holds old MOS metadata. log_must mdb_ctf_set_int vdev_min_ms_count 0t150 +# Decrease the number of allocators for pools created during this test, +# to increase the odds that metadata survives from old txgs. +log_must mdb_ctf_set_int spa_allocators 0t1 + # Part of the rewind test is to see how it reacts to path changes typeset pathstochange="$VDEV0 $VDEV1 $VDEV2 $VDEV3" diff --git a/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh b/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh index b9dbc6c97e..621ac23aa9 100644 --- a/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh @@ -26,7 +26,7 @@ # # -# Copyright (c) 2013, 2016 by Delphix. All rights reserved. +# Copyright (c) 2013, 2018 by Delphix. All rights reserved. # . $STF_SUITE/tests/functional/slog/slog.kshlib @@ -52,9 +52,19 @@ do log_must zpool create $TESTPOOL $type $VDEV $spare $SDEV \ log $LDEV + # Create a file to be corrupted + dd if=/dev/urandom of=/$TESTPOOL/filler bs=1024k count=50 + + # + # Ensure the file has been synced out before attempting to + # corrupt its contents. + # + sync + + # # Corrupt a pool device to make the pool DEGRADED - dd if=/dev/urandom of=/$TESTPOOL/filler bs=1024k count=50 # The oseek value below is to skip past the vdev label. + # log_must dd if=/dev/urandom of=$VDIR/a bs=1024k oseek=4 \ conv=notrunc count=50 log_must zpool scrub $TESTPOOL diff --git a/usr/src/tools/ndrgen/ndrgen.sh b/usr/src/tools/ndrgen/ndrgen.sh index c74253b6d2..19dbb9f8e5 100644 --- a/usr/src/tools/ndrgen/ndrgen.sh +++ b/usr/src/tools/ndrgen/ndrgen.sh @@ -19,16 +19,24 @@ # # CDDL HEADER END # + # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2013 Nexenta Systems, Inc. All rights reserved. +# # This is a wrapper script around the ndrgen compiler (ndrgen1). -# CC must be defined in the environment or on the command line. -NDRPROG="${0%/*}/ndrgen1" -INCDIR=${ROOT}/usr/include/smbsrv +NDRPROG="${0}1" + +# Note: most *.ndl files require an ANSI-compatible cpp, +# so we can NOT use /usr/lib/cpp or /usr/ccs/lib/cpp +# Wish there was an easier way to get an ANSI cpp. +CPP="${CC} -E" +CPPFLAGS="-DNDRGEN" +V_FLAG= PROGNAME=`basename $0` @@ -38,60 +46,61 @@ ndrgen_usage() print "$PROGNAME: ERROR: $1" fi - echo "usage: $PROGNAME [-Y cpp-path] file [file]..." + echo "usage: $PROGNAME [options] file.ndl [file.ndl]..." + echo " options: -Y cc-path -Ddefine -Iinclude" exit 1 } -# Copy header text from the input ndl file to the generated ndr C file. -ndrgen_copy_header() +# Process the input ndl file ($1) generating C code on stdout. +process() { - ndl_file=$1 - ndr_file=$2 + # Put the standard top matter + # + # Want the include directive to have just + # include "file.ndl" (no path) so... + inc_ndl=`basename $1` + cat - << EOF +/* + * Please do not edit this file. + * It was generated using ndrgen. + */ + +#include <strings.h> +#include <libmlrpc/ndr.h> +#include "$inc_ndl" +EOF + + # Put optional custom top matter nawk 'BEGIN { copy=0; } /^\/\* NDRGEN_HEADER_BEGIN \*\// { copy=1; next; } /^\/\* NDRGEN_HEADER_END \*\// { copy=0; next; } - /./ { if (copy==1) print; }' < $ndl_file > $ndr_file + /./ { if (copy==1) print; }' $1 + + # now the real ndrgen output + [ -n "$V_FLAG" ] && + echo "$CPP $CPPFLAGS $1 | $NDRPROG" >&2 + $CPP $CPPFLAGS $1 | $NDRPROG } -if [[ $# -lt 1 ]] ; then - ndrgen_usage -fi -while getopts "Y" FLAG $*; do +while getopts "D:I:Y:V" FLAG +do case $FLAG in - Y) - CC_FLAG="y" - ;; - *) - ndrgen_usage - ;; + D|I) CPPFLAGS="$CPPFLAGS -${FLAG}${OPTARG}";; + Y) CPP="$OPTARG";; + V) V_FLAG="V";; + *) ndrgen_usage;; esac done +shift $(($OPTIND - 1)) -if [[ $CC_FLAG = "y" ]] ; then - shift $(($OPTIND - 1)) - - if [[ $# -lt 1 ]] ; then - ndrgen_usage "C pre-processor path is missing" - else - CC=$1 - shift $(($OPTIND - 1)) - - # Check for cw being invoked with -_cc or -_gcc - if [[ $1 = "-_cc" || $1 = "-_gcc" ]] ; then - CC_ARG=$1 - shift $(($OPTIND - 1)) - fi - fi -fi - -if [[ $CC = "" ]] ; then - ndrgen_usage "C pre-processor is not defined" +if [[ $# -lt 1 ]] ; then + ndrgen_usage fi -if [ ! -f $CC ] || [ ! -x $CC ] ; then - ndrgen_usage "cannot run $CC" +if [ ! -x $CPP ] ; then + ndrgen_usage "cannot run $CPP" fi for i @@ -101,36 +110,9 @@ do exit 1 fi - BASENAME=`basename $i .ndl` - TMP_NAME=$BASENAME.ndl.c - - cp $i $TMP_NAME - - if $CC $CC_ARG -E -D__a64 -D__EXTENSIONS__ -D_FILE_OFFSET_BITS=64 \ - -I. -I${INCDIR} -I${INCDIR}/ndl -DNDRGEN $TMP_NAME | \ - $NDRPROG > $BASENAME.raw - then - touch ${BASENAME}_ndr.c - ndrgen_copy_header $i ${BASENAME}_ndr.c - - cat - << EOF >> ${BASENAME}_ndr.c -/* - * Please do not edit this file. - * It was generated using ndrgen. - */ - -#include <strings.h> -#include <smbsrv/ndr.h> -#include <smbsrv/ndl/$BASENAME.ndl> -EOF - - cat $BASENAME.raw >> ${BASENAME}_ndr.c - - rm -f $BASENAME.raw - rm -f $TMP_NAME - else - rm -f $BASENAME.raw - rm -f $TMP_NAME - exit 1 - fi + base=`basename $i .ndl` + process $i > ${base}_ndr.c || { + echo "ndrgen error"; + rm ${base}_ndr.c; + } done diff --git a/usr/src/tools/quick/make-smbclnt b/usr/src/tools/quick/make-smbclnt new file mode 100755 index 0000000000..1b65f50a71 --- /dev/null +++ b/usr/src/tools/quick/make-smbclnt @@ -0,0 +1,304 @@ +#!/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2014 Nexenta Systems, Inc. All rights reserved. +# + +# Use distributed make (dmake) by default. +make=${MAKE:-dmake} + +CLOSED_IS_PRESENT=no +export CLOSED_IS_PRESENT + +# Do this if you want to use dbx or gdb +# export SOURCEDEBUG=yes + +[ -n "$SRC" ] || { + echo "SRC not set. Run 'ws' or 'bldenv' first." + exit 1 +} + +cpu=`uname -p` +case $cpu in +i386) + x=intel + kmdb_arch="amd64" + mdb_arch="ia32 amd64" + arch64=amd64 + ;; +sparc) + x=sparc + kmdb_arch=v9 + mdb_arch="v7 v9" + arch64=sparcv9 + ;; +*) echo "Huh?" ; exit 1;; +esac + +################################################################ + +build_tools() { + test -f $SRC/tools/proto/root_i386-nd/opt/onbld/bin/genoffsets || + (cd $SRC/tools && $make install) + (cd $SRC/common/mapfiles; $make install) +} + +clobber_tools() { + (cd $SRC/tools && $make clobber) + (cd $SRC/common/mapfiles; $make clobber) +} + +################################################################ + +do_hdrs() { + +targ=$1 +if [ "$targ" = clobber ] +then + (cd $SRC/uts && $make -k clobber_h) + (cd $SRC/head && $make clobber) +fi + +if [ "$targ" = install ] +then + targ=install_h + + # Just the parts of "make sgs" we need, and + # skip them if they appear to be done. + # ... stuff under $SRC + test -f $SRC/uts/common/sys/priv_names.h || + (cd $SRC/uts && $make -k all_h) + + test -f $SRC/head/rpcsvc/nispasswd.h || + (cd $SRC/head && $make -k install_h) + + # ... stuff under $ROOT (proto area) + test -d $ROOT/usr/include/sys || + (cd $SRC && $make rootdirs) + test -f $ROOT/usr/include/sys/types.h || + (cd $SRC/uts && $make -k install_h) + test -f $ROOT/usr/include/rpcsvc/daemon_utils.h || + (cd $SRC/head && $make install_h) + + # always update the smb headers to be safe + (cd $SRC/uts/common/smb && $make -k install_h) + +fi + +# Need some library headers too... +for lib in \ + libcryptoutil \ + libmlrpc \ + libpam \ + libsec \ + libshare \ + libsmbfs \ + passwdutil +do + (cd $SRC/lib/$lib && $make $targ) +done +} + +################################################################ + +do_kern() { + case $1 in + lint) targ=modlintlib ;; + *) targ=$1 ;; + esac + ( unset SOURCEDEBUG ; + (cd $SRC/uts/$x/nsmb && $make $targ) ; + (cd $SRC/uts/$x/smbfs && $make $targ) ) +} + +################################################################ + +# Note lib1 builds prerequisite libraries not delivered by the +# tar file we create below. To accelerate clean/install, we +# skip these on clean (but still nuke them for clobber) + +do_lib1() { + : +} + +# lib2 builds stuff we include in the tar file, +# or that we don't mind rebuilding after clean. + +do_lib2() { + +(cd $SRC/lib/libsmbfs && $make $1) +[ "$1" = install ] && + (cd $SRC/lib/libsmbfs && $make _msg) +(cd $SRC/lib/libmlrpc && $make $1) +(cd $SRC/lib/libshare && $make $1 PLUGINS=smbfs) +(cd $SRC/lib/passwdutil && $make $1) +(cd $SRC/lib/pam_modules/smbfs && $make $1) + +} + +################################################################ + +do_cmds() { + +case $1 in +install) + # mount programs need fslib.o + (cd $SRC/cmd/fs.d && $make fslib.o) + (cd $SRC/cmd/fs.d/smbclnt && $make $1 catalog) + ;; +clean|clobber) + (cd $SRC/cmd/fs.d/smbclnt && $make $1) + (cd $SRC/cmd/fs.d && $make ${1}_local) + ;; +esac + +# Build the MDB modules, WITH the linktest +(cd $SRC/cmd/mdb/tools && $make $1) + +# kmdb_arch is 64-bit only +for a in $kmdb_arch +do + case $1 in + install|lint) + (cd $SRC/cmd/mdb/$x/$a/kmdb && + $make kmdb_modlinktest.o ) + ;; + clean|clobber) + (cd $SRC/cmd/mdb/$x/$a/kmdb && + $make -k $1 ) + ;; + esac + + (cd $SRC/cmd/mdb/$x/$a/nsmb && + $make $1 KMDB_LINKTEST_ENABLE= ) + (cd $SRC/cmd/mdb/$x/$a/smbfs && + $make $1 KMDB_LINKTEST_ENABLE= ) +done +} + + +################################################################ +# This builds $SRC/TAGS (and cscope.files) in a helpful order. + +do_tags() { + (cd $SRC ; + find uts/common/sys -name '*.[ch]' -print |sort + find uts/common/net -name '*.[ch]' -print |sort + find uts/common/netinet -name '*.[ch]' -print |sort + find uts/common/smb -name '*.[ch]' -print |sort + find uts/common/netsmb -name '*.[ch]' -print |sort + find uts/common/fs/smbclnt -name '*.[ch]' -print |sort + find head -name '*.h' -print |sort + find lib/libsmbfs -name '*.[ch]' -print |sort + find cmd/fs.d/smbclnt -name '*.[ch]' -print |sort + find common/smbclnt -name '*.[ch]' -print |sort + ) > $SRC/cscope.files + + (cd $SRC ; + exctags -e --langmap=c:+.ndl -h ndl -L - < cscope.files + cscope -b ) +} + +################################################################ +# This creates a tarfile one can use to update a test machine. + +do_tar() { + git_rev=`git rev-parse --short=8 HEAD` + files=" +lib/svc/manifest/network/smb/client.xml +lib/svc/method/smb-client +opt/smbcl-tests/tests/srvenum +opt/smbcl-tests/tests/srvinfo +opt/smbcl-tests/tests/tconn +usr/bin/smbutil +usr/kernel/drv/$arch64/nsmb +usr/kernel/fs/$arch64/smbfs +usr/kernel/kmdb/$arch64/nsmb +usr/kernel/kmdb/$arch64/smbfs +usr/lib/$arch64/libsmbfs.so.1 +usr/lib/fs/smbfs/$arch64/libshare_smbfs.so.1 +usr/lib/fs/smbfs/chacl +usr/lib/fs/smbfs/dfshares +usr/lib/fs/smbfs/libshare_smbfs.so.1 +usr/lib/fs/smbfs/lsacl +usr/lib/fs/smbfs/mount +usr/lib/fs/smbfs/share +usr/lib/fs/smbfs/umount +usr/lib/fs/smbfs/unshare +usr/lib/libmlrpc.so.2 +usr/lib/libsmbfs.so.1 +usr/lib/mdb/kvm/$arch64/nsmb.so +usr/lib/mdb/kvm/$arch64/smbfs.so +usr/lib/mdb/kvm/nsmb.so +usr/lib/mdb/kvm/smbfs.so +usr/lib/security/$arch64/pam_smbfs_login.so.1 +usr/lib/security/pam_smbfs_login.so.1 +usr/lib/smbfs/smbiod +usr/lib/smbfs/smbiod-svc +" + + (cd $ROOT && tar cfj ../../smbclnt-${git_rev}.tar.bz2 $files) +} + +################################################################ + +if [ "$1" = "" ]; then + set '?' # force usage +fi + +set -x + +for arg +do + case "$arg" in + install) + build_tools + set -e + do_hdrs $arg + do_kern $arg + do_lib1 $arg + do_lib2 $arg + do_cmds $arg + ;; + lint) + do_kern $arg + do_lib1 $arg + do_lib2 $arg + do_cmds $arg + ;; + clean) + # intentionally skip: lib1, hdrs, tools + do_cmds $arg + do_lib2 $arg + do_kern $arg + ;; + clobber) + do_cmds $arg + do_lib2 $arg + do_lib1 $arg + do_kern $arg + do_hdrs $arg + clobber_tools + ;; + tags) + do_tags + ;; + tar) + do_tar + ;; + *) + echo "Usage: $0 {install|lint|clean|clobber|tags|tar}"; + exit 1; + ;; + esac +done diff --git a/usr/src/tools/quick/make-smbsrv b/usr/src/tools/quick/make-smbsrv index e808bffee2..18c1baddcf 100755 --- a/usr/src/tools/quick/make-smbsrv +++ b/usr/src/tools/quick/make-smbsrv @@ -107,8 +107,9 @@ for lib in \ libdevid \ libfakekernel \ libgss \ - libkrb5 \ libidmap \ + libkrb5 \ + libmlrpc \ libpam \ libsec \ libscf \ @@ -164,7 +165,8 @@ do_lib2() { for lib in \ libfakekernel \ libads \ - libsmbfs + libsmbfs \ + libmlrpc do (cd $SRC/lib/$lib && $make $1) done @@ -287,7 +289,7 @@ usr/lib/mdb/kvm/$arch64/smbsrv.so usr/lib/reparse/libreparse_smb.so.1 usr/lib/security/pam_smb_passwd.so.1 usr/lib/smbsrv/dtrace -usr/lib/smbsrv/libmlrpc.so.1 +usr/lib/libmlrpc.so.2 usr/lib/smbsrv/libmlsvc.so.1 usr/lib/smbsrv/libsmb.so.1 usr/lib/smbsrv/libsmbns.so.1 diff --git a/usr/src/uts/common/fs/zfs/metaslab.c b/usr/src/uts/common/fs/zfs/metaslab.c index 82ca2d6cbf..1f5a7fbd26 100644 --- a/usr/src/uts/common/fs/zfs/metaslab.c +++ b/usr/src/uts/common/fs/zfs/metaslab.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2015 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -217,6 +217,8 @@ static uint64_t metaslab_weight(metaslab_t *); static void metaslab_set_fragmentation(metaslab_t *); static void metaslab_free_impl(vdev_t *, uint64_t, uint64_t, boolean_t); static void metaslab_check_free_impl(vdev_t *, uint64_t, uint64_t); +static void metaslab_passivate(metaslab_t *msp, uint64_t weight); +static uint64_t metaslab_weight_from_range_tree(metaslab_t *msp); kmem_cache_t *metaslab_alloc_trace_cache; @@ -236,7 +238,12 @@ metaslab_class_create(spa_t *spa, metaslab_ops_t *ops) mc->mc_rotor = NULL; mc->mc_ops = ops; mutex_init(&mc->mc_lock, NULL, MUTEX_DEFAULT, NULL); - refcount_create_tracked(&mc->mc_alloc_slots); + mc->mc_alloc_slots = kmem_zalloc(spa->spa_alloc_count * + sizeof (refcount_t), KM_SLEEP); + mc->mc_alloc_max_slots = kmem_zalloc(spa->spa_alloc_count * + sizeof (uint64_t), KM_SLEEP); + for (int i = 0; i < spa->spa_alloc_count; i++) + refcount_create_tracked(&mc->mc_alloc_slots[i]); return (mc); } @@ -250,7 +257,12 @@ metaslab_class_destroy(metaslab_class_t *mc) ASSERT(mc->mc_space == 0); ASSERT(mc->mc_dspace == 0); - refcount_destroy(&mc->mc_alloc_slots); + for (int i = 0; i < mc->mc_spa->spa_alloc_count; i++) + refcount_destroy(&mc->mc_alloc_slots[i]); + kmem_free(mc->mc_alloc_slots, mc->mc_spa->spa_alloc_count * + sizeof (refcount_t)); + kmem_free(mc->mc_alloc_max_slots, mc->mc_spa->spa_alloc_count * + sizeof (uint64_t)); mutex_destroy(&mc->mc_lock); kmem_free(mc, sizeof (metaslab_class_t)); } @@ -447,6 +459,30 @@ metaslab_compare(const void *x1, const void *x2) const metaslab_t *m1 = x1; const metaslab_t *m2 = x2; + int sort1 = 0; + int sort2 = 0; + if (m1->ms_allocator != -1 && m1->ms_primary) + sort1 = 1; + else if (m1->ms_allocator != -1 && !m1->ms_primary) + sort1 = 2; + if (m2->ms_allocator != -1 && m2->ms_primary) + sort2 = 1; + else if (m2->ms_allocator != -1 && !m2->ms_primary) + sort2 = 2; + + /* + * Sort inactive metaslabs first, then primaries, then secondaries. When + * selecting a metaslab to allocate from, an allocator first tries its + * primary, then secondary active metaslab. If it doesn't have active + * metaslabs, or can't allocate from them, it searches for an inactive + * metaslab to activate. If it can't find a suitable one, it will steal + * a primary or secondary metaslab from another allocator. + */ + if (sort1 < sort2) + return (-1); + if (sort1 > sort2) + return (1); + if (m1->ms_weight < m2->ms_weight) return (1); if (m1->ms_weight > m2->ms_weight) @@ -598,12 +634,16 @@ metaslab_group_alloc_update(metaslab_group_t *mg) } metaslab_group_t * -metaslab_group_create(metaslab_class_t *mc, vdev_t *vd) +metaslab_group_create(metaslab_class_t *mc, vdev_t *vd, int allocators) { metaslab_group_t *mg; mg = kmem_zalloc(sizeof (metaslab_group_t), KM_SLEEP); mutex_init(&mg->mg_lock, NULL, MUTEX_DEFAULT, NULL); + mg->mg_primaries = kmem_zalloc(allocators * sizeof (metaslab_t *), + KM_SLEEP); + mg->mg_secondaries = kmem_zalloc(allocators * sizeof (metaslab_t *), + KM_SLEEP); avl_create(&mg->mg_metaslab_tree, metaslab_compare, sizeof (metaslab_t), offsetof(struct metaslab, ms_group_node)); mg->mg_vd = vd; @@ -611,7 +651,16 @@ metaslab_group_create(metaslab_class_t *mc, vdev_t *vd) mg->mg_activation_count = 0; mg->mg_initialized = B_FALSE; mg->mg_no_free_space = B_TRUE; - refcount_create_tracked(&mg->mg_alloc_queue_depth); + mg->mg_allocators = allocators; + + mg->mg_alloc_queue_depth = kmem_zalloc(allocators * sizeof (refcount_t), + KM_SLEEP); + mg->mg_cur_max_alloc_queue_depth = kmem_zalloc(allocators * + sizeof (uint64_t), KM_SLEEP); + for (int i = 0; i < allocators; i++) { + refcount_create_tracked(&mg->mg_alloc_queue_depth[i]); + mg->mg_cur_max_alloc_queue_depth[i] = 0; + } mg->mg_taskq = taskq_create("metaslab_group_taskq", metaslab_load_pct, minclsyspri, 10, INT_MAX, TASKQ_THREADS_CPU_PCT); @@ -633,8 +682,20 @@ metaslab_group_destroy(metaslab_group_t *mg) taskq_destroy(mg->mg_taskq); avl_destroy(&mg->mg_metaslab_tree); + kmem_free(mg->mg_primaries, mg->mg_allocators * sizeof (metaslab_t *)); + kmem_free(mg->mg_secondaries, mg->mg_allocators * + sizeof (metaslab_t *)); mutex_destroy(&mg->mg_lock); - refcount_destroy(&mg->mg_alloc_queue_depth); + + for (int i = 0; i < mg->mg_allocators; i++) { + refcount_destroy(&mg->mg_alloc_queue_depth[i]); + mg->mg_cur_max_alloc_queue_depth[i] = 0; + } + kmem_free(mg->mg_alloc_queue_depth, mg->mg_allocators * + sizeof (refcount_t)); + kmem_free(mg->mg_cur_max_alloc_queue_depth, mg->mg_allocators * + sizeof (uint64_t)); + kmem_free(mg, sizeof (metaslab_group_t)); } @@ -713,6 +774,22 @@ metaslab_group_passivate(metaslab_group_t *mg) taskq_wait(mg->mg_taskq); spa_config_enter(spa, locks & ~(SCL_ZIO - 1), spa, RW_WRITER); metaslab_group_alloc_update(mg); + for (int i = 0; i < mg->mg_allocators; i++) { + metaslab_t *msp = mg->mg_primaries[i]; + if (msp != NULL) { + mutex_enter(&msp->ms_lock); + metaslab_passivate(msp, + metaslab_weight_from_range_tree(msp)); + mutex_exit(&msp->ms_lock); + } + msp = mg->mg_secondaries[i]; + if (msp != NULL) { + mutex_enter(&msp->ms_lock); + metaslab_passivate(msp, + metaslab_weight_from_range_tree(msp)); + mutex_exit(&msp->ms_lock); + } + } mgprev = mg->mg_prev; mgnext = mg->mg_next; @@ -853,6 +930,17 @@ metaslab_group_remove(metaslab_group_t *mg, metaslab_t *msp) } static void +metaslab_group_sort_impl(metaslab_group_t *mg, metaslab_t *msp, uint64_t weight) +{ + ASSERT(MUTEX_HELD(&mg->mg_lock)); + ASSERT(msp->ms_group == mg); + avl_remove(&mg->mg_metaslab_tree, msp); + msp->ms_weight = weight; + avl_add(&mg->mg_metaslab_tree, msp); + +} + +static void metaslab_group_sort(metaslab_group_t *mg, metaslab_t *msp, uint64_t weight) { /* @@ -863,10 +951,7 @@ metaslab_group_sort(metaslab_group_t *mg, metaslab_t *msp, uint64_t weight) ASSERT(MUTEX_HELD(&msp->ms_lock)); mutex_enter(&mg->mg_lock); - ASSERT(msp->ms_group == mg); - avl_remove(&mg->mg_metaslab_tree, msp); - msp->ms_weight = weight; - avl_add(&mg->mg_metaslab_tree, msp); + metaslab_group_sort_impl(mg, msp, weight); mutex_exit(&mg->mg_lock); } @@ -914,7 +999,7 @@ metaslab_group_fragmentation(metaslab_group_t *mg) */ static boolean_t metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor, - uint64_t psize) + uint64_t psize, int allocator) { spa_t *spa = mg->mg_vd->vdev_spa; metaslab_class_t *mc = mg->mg_class; @@ -943,7 +1028,7 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor, if (mg->mg_allocatable) { metaslab_group_t *mgp; int64_t qdepth; - uint64_t qmax = mg->mg_max_alloc_queue_depth; + uint64_t qmax = mg->mg_cur_max_alloc_queue_depth[allocator]; if (!mc->mc_alloc_throttle_enabled) return (B_TRUE); @@ -955,7 +1040,7 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor, if (mg->mg_no_free_space) return (B_FALSE); - qdepth = refcount_count(&mg->mg_alloc_queue_depth); + qdepth = refcount_count(&mg->mg_alloc_queue_depth[allocator]); /* * If this metaslab group is below its qmax or it's @@ -974,9 +1059,10 @@ metaslab_group_allocatable(metaslab_group_t *mg, metaslab_group_t *rotor, * groups at the same time when we make this check. */ for (mgp = mg->mg_next; mgp != rotor; mgp = mgp->mg_next) { - qmax = mgp->mg_max_alloc_queue_depth; + qmax = mgp->mg_cur_max_alloc_queue_depth[allocator]; - qdepth = refcount_count(&mgp->mg_alloc_queue_depth); + qdepth = refcount_count( + &mgp->mg_alloc_queue_depth[allocator]); /* * If there is another metaslab group that @@ -1463,6 +1549,8 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg, ms->ms_id = id; ms->ms_start = id << vd->vdev_ms_shift; ms->ms_size = 1ULL << vd->vdev_ms_shift; + ms->ms_allocator = -1; + ms->ms_new = B_TRUE; /* * We only open space map objects that already exist. All others @@ -1558,6 +1646,7 @@ metaslab_fini(metaslab_t *msp) cv_destroy(&msp->ms_load_cv); mutex_destroy(&msp->ms_lock); mutex_destroy(&msp->ms_sync_lock); + ASSERT3U(msp->ms_allocator, ==, -1); kmem_free(msp, sizeof (metaslab_t)); } @@ -1954,19 +2043,59 @@ metaslab_weight(metaslab_t *msp) } static int -metaslab_activate(metaslab_t *msp, uint64_t activation_weight) +metaslab_activate_allocator(metaslab_group_t *mg, metaslab_t *msp, + int allocator, uint64_t activation_weight) +{ + /* + * If we're activating for the claim code, we don't want to actually + * set the metaslab up for a specific allocator. + */ + if (activation_weight == METASLAB_WEIGHT_CLAIM) + return (0); + metaslab_t **arr = (activation_weight == METASLAB_WEIGHT_PRIMARY ? + mg->mg_primaries : mg->mg_secondaries); + + ASSERT(MUTEX_HELD(&msp->ms_lock)); + mutex_enter(&mg->mg_lock); + if (arr[allocator] != NULL) { + mutex_exit(&mg->mg_lock); + return (EEXIST); + } + + arr[allocator] = msp; + ASSERT3S(msp->ms_allocator, ==, -1); + msp->ms_allocator = allocator; + msp->ms_primary = (activation_weight == METASLAB_WEIGHT_PRIMARY); + mutex_exit(&mg->mg_lock); + + return (0); +} + +static int +metaslab_activate(metaslab_t *msp, int allocator, uint64_t activation_weight) { ASSERT(MUTEX_HELD(&msp->ms_lock)); if ((msp->ms_weight & METASLAB_ACTIVE_MASK) == 0) { + int error = 0; metaslab_load_wait(msp); if (!msp->ms_loaded) { - int error = metaslab_load(msp); - if (error) { + if ((error = metaslab_load(msp)) != 0) { metaslab_group_sort(msp->ms_group, msp, 0); return (error); } } + if ((msp->ms_weight & METASLAB_ACTIVE_MASK) != 0) { + /* + * The metaslab was activated for another allocator + * while we were waiting, we should reselect. + */ + return (EBUSY); + } + if ((error = metaslab_activate_allocator(msp->ms_group, msp, + allocator, activation_weight)) != 0) { + return (error); + } msp->ms_activation_weight = msp->ms_weight; metaslab_group_sort(msp->ms_group, msp, @@ -1979,6 +2108,34 @@ metaslab_activate(metaslab_t *msp, uint64_t activation_weight) } static void +metaslab_passivate_allocator(metaslab_group_t *mg, metaslab_t *msp, + uint64_t weight) +{ + ASSERT(MUTEX_HELD(&msp->ms_lock)); + if (msp->ms_weight & METASLAB_WEIGHT_CLAIM) { + metaslab_group_sort(mg, msp, weight); + return; + } + + mutex_enter(&mg->mg_lock); + ASSERT3P(msp->ms_group, ==, mg); + if (msp->ms_primary) { + ASSERT3U(0, <=, msp->ms_allocator); + ASSERT3U(msp->ms_allocator, <, mg->mg_allocators); + ASSERT3P(mg->mg_primaries[msp->ms_allocator], ==, msp); + ASSERT(msp->ms_weight & METASLAB_WEIGHT_PRIMARY); + mg->mg_primaries[msp->ms_allocator] = NULL; + } else { + ASSERT(msp->ms_weight & METASLAB_WEIGHT_SECONDARY); + ASSERT3P(mg->mg_secondaries[msp->ms_allocator], ==, msp); + mg->mg_secondaries[msp->ms_allocator] = NULL; + } + msp->ms_allocator = -1; + metaslab_group_sort_impl(mg, msp, weight); + mutex_exit(&mg->mg_lock); +} + +static void metaslab_passivate(metaslab_t *msp, uint64_t weight) { uint64_t size = weight & ~METASLAB_WEIGHT_TYPE; @@ -1993,7 +2150,7 @@ metaslab_passivate(metaslab_t *msp, uint64_t weight) ASSERT0(weight & METASLAB_ACTIVE_MASK); msp->ms_activation_weight = 0; - metaslab_group_sort(msp->ms_group, msp, weight); + metaslab_passivate_allocator(msp->ms_group, msp, weight); ASSERT((msp->ms_weight & METASLAB_ACTIVE_MASK) == 0); } @@ -2550,11 +2707,18 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) vdev_dirty(vd, VDD_METASLAB, msp, txg + 1); } + if (msp->ms_new) { + msp->ms_new = B_FALSE; + mutex_enter(&mg->mg_lock); + mg->mg_ms_ready++; + mutex_exit(&mg->mg_lock); + } /* * Calculate the new weights before unloading any metaslabs. * This will give us the most accurate weighting. */ - metaslab_group_sort(mg, msp, metaslab_weight(msp)); + metaslab_group_sort(mg, msp, metaslab_weight(msp) | + (msp->ms_weight & METASLAB_ACTIVE_MASK)); /* * If the metaslab is loaded and we've not tried to load or allocate @@ -2566,6 +2730,10 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) VERIFY0(range_tree_space( msp->ms_allocating[(txg + t) & TXG_MASK])); } + if (msp->ms_allocator != -1) { + metaslab_passivate(msp, msp->ms_weight & + ~METASLAB_ACTIVE_MASK); + } if (!metaslab_debug_unload) metaslab_unload(msp); @@ -2659,7 +2827,8 @@ metaslab_alloc_trace_fini(void) */ static void metaslab_trace_add(zio_alloc_list_t *zal, metaslab_group_t *mg, - metaslab_t *msp, uint64_t psize, uint32_t dva_id, uint64_t offset) + metaslab_t *msp, uint64_t psize, uint32_t dva_id, uint64_t offset, + int allocator) { if (!metaslab_trace_enabled) return; @@ -2692,6 +2861,7 @@ metaslab_trace_add(zio_alloc_list_t *zal, metaslab_group_t *mg, mat->mat_dva_id = dva_id; mat->mat_offset = offset; mat->mat_weight = 0; + mat->mat_allocator = allocator; if (msp != NULL) mat->mat_weight = msp->ms_weight; @@ -2732,35 +2902,56 @@ metaslab_trace_fini(zio_alloc_list_t *zal) */ static void -metaslab_group_alloc_increment(spa_t *spa, uint64_t vdev, void *tag, int flags) +metaslab_group_alloc_increment(spa_t *spa, uint64_t vdev, void *tag, int flags, + int allocator) { if (!(flags & METASLAB_ASYNC_ALLOC) || - flags & METASLAB_DONT_THROTTLE) + (flags & METASLAB_DONT_THROTTLE)) return; metaslab_group_t *mg = vdev_lookup_top(spa, vdev)->vdev_mg; if (!mg->mg_class->mc_alloc_throttle_enabled) return; - (void) refcount_add(&mg->mg_alloc_queue_depth, tag); + (void) refcount_add(&mg->mg_alloc_queue_depth[allocator], tag); +} + +static void +metaslab_group_increment_qdepth(metaslab_group_t *mg, int allocator) +{ + uint64_t max = mg->mg_max_alloc_queue_depth; + uint64_t cur = mg->mg_cur_max_alloc_queue_depth[allocator]; + while (cur < max) { + if (atomic_cas_64(&mg->mg_cur_max_alloc_queue_depth[allocator], + cur, cur + 1) == cur) { + atomic_inc_64( + &mg->mg_class->mc_alloc_max_slots[allocator]); + return; + } + cur = mg->mg_cur_max_alloc_queue_depth[allocator]; + } } void -metaslab_group_alloc_decrement(spa_t *spa, uint64_t vdev, void *tag, int flags) +metaslab_group_alloc_decrement(spa_t *spa, uint64_t vdev, void *tag, int flags, + int allocator, boolean_t io_complete) { if (!(flags & METASLAB_ASYNC_ALLOC) || - flags & METASLAB_DONT_THROTTLE) + (flags & METASLAB_DONT_THROTTLE)) return; metaslab_group_t *mg = vdev_lookup_top(spa, vdev)->vdev_mg; if (!mg->mg_class->mc_alloc_throttle_enabled) return; - (void) refcount_remove(&mg->mg_alloc_queue_depth, tag); + (void) refcount_remove(&mg->mg_alloc_queue_depth[allocator], tag); + if (io_complete) + metaslab_group_increment_qdepth(mg, allocator); } void -metaslab_group_alloc_verify(spa_t *spa, const blkptr_t *bp, void *tag) +metaslab_group_alloc_verify(spa_t *spa, const blkptr_t *bp, void *tag, + int allocator) { #ifdef ZFS_DEBUG const dva_t *dva = bp->blk_dva; @@ -2769,7 +2960,8 @@ metaslab_group_alloc_verify(spa_t *spa, const blkptr_t *bp, void *tag) for (int d = 0; d < ndvas; d++) { uint64_t vdev = DVA_GET_VDEV(&dva[d]); metaslab_group_t *mg = vdev_lookup_top(spa, vdev)->vdev_mg; - VERIFY(refcount_not_held(&mg->mg_alloc_queue_depth, tag)); + VERIFY(refcount_not_held(&mg->mg_alloc_queue_depth[allocator], + tag)); } #endif } @@ -2811,91 +3003,146 @@ metaslab_block_alloc(metaslab_t *msp, uint64_t size, uint64_t txg) return (start); } +/* + * Find the metaslab with the highest weight that is less than what we've + * already tried. In the common case, this means that we will examine each + * metaslab at most once. Note that concurrent callers could reorder metaslabs + * by activation/passivation once we have dropped the mg_lock. If a metaslab is + * activated by another thread, and we fail to allocate from the metaslab we + * have selected, we may not try the newly-activated metaslab, and instead + * activate another metaslab. This is not optimal, but generally does not cause + * any problems (a possible exception being if every metaslab is completely full + * except for the the newly-activated metaslab which we fail to examine). + */ +static metaslab_t * +find_valid_metaslab(metaslab_group_t *mg, uint64_t activation_weight, + dva_t *dva, int d, uint64_t min_distance, uint64_t asize, int allocator, + zio_alloc_list_t *zal, metaslab_t *search, boolean_t *was_active) +{ + avl_index_t idx; + avl_tree_t *t = &mg->mg_metaslab_tree; + metaslab_t *msp = avl_find(t, search, &idx); + if (msp == NULL) + msp = avl_nearest(t, idx, AVL_AFTER); + + for (; msp != NULL; msp = AVL_NEXT(t, msp)) { + int i; + if (!metaslab_should_allocate(msp, asize)) { + metaslab_trace_add(zal, mg, msp, asize, d, + TRACE_TOO_SMALL, allocator); + continue; + } + + /* + * If the selected metaslab is condensing, skip it. + */ + if (msp->ms_condensing) + continue; + + *was_active = msp->ms_allocator != -1; + /* + * If we're activating as primary, this is our first allocation + * from this disk, so we don't need to check how close we are. + * If the metaslab under consideration was already active, + * we're getting desperate enough to steal another allocator's + * metaslab, so we still don't care about distances. + */ + if (activation_weight == METASLAB_WEIGHT_PRIMARY || *was_active) + break; + + uint64_t target_distance = min_distance + + (space_map_allocated(msp->ms_sm) != 0 ? 0 : + min_distance >> 1); + + for (i = 0; i < d; i++) { + if (metaslab_distance(msp, &dva[i]) < target_distance) + break; + } + if (i == d) + break; + } + + if (msp != NULL) { + search->ms_weight = msp->ms_weight; + search->ms_start = msp->ms_start + 1; + search->ms_allocator = msp->ms_allocator; + search->ms_primary = msp->ms_primary; + } + return (msp); +} + +/* ARGSUSED */ static uint64_t metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, - uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d) + uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d, + int allocator) { metaslab_t *msp = NULL; uint64_t offset = -1ULL; uint64_t activation_weight; - uint64_t target_distance; - int i; + boolean_t tertiary = B_FALSE; activation_weight = METASLAB_WEIGHT_PRIMARY; - for (i = 0; i < d; i++) { - if (DVA_GET_VDEV(&dva[i]) == mg->mg_vd->vdev_id) { + for (int i = 0; i < d; i++) { + if (activation_weight == METASLAB_WEIGHT_PRIMARY && + DVA_GET_VDEV(&dva[i]) == mg->mg_vd->vdev_id) { activation_weight = METASLAB_WEIGHT_SECONDARY; + } else if (activation_weight == METASLAB_WEIGHT_SECONDARY && + DVA_GET_VDEV(&dva[i]) == mg->mg_vd->vdev_id) { + tertiary = B_TRUE; break; } } + /* + * If we don't have enough metaslabs active to fill the entire array, we + * just use the 0th slot. + */ + if (mg->mg_ms_ready < mg->mg_allocators * 2) { + tertiary = B_FALSE; + allocator = 0; + } + + ASSERT3U(mg->mg_vd->vdev_ms_count, >=, 2); + metaslab_t *search = kmem_alloc(sizeof (*search), KM_SLEEP); search->ms_weight = UINT64_MAX; search->ms_start = 0; + /* + * At the end of the metaslab tree are the already-active metaslabs, + * first the primaries, then the secondaries. When we resume searching + * through the tree, we need to consider ms_allocator and ms_primary so + * we start in the location right after where we left off, and don't + * accidentally loop forever considering the same metaslabs. + */ + search->ms_allocator = -1; + search->ms_primary = B_TRUE; for (;;) { - boolean_t was_active; - avl_tree_t *t = &mg->mg_metaslab_tree; - avl_index_t idx; + boolean_t was_active = B_FALSE; mutex_enter(&mg->mg_lock); - /* - * Find the metaslab with the highest weight that is less - * than what we've already tried. In the common case, this - * means that we will examine each metaslab at most once. - * Note that concurrent callers could reorder metaslabs - * by activation/passivation once we have dropped the mg_lock. - * If a metaslab is activated by another thread, and we fail - * to allocate from the metaslab we have selected, we may - * not try the newly-activated metaslab, and instead activate - * another metaslab. This is not optimal, but generally - * does not cause any problems (a possible exception being - * if every metaslab is completely full except for the - * the newly-activated metaslab which we fail to examine). - */ - msp = avl_find(t, search, &idx); - if (msp == NULL) - msp = avl_nearest(t, idx, AVL_AFTER); - for (; msp != NULL; msp = AVL_NEXT(t, msp)) { - - if (!metaslab_should_allocate(msp, asize)) { - metaslab_trace_add(zal, mg, msp, asize, d, - TRACE_TOO_SMALL); - continue; - } - - /* - * If the selected metaslab is condensing, skip it. - */ - if (msp->ms_condensing) - continue; - - was_active = msp->ms_weight & METASLAB_ACTIVE_MASK; - if (activation_weight == METASLAB_WEIGHT_PRIMARY) - break; - - target_distance = min_distance + - (space_map_allocated(msp->ms_sm) != 0 ? 0 : - min_distance >> 1); - - for (i = 0; i < d; i++) { - if (metaslab_distance(msp, &dva[i]) < - target_distance) - break; - } - if (i == d) - break; + if (activation_weight == METASLAB_WEIGHT_PRIMARY && + mg->mg_primaries[allocator] != NULL) { + msp = mg->mg_primaries[allocator]; + was_active = B_TRUE; + } else if (activation_weight == METASLAB_WEIGHT_SECONDARY && + mg->mg_secondaries[allocator] != NULL && !tertiary) { + msp = mg->mg_secondaries[allocator]; + was_active = B_TRUE; + } else { + msp = find_valid_metaslab(mg, activation_weight, dva, d, + min_distance, asize, allocator, zal, search, + &was_active); } + mutex_exit(&mg->mg_lock); if (msp == NULL) { kmem_free(search, sizeof (*search)); return (-1ULL); } - search->ms_weight = msp->ms_weight; - search->ms_start = msp->ms_start + 1; mutex_enter(&msp->ms_lock); - /* * Ensure that the metaslab we have selected is still * capable of handling our request. It's possible that @@ -2909,18 +3156,32 @@ metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, continue; } - if ((msp->ms_weight & METASLAB_WEIGHT_SECONDARY) && - activation_weight == METASLAB_WEIGHT_PRIMARY) { - metaslab_passivate(msp, - msp->ms_weight & ~METASLAB_ACTIVE_MASK); + /* + * If the metaslab is freshly activated for an allocator that + * isn't the one we're allocating from, or if it's a primary and + * we're seeking a secondary (or vice versa), we go back and + * select a new metaslab. + */ + if (!was_active && (msp->ms_weight & METASLAB_ACTIVE_MASK) && + (msp->ms_allocator != -1) && + (msp->ms_allocator != allocator || ((activation_weight == + METASLAB_WEIGHT_PRIMARY) != msp->ms_primary))) { mutex_exit(&msp->ms_lock); continue; } - if (metaslab_activate(msp, activation_weight) != 0) { + if (msp->ms_weight & METASLAB_WEIGHT_CLAIM) { + metaslab_passivate(msp, msp->ms_weight & + ~METASLAB_WEIGHT_CLAIM); mutex_exit(&msp->ms_lock); continue; } + + if (metaslab_activate(msp, allocator, activation_weight) != 0) { + mutex_exit(&msp->ms_lock); + continue; + } + msp->ms_selected_txg = txg; /* @@ -2933,7 +3194,7 @@ metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, if (!metaslab_should_allocate(msp, asize)) { /* Passivate this metaslab and select a new one. */ metaslab_trace_add(zal, mg, msp, asize, d, - TRACE_TOO_SMALL); + TRACE_TOO_SMALL, allocator); goto next; } @@ -2944,13 +3205,15 @@ metaslab_group_alloc_normal(metaslab_group_t *mg, zio_alloc_list_t *zal, */ if (msp->ms_condensing) { metaslab_trace_add(zal, mg, msp, asize, d, - TRACE_CONDENSING); + TRACE_CONDENSING, allocator); + metaslab_passivate(msp, msp->ms_weight & + ~METASLAB_ACTIVE_MASK); mutex_exit(&msp->ms_lock); continue; } offset = metaslab_block_alloc(msp, asize, txg); - metaslab_trace_add(zal, mg, msp, asize, d, offset); + metaslab_trace_add(zal, mg, msp, asize, d, offset, allocator); if (offset != -1ULL) { /* Proactively passivate the metaslab, if needed */ @@ -3006,19 +3269,20 @@ next: static uint64_t metaslab_group_alloc(metaslab_group_t *mg, zio_alloc_list_t *zal, - uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d) + uint64_t asize, uint64_t txg, uint64_t min_distance, dva_t *dva, int d, + int allocator) { uint64_t offset; ASSERT(mg->mg_initialized); offset = metaslab_group_alloc_normal(mg, zal, asize, txg, - min_distance, dva, d); + min_distance, dva, d, allocator); mutex_enter(&mg->mg_lock); if (offset == -1ULL) { mg->mg_failed_allocations++; metaslab_trace_add(zal, mg, NULL, asize, d, - TRACE_GROUP_FAILURE); + TRACE_GROUP_FAILURE, allocator); if (asize == SPA_GANGBLOCKSIZE) { /* * This metaslab group was unable to allocate @@ -3053,7 +3317,7 @@ int ditto_same_vdev_distance_shift = 3; int metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize, dva_t *dva, int d, dva_t *hintdva, uint64_t txg, int flags, - zio_alloc_list_t *zal) + zio_alloc_list_t *zal, int allocator) { metaslab_group_t *mg, *rotor; vdev_t *vd; @@ -3065,7 +3329,8 @@ metaslab_alloc_dva(spa_t *spa, metaslab_class_t *mc, uint64_t psize, * For testing, make some blocks above a certain size be gang blocks. */ if (psize >= metaslab_force_ganging && (ddi_get_lbolt() & 3) == 0) { - metaslab_trace_add(zal, NULL, NULL, psize, d, TRACE_FORCE_GANG); + metaslab_trace_add(zal, NULL, NULL, psize, d, TRACE_FORCE_GANG, + allocator); return (SET_ERROR(ENOSPC)); } @@ -3151,12 +3416,12 @@ top: */ if (allocatable && !GANG_ALLOCATION(flags) && !try_hard) { allocatable = metaslab_group_allocatable(mg, rotor, - psize); + psize, allocator); } if (!allocatable) { metaslab_trace_add(zal, mg, NULL, psize, d, - TRACE_NOT_ALLOCATABLE); + TRACE_NOT_ALLOCATABLE, allocator); goto next; } @@ -3171,7 +3436,7 @@ top: vd->vdev_state < VDEV_STATE_HEALTHY) && d == 0 && !try_hard && vd->vdev_children == 0) { metaslab_trace_add(zal, mg, NULL, psize, d, - TRACE_VDEV_ERROR); + TRACE_VDEV_ERROR, allocator); goto next; } @@ -3195,7 +3460,7 @@ top: ASSERT(P2PHASE(asize, 1ULL << vd->vdev_ashift) == 0); uint64_t offset = metaslab_group_alloc(mg, zal, asize, txg, - distance, dva, d); + distance, dva, d, allocator); if (offset != -1ULL) { /* @@ -3258,7 +3523,7 @@ next: bzero(&dva[d], sizeof (dva_t)); - metaslab_trace_add(zal, rotor, NULL, psize, d, TRACE_ENOSPC); + metaslab_trace_add(zal, rotor, NULL, psize, d, TRACE_ENOSPC, allocator); return (SET_ERROR(ENOSPC)); } @@ -3559,18 +3824,20 @@ metaslab_free_dva(spa_t *spa, const dva_t *dva, boolean_t checkpoint) * the reservation. */ boolean_t -metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, zio_t *zio, - int flags) +metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, int allocator, + zio_t *zio, int flags) { uint64_t available_slots = 0; boolean_t slot_reserved = B_FALSE; + uint64_t max = mc->mc_alloc_max_slots[allocator]; ASSERT(mc->mc_alloc_throttle_enabled); mutex_enter(&mc->mc_lock); - uint64_t reserved_slots = refcount_count(&mc->mc_alloc_slots); - if (reserved_slots < mc->mc_alloc_max_slots) - available_slots = mc->mc_alloc_max_slots - reserved_slots; + uint64_t reserved_slots = + refcount_count(&mc->mc_alloc_slots[allocator]); + if (reserved_slots < max) + available_slots = max - reserved_slots; if (slots <= available_slots || GANG_ALLOCATION(flags)) { /* @@ -3578,7 +3845,9 @@ metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, zio_t *zio, * them individually when an I/O completes. */ for (int d = 0; d < slots; d++) { - reserved_slots = refcount_add(&mc->mc_alloc_slots, zio); + reserved_slots = + refcount_add(&mc->mc_alloc_slots[allocator], + zio); } zio->io_flags |= ZIO_FLAG_IO_ALLOCATING; slot_reserved = B_TRUE; @@ -3589,12 +3858,14 @@ metaslab_class_throttle_reserve(metaslab_class_t *mc, int slots, zio_t *zio, } void -metaslab_class_throttle_unreserve(metaslab_class_t *mc, int slots, zio_t *zio) +metaslab_class_throttle_unreserve(metaslab_class_t *mc, int slots, + int allocator, zio_t *zio) { ASSERT(mc->mc_alloc_throttle_enabled); mutex_enter(&mc->mc_lock); for (int d = 0; d < slots; d++) { - (void) refcount_remove(&mc->mc_alloc_slots, zio); + (void) refcount_remove(&mc->mc_alloc_slots[allocator], + zio); } mutex_exit(&mc->mc_lock); } @@ -3616,7 +3887,13 @@ metaslab_claim_concrete(vdev_t *vd, uint64_t offset, uint64_t size, mutex_enter(&msp->ms_lock); if ((txg != 0 && spa_writeable(spa)) || !msp->ms_loaded) - error = metaslab_activate(msp, METASLAB_WEIGHT_SECONDARY); + error = metaslab_activate(msp, 0, METASLAB_WEIGHT_CLAIM); + /* + * No need to fail in that case; someone else has activated the + * metaslab, but that doesn't preclude us from using it. + */ + if (error == EBUSY) + error = 0; if (error == 0 && !range_tree_contains(msp->ms_allocatable, offset, size)) @@ -3721,7 +3998,7 @@ metaslab_claim_dva(spa_t *spa, const dva_t *dva, uint64_t txg) int metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp, int ndvas, uint64_t txg, blkptr_t *hintbp, int flags, - zio_alloc_list_t *zal, zio_t *zio) + zio_alloc_list_t *zal, zio_t *zio, int allocator) { dva_t *dva = bp->blk_dva; dva_t *hintdva = hintbp->blk_dva; @@ -3744,12 +4021,13 @@ metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp, for (int d = 0; d < ndvas; d++) { error = metaslab_alloc_dva(spa, mc, psize, dva, d, hintdva, - txg, flags, zal); + txg, flags, zal, allocator); if (error != 0) { for (d--; d >= 0; d--) { metaslab_unalloc_dva(spa, &dva[d], txg); metaslab_group_alloc_decrement(spa, - DVA_GET_VDEV(&dva[d]), zio, flags); + DVA_GET_VDEV(&dva[d]), zio, flags, + allocator, B_FALSE); bzero(&dva[d], sizeof (dva_t)); } spa_config_exit(spa, SCL_ALLOC, FTAG); @@ -3760,7 +4038,7 @@ metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp, * based on the newly allocated dva. */ metaslab_group_alloc_increment(spa, - DVA_GET_VDEV(&dva[d]), zio, flags); + DVA_GET_VDEV(&dva[d]), zio, flags, allocator); } } diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index 064e4411db..163f5e054e 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -7398,9 +7398,11 @@ spa_sync(spa_t *spa, uint64_t txg) spa->spa_syncing_txg = txg; spa->spa_sync_pass = 0; - mutex_enter(&spa->spa_alloc_lock); - VERIFY0(avl_numnodes(&spa->spa_alloc_tree)); - mutex_exit(&spa->spa_alloc_lock); + for (int i = 0; i < spa->spa_alloc_count; i++) { + mutex_enter(&spa->spa_alloc_locks[i]); + VERIFY0(avl_numnodes(&spa->spa_alloc_trees[i])); + mutex_exit(&spa->spa_alloc_locks[i]); + } /* * If there are any pending vdev state changes, convert them @@ -7459,7 +7461,7 @@ spa_sync(spa_t *spa, uint64_t txg) * The max queue depth will not change in the middle of syncing * out this txg. */ - uint64_t queue_depth_total = 0; + uint64_t slots_per_allocator = 0; for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *tvd = rvd->vdev_child[c]; metaslab_group_t *mg = tvd->vdev_mg; @@ -7473,18 +7475,23 @@ spa_sync(spa_t *spa, uint64_t txg) * allocations look at mg_max_alloc_queue_depth, and async * allocations all happen from spa_sync(). */ - ASSERT0(refcount_count(&mg->mg_alloc_queue_depth)); + for (int i = 0; i < spa->spa_alloc_count; i++) + ASSERT0(refcount_count(&(mg->mg_alloc_queue_depth[i]))); mg->mg_max_alloc_queue_depth = max_queue_depth; - queue_depth_total += mg->mg_max_alloc_queue_depth; + + for (int i = 0; i < spa->spa_alloc_count; i++) { + mg->mg_cur_max_alloc_queue_depth[i] = + zfs_vdev_def_queue_depth; + } + slots_per_allocator += zfs_vdev_def_queue_depth; } metaslab_class_t *mc = spa_normal_class(spa); - ASSERT0(refcount_count(&mc->mc_alloc_slots)); - mc->mc_alloc_max_slots = queue_depth_total; + for (int i = 0; i < spa->spa_alloc_count; i++) { + ASSERT0(refcount_count(&mc->mc_alloc_slots[i])); + mc->mc_alloc_max_slots[i] = slots_per_allocator; + } mc->mc_alloc_throttle_enabled = zio_dva_throttle_enabled; - ASSERT3U(mc->mc_alloc_max_slots, <=, - max_queue_depth * rvd->vdev_children); - for (int c = 0; c < rvd->vdev_children; c++) { vdev_t *vd = rvd->vdev_child[c]; vdev_indirect_state_sync_verify(vd); @@ -7661,9 +7668,11 @@ spa_sync(spa_t *spa, uint64_t txg) dsl_pool_sync_done(dp, txg); - mutex_enter(&spa->spa_alloc_lock); - VERIFY0(avl_numnodes(&spa->spa_alloc_tree)); - mutex_exit(&spa->spa_alloc_lock); + for (int i = 0; i < spa->spa_alloc_count; i++) { + mutex_enter(&spa->spa_alloc_locks[i]); + VERIFY0(avl_numnodes(&spa->spa_alloc_trees[i])); + mutex_exit(&spa->spa_alloc_locks[i]); + } /* * Update usable space statistics. diff --git a/usr/src/uts/common/fs/zfs/spa_misc.c b/usr/src/uts/common/fs/zfs/spa_misc.c index efb4993c0a..fe0971a720 100644 --- a/usr/src/uts/common/fs/zfs/spa_misc.c +++ b/usr/src/uts/common/fs/zfs/spa_misc.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright 2013 Saso Kiselkov. All rights reserved. @@ -357,6 +357,8 @@ int spa_asize_inflation = 24; int spa_slop_shift = 5; uint64_t spa_min_slop = 128 * 1024 * 1024; +int spa_allocators = 4; + /*PRINTFLIKE2*/ void spa_load_failed(spa_t *spa, const char *fmt, ...) @@ -607,7 +609,6 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_iokstat_lock, NULL, MUTEX_DEFAULT, NULL); - mutex_init(&spa->spa_alloc_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL); cv_init(&spa->spa_evicting_os_cv, NULL, CV_DEFAULT, NULL); @@ -658,8 +659,16 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) spa_active_count++; } - avl_create(&spa->spa_alloc_tree, zio_bookmark_compare, - sizeof (zio_t), offsetof(zio_t, io_alloc_node)); + spa->spa_alloc_count = spa_allocators; + spa->spa_alloc_locks = kmem_zalloc(spa->spa_alloc_count * + sizeof (kmutex_t), KM_SLEEP); + spa->spa_alloc_trees = kmem_zalloc(spa->spa_alloc_count * + sizeof (avl_tree_t), KM_SLEEP); + for (int i = 0; i < spa->spa_alloc_count; i++) { + mutex_init(&spa->spa_alloc_locks[i], NULL, MUTEX_DEFAULT, NULL); + avl_create(&spa->spa_alloc_trees[i], zio_bookmark_compare, + sizeof (zio_t), offsetof(zio_t, io_alloc_node)); + } /* * Every pool starts with the default cachefile @@ -746,7 +755,15 @@ spa_remove(spa_t *spa) kmem_free(dp, sizeof (spa_config_dirent_t)); } - avl_destroy(&spa->spa_alloc_tree); + for (int i = 0; i < spa->spa_alloc_count; i++) { + avl_destroy(&spa->spa_alloc_trees[i]); + mutex_destroy(&spa->spa_alloc_locks[i]); + } + kmem_free(spa->spa_alloc_locks, spa->spa_alloc_count * + sizeof (kmutex_t)); + kmem_free(spa->spa_alloc_trees, spa->spa_alloc_count * + sizeof (avl_tree_t)); + list_destroy(&spa->spa_config_list); nvlist_free(spa->spa_label_features); @@ -777,7 +794,6 @@ spa_remove(spa_t *spa) cv_destroy(&spa->spa_scrub_io_cv); cv_destroy(&spa->spa_suspend_cv); - mutex_destroy(&spa->spa_alloc_lock); mutex_destroy(&spa->spa_async_lock); mutex_destroy(&spa->spa_errlist_lock); mutex_destroy(&spa->spa_errlog_lock); diff --git a/usr/src/uts/common/fs/zfs/sys/metaslab.h b/usr/src/uts/common/fs/zfs/sys/metaslab.h index a76d344d21..32a19ca645 100644 --- a/usr/src/uts/common/fs/zfs/sys/metaslab.h +++ b/usr/src/uts/common/fs/zfs/sys/metaslab.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. */ #ifndef _SYS_METASLAB_H @@ -65,9 +65,10 @@ uint64_t metaslab_block_maxsize(metaslab_t *); #define METASLAB_DONT_THROTTLE 0x10 int metaslab_alloc(spa_t *, metaslab_class_t *, uint64_t, - blkptr_t *, int, uint64_t, blkptr_t *, int, zio_alloc_list_t *, zio_t *); + blkptr_t *, int, uint64_t, blkptr_t *, int, zio_alloc_list_t *, zio_t *, + int); int metaslab_alloc_dva(spa_t *, metaslab_class_t *, uint64_t, - dva_t *, int, dva_t *, uint64_t, int, zio_alloc_list_t *); + dva_t *, int, dva_t *, uint64_t, int, zio_alloc_list_t *, int); void metaslab_free(spa_t *, const blkptr_t *, uint64_t, boolean_t); void metaslab_free_concrete(vdev_t *, uint64_t, uint64_t, boolean_t); void metaslab_free_dva(spa_t *, const dva_t *, boolean_t); @@ -88,9 +89,9 @@ int metaslab_class_validate(metaslab_class_t *); void metaslab_class_histogram_verify(metaslab_class_t *); uint64_t metaslab_class_fragmentation(metaslab_class_t *); uint64_t metaslab_class_expandable_space(metaslab_class_t *); -boolean_t metaslab_class_throttle_reserve(metaslab_class_t *, int, +boolean_t metaslab_class_throttle_reserve(metaslab_class_t *, int, int, zio_t *, int); -void metaslab_class_throttle_unreserve(metaslab_class_t *, int, zio_t *); +void metaslab_class_throttle_unreserve(metaslab_class_t *, int, int, zio_t *); void metaslab_class_space_update(metaslab_class_t *, int64_t, int64_t, int64_t, int64_t); @@ -99,7 +100,7 @@ uint64_t metaslab_class_get_space(metaslab_class_t *); uint64_t metaslab_class_get_dspace(metaslab_class_t *); uint64_t metaslab_class_get_deferred(metaslab_class_t *); -metaslab_group_t *metaslab_group_create(metaslab_class_t *, vdev_t *); +metaslab_group_t *metaslab_group_create(metaslab_class_t *, vdev_t *, int); void metaslab_group_destroy(metaslab_group_t *); void metaslab_group_activate(metaslab_group_t *); void metaslab_group_passivate(metaslab_group_t *); @@ -108,8 +109,9 @@ uint64_t metaslab_group_get_space(metaslab_group_t *); void metaslab_group_histogram_verify(metaslab_group_t *); uint64_t metaslab_group_fragmentation(metaslab_group_t *); void metaslab_group_histogram_remove(metaslab_group_t *, metaslab_t *); -void metaslab_group_alloc_decrement(spa_t *, uint64_t, void *, int); -void metaslab_group_alloc_verify(spa_t *, const blkptr_t *, void *); +void metaslab_group_alloc_decrement(spa_t *, uint64_t, void *, int, int, + boolean_t); +void metaslab_group_alloc_verify(spa_t *, const blkptr_t *, void *, int); #ifdef __cplusplus } diff --git a/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h b/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h index a6673fbe06..6a02f7c800 100644 --- a/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h @@ -24,7 +24,7 @@ */ /* - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. */ #ifndef _SYS_METASLAB_IMPL_H @@ -52,6 +52,7 @@ typedef struct metaslab_alloc_trace { uint64_t mat_weight; uint32_t mat_dva_id; uint64_t mat_offset; + int mat_allocator; } metaslab_alloc_trace_t; /* @@ -72,9 +73,11 @@ typedef enum trace_alloc_type { #define METASLAB_WEIGHT_PRIMARY (1ULL << 63) #define METASLAB_WEIGHT_SECONDARY (1ULL << 62) -#define METASLAB_WEIGHT_TYPE (1ULL << 61) +#define METASLAB_WEIGHT_CLAIM (1ULL << 61) +#define METASLAB_WEIGHT_TYPE (1ULL << 60) #define METASLAB_ACTIVE_MASK \ - (METASLAB_WEIGHT_PRIMARY | METASLAB_WEIGHT_SECONDARY) + (METASLAB_WEIGHT_PRIMARY | METASLAB_WEIGHT_SECONDARY | \ + METASLAB_WEIGHT_CLAIM) /* * The metaslab weight is used to encode the amount of free space in a @@ -97,37 +100,39 @@ typedef enum trace_alloc_type { * * 64 56 48 40 32 24 16 8 0 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * |PS1| weighted-free space | + * |PSC1| weighted-free space | * +-------+-------+-------+-------+-------+-------+-------+-------+ * * PS - indicates primary and secondary activation + * C - indicates activation for claimed block zio * space - the fragmentation-weighted space * * Segment-based weight: * * 64 56 48 40 32 24 16 8 0 * +-------+-------+-------+-------+-------+-------+-------+-------+ - * |PS0| idx| count of segments in region | + * |PSC0| idx| count of segments in region | * +-------+-------+-------+-------+-------+-------+-------+-------+ * * PS - indicates primary and secondary activation + * C - indicates activation for claimed block zio * idx - index for the highest bucket in the histogram * count - number of segments in the specified bucket */ -#define WEIGHT_GET_ACTIVE(weight) BF64_GET((weight), 62, 2) -#define WEIGHT_SET_ACTIVE(weight, x) BF64_SET((weight), 62, 2, x) +#define WEIGHT_GET_ACTIVE(weight) BF64_GET((weight), 61, 3) +#define WEIGHT_SET_ACTIVE(weight, x) BF64_SET((weight), 61, 3, x) #define WEIGHT_IS_SPACEBASED(weight) \ - ((weight) == 0 || BF64_GET((weight), 61, 1)) -#define WEIGHT_SET_SPACEBASED(weight) BF64_SET((weight), 61, 1, 1) + ((weight) == 0 || BF64_GET((weight), 60, 1)) +#define WEIGHT_SET_SPACEBASED(weight) BF64_SET((weight), 60, 1, 1) /* * These macros are only applicable to segment-based weighting. */ -#define WEIGHT_GET_INDEX(weight) BF64_GET((weight), 55, 6) -#define WEIGHT_SET_INDEX(weight, x) BF64_SET((weight), 55, 6, x) -#define WEIGHT_GET_COUNT(weight) BF64_GET((weight), 0, 55) -#define WEIGHT_SET_COUNT(weight, x) BF64_SET((weight), 0, 55, x) +#define WEIGHT_GET_INDEX(weight) BF64_GET((weight), 54, 6) +#define WEIGHT_SET_INDEX(weight, x) BF64_SET((weight), 54, 6, x) +#define WEIGHT_GET_COUNT(weight) BF64_GET((weight), 0, 54) +#define WEIGHT_SET_COUNT(weight, x) BF64_SET((weight), 0, 54, x) /* * A metaslab class encompasses a category of allocatable top-level vdevs. @@ -178,8 +183,8 @@ struct metaslab_class { * allowed to reserve slots even if we've reached the maximum * number of allocations allowed. */ - uint64_t mc_alloc_max_slots; - refcount_t mc_alloc_slots; + uint64_t *mc_alloc_max_slots; + refcount_t *mc_alloc_slots; uint64_t mc_alloc_groups; /* # of allocatable groups */ @@ -201,9 +206,12 @@ struct metaslab_class { */ struct metaslab_group { kmutex_t mg_lock; + metaslab_t **mg_primaries; + metaslab_t **mg_secondaries; avl_tree_t mg_metaslab_tree; uint64_t mg_aliquot; boolean_t mg_allocatable; /* can we allocate? */ + uint64_t mg_ms_ready; /* * A metaslab group is considered to be initialized only after @@ -223,15 +231,33 @@ struct metaslab_group { metaslab_group_t *mg_next; /* - * Each metaslab group can handle mg_max_alloc_queue_depth allocations - * which are tracked by mg_alloc_queue_depth. It's possible for a - * metaslab group to handle more allocations than its max. This - * can occur when gang blocks are required or when other groups - * are unable to handle their share of allocations. + * In order for the allocation throttle to function properly, we cannot + * have too many IOs going to each disk by default; the throttle + * operates by allocating more work to disks that finish quickly, so + * allocating larger chunks to each disk reduces its effectiveness. + * However, if the number of IOs going to each allocator is too small, + * we will not perform proper aggregation at the vdev_queue layer, + * also resulting in decreased performance. Therefore, we will use a + * ramp-up strategy. + * + * Each allocator in each metaslab group has a current queue depth + * (mg_alloc_queue_depth[allocator]) and a current max queue depth + * (mg_cur_max_alloc_queue_depth[allocator]), and each metaslab group + * has an absolute max queue depth (mg_max_alloc_queue_depth). We + * add IOs to an allocator until the mg_alloc_queue_depth for that + * allocator hits the cur_max. Every time an IO completes for a given + * allocator on a given metaslab group, we increment its cur_max until + * it reaches mg_max_alloc_queue_depth. The cur_max resets every txg to + * help protect against disks that decrease in performance over time. + * + * It's possible for an allocator to handle more allocations than + * its max. This can occur when gang blocks are required or when other + * groups are unable to handle their share of allocations. */ uint64_t mg_max_alloc_queue_depth; - refcount_t mg_alloc_queue_depth; - + uint64_t *mg_cur_max_alloc_queue_depth; + refcount_t *mg_alloc_queue_depth; + int mg_allocators; /* * A metalab group that can no longer allocate the minimum block * size will set mg_no_free_space. Once a metaslab group is out @@ -356,6 +382,13 @@ struct metaslab { uint64_t ms_max_size; /* maximum allocatable size */ /* + * -1 if it's not active in an allocator, otherwise set to the allocator + * this metaslab is active for. + */ + int ms_allocator; + boolean_t ms_primary; /* Only valid if ms_allocator is not -1 */ + + /* * The metaslab block allocators can optionally use a size-ordered * range tree and/or an array of LBAs. Not all allocators use * this functionality. The ms_allocatable_by_size should always @@ -369,6 +402,8 @@ struct metaslab { metaslab_group_t *ms_group; /* metaslab group */ avl_node_t ms_group_node; /* node in metaslab group tree */ txg_node_t ms_txg_node; /* per-txg dirty metaslab links */ + + boolean_t ms_new; }; #ifdef __cplusplus diff --git a/usr/src/uts/common/fs/zfs/sys/spa_impl.h b/usr/src/uts/common/fs/zfs/sys/spa_impl.h index a23f9b8c4f..a6da04b67b 100644 --- a/usr/src/uts/common/fs/zfs/sys/spa_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/spa_impl.h @@ -237,8 +237,16 @@ struct spa { uint64_t spa_last_synced_guid; /* last synced guid */ list_t spa_config_dirty_list; /* vdevs with dirty config */ list_t spa_state_dirty_list; /* vdevs with dirty state */ - kmutex_t spa_alloc_lock; - avl_tree_t spa_alloc_tree; + /* + * spa_alloc_locks and spa_alloc_trees are arrays, whose lengths are + * stored in spa_alloc_count. There is one tree and one lock for each + * allocator, to help improve allocation performance in write-heavy + * workloads. + */ + kmutex_t *spa_alloc_locks; + avl_tree_t *spa_alloc_trees; + int spa_alloc_count; + spa_aux_vdev_t spa_spares; /* hot spares */ spa_aux_vdev_t spa_l2cache; /* L2ARC cache devices */ nvlist_t *spa_label_features; /* Features for reading MOS */ diff --git a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h index 4327f61af9..252069c5a4 100644 --- a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. */ #ifndef _SYS_VDEV_IMPL_H @@ -59,6 +59,7 @@ typedef struct vdev_cache_entry vdev_cache_entry_t; struct abd; extern int zfs_vdev_queue_depth_pct; +extern int zfs_vdev_def_queue_depth; extern uint32_t zfs_vdev_async_write_max_active; /* diff --git a/usr/src/uts/common/fs/zfs/sys/zio.h b/usr/src/uts/common/fs/zfs/sys/zio.h index 1520216c8f..273e5fcb0b 100644 --- a/usr/src/uts/common/fs/zfs/sys/zio.h +++ b/usr/src/uts/common/fs/zfs/sys/zio.h @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright 2016 Toomas Soome <tsoome@me.com> @@ -459,6 +459,7 @@ struct zio { void *io_waiter; kmutex_t io_lock; kcondvar_t io_cv; + int io_allocator; /* FMA state */ zio_cksum_report_t *io_cksum_report; @@ -517,8 +518,8 @@ extern zio_t *zio_write_phys(zio_t *pio, vdev_t *vd, uint64_t offset, extern zio_t *zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp, enum zio_flag flags); -extern int zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, - blkptr_t *old_bp, uint64_t size, boolean_t *slog); +extern int zio_alloc_zil(spa_t *spa, uint64_t objset, uint64_t txg, + blkptr_t *new_bp, blkptr_t *old_bp, uint64_t size, boolean_t *slog); extern void zio_flush(zio_t *zio, vdev_t *vd); extern void zio_shrink(zio_t *zio, uint64_t size); diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c index ae7f4b501c..e761ee4b39 100644 --- a/usr/src/uts/common/fs/zfs/vdev.c +++ b/usr/src/uts/common/fs/zfs/vdev.c @@ -644,7 +644,8 @@ vdev_alloc(spa_t *spa, vdev_t **vdp, nvlist_t *nv, vdev_t *parent, uint_t id, alloctype == VDEV_ALLOC_SPLIT || alloctype == VDEV_ALLOC_ROOTPOOL); vd->vdev_mg = metaslab_group_create(islog ? - spa_log_class(spa) : spa_normal_class(spa), vd); + spa_log_class(spa) : spa_normal_class(spa), vd, + spa->spa_alloc_count); } if (vd->vdev_ops->vdev_op_leaf && @@ -1013,7 +1014,6 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg) vd->vdev_ms = mspp; vd->vdev_ms_count = newc; - for (m = oldc; m < newc; m++) { uint64_t object = 0; diff --git a/usr/src/uts/common/fs/zfs/vdev_queue.c b/usr/src/uts/common/fs/zfs/vdev_queue.c index 3a6644a51f..9f962350db 100644 --- a/usr/src/uts/common/fs/zfs/vdev_queue.c +++ b/usr/src/uts/common/fs/zfs/vdev_queue.c @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -189,6 +189,15 @@ int zfs_vdev_queue_depth_pct = 1000; int zfs_vdev_queue_depth_pct = 300; #endif +/* + * When performing allocations for a given metaslab, we want to make sure that + * there are enough IOs to aggregate together to improve throughput. We want to + * ensure that there are at least 128k worth of IOs that can be aggregated, and + * we assume that the average allocation size is 4k, so we need the queue depth + * to be 32 per allocator to get good aggregation of sequential writes. + */ +int zfs_vdev_def_queue_depth = 32; + int vdev_queue_offset_compare(const void *x1, const void *x2) diff --git a/usr/src/uts/common/fs/zfs/vdev_removal.c b/usr/src/uts/common/fs/zfs/vdev_removal.c index f8d149fc11..d00b5b35f7 100644 --- a/usr/src/uts/common/fs/zfs/vdev_removal.c +++ b/usr/src/uts/common/fs/zfs/vdev_removal.c @@ -806,8 +806,15 @@ spa_vdev_copy_segment(vdev_t *vd, uint64_t start, uint64_t size, uint64_t txg, ASSERT3U(size, <=, SPA_MAXBLOCKSIZE); + /* + * We use allocator 0 for this I/O because we don't expect device remap + * to be the steady state of the system, so parallelizing is not as + * critical as it is for other allocation types. We also want to ensure + * that the IOs are allocated together as much as possible, to reduce + * mapping sizes. + */ int error = metaslab_alloc_dva(spa, mg->mg_class, size, - &dst, 0, NULL, txg, 0, zal); + &dst, 0, NULL, txg, 0, zal, 0); if (error != 0) return (error); diff --git a/usr/src/uts/common/fs/zfs/zil.c b/usr/src/uts/common/fs/zfs/zil.c index 4711c7150f..0e02377de5 100644 --- a/usr/src/uts/common/fs/zfs/zil.c +++ b/usr/src/uts/common/fs/zfs/zil.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Joyent, Inc. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ @@ -657,7 +657,8 @@ zil_create(zilog_t *zilog) BP_ZERO(&blk); } - error = zio_alloc_zil(zilog->zl_spa, txg, &blk, NULL, + error = zio_alloc_zil(zilog->zl_spa, + zilog->zl_os->os_dsl_dataset->ds_object, txg, &blk, NULL, ZIL_MIN_BLKSZ, &slog); if (error == 0) @@ -1334,7 +1335,8 @@ zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb) BP_ZERO(bp); /* pass the old blkptr in order to spread log blocks across devs */ - error = zio_alloc_zil(spa, txg, bp, &lwb->lwb_blk, zil_blksz, &slog); + error = zio_alloc_zil(spa, zilog->zl_os->os_dsl_dataset->ds_object, + txg, bp, &lwb->lwb_blk, zil_blksz, &slog); if (error == 0) { ASSERT3U(bp->blk_birth, ==, txg); bp->blk_cksum = lwb->lwb_blk.blk_cksum; diff --git a/usr/src/uts/common/fs/zfs/zio.c b/usr/src/uts/common/fs/zfs/zio.c index d43adabb5b..f2c511ef77 100644 --- a/usr/src/uts/common/fs/zfs/zio.c +++ b/usr/src/uts/common/fs/zfs/zio.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2014 Integros [integros.com] @@ -44,6 +44,7 @@ #include <sys/zfs_zone.h> #include <sys/metaslab_impl.h> #include <sys/abd.h> +#include <sys/cityhash.h> /* * ========================================================================== @@ -2235,7 +2236,8 @@ zio_write_gang_block(zio_t *pio) ASSERT(!(pio->io_flags & ZIO_FLAG_NODATA)); flags |= METASLAB_ASYNC_ALLOC; - VERIFY(refcount_held(&mc->mc_alloc_slots, pio)); + VERIFY(refcount_held(&mc->mc_alloc_slots[pio->io_allocator], + pio)); /* * The logical zio has already placed a reservation for @@ -2246,12 +2248,12 @@ zio_write_gang_block(zio_t *pio) * additional reservations for gang blocks. */ VERIFY(metaslab_class_throttle_reserve(mc, gbh_copies - copies, - pio, flags)); + pio->io_allocator, pio, flags)); } error = metaslab_alloc(spa, mc, SPA_GANGBLOCKSIZE, bp, gbh_copies, txg, pio == gio ? NULL : gio->io_bp, flags, - &pio->io_alloc_list, pio); + &pio->io_alloc_list, pio, pio->io_allocator); if (error) { if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) { ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE); @@ -2265,7 +2267,7 @@ zio_write_gang_block(zio_t *pio) * stage. */ metaslab_class_throttle_unreserve(mc, - gbh_copies - copies, pio); + gbh_copies - copies, pio->io_allocator, pio); } pio->io_error = error; return (ZIO_PIPELINE_CONTINUE); @@ -2323,7 +2325,7 @@ zio_write_gang_block(zio_t *pio) * slot for them here. */ VERIFY(metaslab_class_throttle_reserve(mc, - zp.zp_copies, cio, flags)); + zp.zp_copies, cio->io_allocator, cio, flags)); } zio_nowait(cio); } @@ -2813,13 +2815,13 @@ zio_ddt_free(zio_t *zio) */ static zio_t * -zio_io_to_allocate(spa_t *spa) +zio_io_to_allocate(spa_t *spa, int allocator) { zio_t *zio; - ASSERT(MUTEX_HELD(&spa->spa_alloc_lock)); + ASSERT(MUTEX_HELD(&spa->spa_alloc_locks[allocator])); - zio = avl_first(&spa->spa_alloc_tree); + zio = avl_first(&spa->spa_alloc_trees[allocator]); if (zio == NULL) return (NULL); @@ -2829,12 +2831,13 @@ zio_io_to_allocate(spa_t *spa) * Try to place a reservation for this zio. If we're unable to * reserve then we throttle. */ + ASSERT3U(zio->io_allocator, ==, allocator); if (!metaslab_class_throttle_reserve(spa_normal_class(spa), - zio->io_prop.zp_copies, zio, 0)) { + zio->io_prop.zp_copies, zio->io_allocator, zio, 0)) { return (NULL); } - avl_remove(&spa->spa_alloc_tree, zio); + avl_remove(&spa->spa_alloc_trees[allocator], zio); ASSERT3U(zio->io_stage, <, ZIO_STAGE_DVA_ALLOCATE); return (zio); @@ -2858,13 +2861,23 @@ zio_dva_throttle(zio_t *zio) ASSERT3U(zio->io_queued_timestamp, >, 0); ASSERT(zio->io_stage == ZIO_STAGE_DVA_THROTTLE); - mutex_enter(&spa->spa_alloc_lock); + zbookmark_phys_t *bm = &zio->io_bookmark; + /* + * We want to try to use as many allocators as possible to help improve + * performance, but we also want logically adjacent IOs to be physically + * adjacent to improve sequential read performance. We chunk each object + * into 2^20 block regions, and then hash based on the objset, object, + * level, and region to accomplish both of these goals. + */ + zio->io_allocator = cityhash4(bm->zb_objset, bm->zb_object, + bm->zb_level, bm->zb_blkid >> 20) % spa->spa_alloc_count; + mutex_enter(&spa->spa_alloc_locks[zio->io_allocator]); ASSERT(zio->io_type == ZIO_TYPE_WRITE); - avl_add(&spa->spa_alloc_tree, zio); + avl_add(&spa->spa_alloc_trees[zio->io_allocator], zio); - nio = zio_io_to_allocate(zio->io_spa); - mutex_exit(&spa->spa_alloc_lock); + nio = zio_io_to_allocate(zio->io_spa, zio->io_allocator); + mutex_exit(&spa->spa_alloc_locks[zio->io_allocator]); if (nio == zio) return (ZIO_PIPELINE_CONTINUE); @@ -2885,13 +2898,13 @@ zio_dva_throttle(zio_t *zio) } void -zio_allocate_dispatch(spa_t *spa) +zio_allocate_dispatch(spa_t *spa, int allocator) { zio_t *zio; - mutex_enter(&spa->spa_alloc_lock); - zio = zio_io_to_allocate(spa); - mutex_exit(&spa->spa_alloc_lock); + mutex_enter(&spa->spa_alloc_locks[allocator]); + zio = zio_io_to_allocate(spa, allocator); + mutex_exit(&spa->spa_alloc_locks[allocator]); if (zio == NULL) return; @@ -2932,7 +2945,7 @@ zio_dva_allocate(zio_t *zio) error = metaslab_alloc(spa, mc, zio->io_size, bp, zio->io_prop.zp_copies, zio->io_txg, NULL, flags, - &zio->io_alloc_list, zio); + &zio->io_alloc_list, zio, zio->io_allocator); if (error != 0) { spa_dbgmsg(spa, "%s: metaslab allocation failure: zio %p, " @@ -2992,8 +3005,8 @@ zio_dva_unallocate(zio_t *zio, zio_gang_node_t *gn, blkptr_t *bp) * Try to allocate an intent log block. Return 0 on success, errno on failure. */ int -zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, blkptr_t *old_bp, - uint64_t size, boolean_t *slog) +zio_alloc_zil(spa_t *spa, uint64_t objset, uint64_t txg, blkptr_t *new_bp, + blkptr_t *old_bp, uint64_t size, boolean_t *slog) { int error = 1; zio_alloc_list_t io_alloc_list; @@ -3001,14 +3014,22 @@ zio_alloc_zil(spa_t *spa, uint64_t txg, blkptr_t *new_bp, blkptr_t *old_bp, ASSERT(txg > spa_syncing_txg(spa)); metaslab_trace_init(&io_alloc_list); + /* + * When allocating a zil block, we don't have information about + * the final destination of the block except the objset it's part + * of, so we just hash the objset ID to pick the allocator to get + * some parallelism. + */ error = metaslab_alloc(spa, spa_log_class(spa), size, new_bp, 1, - txg, old_bp, METASLAB_HINTBP_AVOID, &io_alloc_list, NULL); + txg, old_bp, METASLAB_HINTBP_AVOID, &io_alloc_list, NULL, + cityhash4(0, 0, 0, objset) % spa->spa_alloc_count); if (error == 0) { *slog = TRUE; } else { error = metaslab_alloc(spa, spa_normal_class(spa), size, new_bp, 1, txg, old_bp, METASLAB_HINTBP_AVOID, - &io_alloc_list, NULL); + &io_alloc_list, NULL, cityhash4(0, 0, 0, objset) % + spa->spa_alloc_count); if (error == 0) *slog = FALSE; } @@ -3498,8 +3519,8 @@ zio_ready(zio_t *zio) */ metaslab_class_throttle_unreserve( spa_normal_class(zio->io_spa), - zio->io_prop.zp_copies, zio); - zio_allocate_dispatch(zio->io_spa); + zio->io_prop.zp_copies, zio->io_allocator, zio); + zio_allocate_dispatch(zio->io_spa, zio->io_allocator); } } @@ -3582,18 +3603,19 @@ zio_dva_throttle_done(zio_t *zio) ASSERT0(zio->io_flags & ZIO_FLAG_NOPWRITE); mutex_enter(&pio->io_lock); - metaslab_group_alloc_decrement(zio->io_spa, vd->vdev_id, pio, flags); + metaslab_group_alloc_decrement(zio->io_spa, vd->vdev_id, pio, flags, + pio->io_allocator, B_TRUE); mutex_exit(&pio->io_lock); metaslab_class_throttle_unreserve(spa_normal_class(zio->io_spa), - 1, pio); + 1, pio->io_allocator, pio); /* * Call into the pipeline to see if there is more work that * needs to be done. If there is work to be done it will be * dispatched to another taskq thread. */ - zio_allocate_dispatch(zio->io_spa); + zio_allocate_dispatch(zio->io_spa, pio->io_allocator); } static int @@ -3636,8 +3658,10 @@ zio_done(zio_t *zio) ASSERT(zio->io_type == ZIO_TYPE_WRITE); ASSERT(zio->io_priority == ZIO_PRIORITY_ASYNC_WRITE); ASSERT(bp != NULL); - metaslab_group_alloc_verify(spa, zio->io_bp, zio); - VERIFY(refcount_not_held(&mc->mc_alloc_slots, zio)); + metaslab_group_alloc_verify(spa, zio->io_bp, zio, + zio->io_allocator); + VERIFY(refcount_not_held(&mc->mc_alloc_slots[zio->io_allocator], + zio)); } for (int c = 0; c < ZIO_CHILD_TYPES; c++) diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c index 370c39ccc1..34014a5768 100644 --- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c +++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c @@ -2143,7 +2143,7 @@ mptsas_get_sas_io_unit_page_hndshk(mptsas_t *mpt) "manufacturing information (%u). Driver " "will not attach. Please contact the " "firmware vendor about this.", num_phys, - mpt->m_num_phys, mpt->m_num_phys); + mpt->m_num_phys); rval = DDI_FAILURE; goto cleanup; } @@ -2243,7 +2243,7 @@ mptsas_get_sas_io_unit_page_hndshk(mptsas_t *mpt) "manufacturing information (%u). Driver " "will not attach. Please contact the " "firmware vendor about this.", num_phys, - mpt->m_num_phys, mpt->m_num_phys); + mpt->m_num_phys); rval = DDI_FAILURE; goto cleanup; } diff --git a/usr/src/uts/common/smb/Makefile b/usr/src/uts/common/smb/Makefile index 2efb11c19c..74ac618565 100644 --- a/usr/src/uts/common/smb/Makefile +++ b/usr/src/uts/common/smb/Makefile @@ -21,6 +21,7 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2013 Nexenta Systems, Inc. All rights reserved. # include ../../../Makefile.master @@ -29,7 +30,8 @@ HDRS= \ doserror.h \ lmerr.h \ nterror.h \ - ntstatus.h + ntstatus.h \ + wintypes.h ROOTDIR= $(ROOT)/usr/include/smb diff --git a/usr/src/uts/common/smbsrv/wintypes.h b/usr/src/uts/common/smb/wintypes.h index 1dc3e1515a..61e48016b4 100644 --- a/usr/src/uts/common/smbsrv/wintypes.h +++ b/usr/src/uts/common/smb/wintypes.h @@ -18,13 +18,16 @@ * * CDDL HEADER END */ + /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ -#ifndef _SMBSRV_WINTYPES_H -#define _SMBSRV_WINTYPES_H +#ifndef _SMB_WINTYPES_H +#define _SMB_WINTYPES_H #include <sys/types.h> @@ -42,36 +45,26 @@ extern "C" { typedef uint8_t BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; -typedef uint32_t ntstatus_t; +typedef DWORD ntstatus_t; + +/* pointers to those types */ +typedef BYTE *LPBYTE; +typedef WORD *LPWORD; +typedef DWORD *LPDWORD; + +/* Note: Internally, this is always a UTF-8 string. */ typedef uint8_t *LPTSTR; -typedef uint8_t *LPBYTE; -typedef uint16_t *LPWORD; -typedef uint32_t *LPDWORD; #endif /* UNSIGNED_TYPES_DEFINED */ - #ifndef ANY_SIZE_ARRAY #define ANY_SIZE_ARRAY 1 #endif /* ANY_SIZE_ARRAY */ -/* - * Opaque context handle. - */ -#ifndef CONTEXT_HANDLE -#define CONTEXT_HANDLE(NAME) \ - struct NAME { \ - DWORD data1; \ - DWORD data2; \ - WORD data3[2]; \ - BYTE data4[8]; \ - }; \ - typedef struct NAME -#endif /* CONTEXT_HANDLE */ - +/* CONTEXT_HANDLE now in ndrtypes.ndl */ #ifdef __cplusplus } #endif -#endif /* _SMBSRV_WINTYPES_H */ +#endif /* _SMB_WINTYPES_H */ diff --git a/usr/src/uts/common/smbsrv/Makefile b/usr/src/uts/common/smbsrv/Makefile index f48dc89acb..4664c09cfb 100644 --- a/usr/src/uts/common/smbsrv/Makefile +++ b/usr/src/uts/common/smbsrv/Makefile @@ -33,7 +33,6 @@ HDRS= alloc.h \ mailslot.h \ mbuf.h \ msgbuf.h \ - ndr.h \ netbios.h \ netrauth.h \ nmpipes.h \ @@ -63,18 +62,15 @@ HDRS= alloc.h \ string.h \ svrapi.h \ winioctl.h \ - winsvc.h \ - wintypes.h + winsvc.h NDLHDRS= dssetup.ndl \ eventlog.ndl \ llsrpc.ndl \ lsarpc.ndl \ msgsvc.ndl \ - ndrtypes.ndl \ netdfs.ndl \ netlogon.ndl \ - rpcpdu.ndl \ samrpc.ndl \ security.ndl \ spoolss.ndl \ diff --git a/usr/src/uts/common/smbsrv/ndl/dssetup.ndl b/usr/src/uts/common/smbsrv/ndl/dssetup.ndl index b70a81bb5e..8f1d718e94 100644 --- a/usr/src/uts/common/smbsrv/ndl/dssetup.ndl +++ b/usr/src/uts/common/smbsrv/ndl/dssetup.ndl @@ -21,6 +21,8 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _DSSETUP_NDL_ @@ -34,7 +36,7 @@ * except DsRoleGetPrimaryDomainInfo have been deprecated (MS04-011). */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #define DSSETUP_OPNUM_DsRoleGetPrimaryDomainInfo 0x00 diff --git a/usr/src/uts/common/smbsrv/ndl/eventlog.ndl b/usr/src/uts/common/smbsrv/ndl/eventlog.ndl index df56f8837a..c0e579c4d6 100644 --- a/usr/src/uts/common/smbsrv/ndl/eventlog.ndl +++ b/usr/src/uts/common/smbsrv/ndl/eventlog.ndl @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _MLSVC_LOGR_NDL_ @@ -34,7 +36,7 @@ *********************************************************************** */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #define LOGR_OPNUM_EventLogClose 0x02 #define LOGR_OPNUM_EventLogQueryCount 0x04 diff --git a/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl b/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl index 3710b32e47..62c276873e 100644 --- a/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/llsrpc.ndl @@ -21,6 +21,8 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _MLSVC_LLSR_NDL_ @@ -41,7 +43,7 @@ * 0x3b closes the handle obtained via 0x3a */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #define LLSR_OPNUM_Open 0x00 #define LLSR_OPNUM_Close 0x01 diff --git a/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl b/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl index 2d89687a6a..e93324b419 100644 --- a/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/lsarpc.ndl @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _MLSVC_LSA_NDL_ @@ -38,7 +39,7 @@ * user principal name (UPN) form, such as john@example.com. */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #define LSARPC_OPNUM_CloseHandle 0x00 diff --git a/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl b/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl index 28ab3b6437..f804f32685 100644 --- a/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/msgsvc.ndl @@ -21,6 +21,8 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _MSGSVC_NDL_ @@ -30,7 +32,7 @@ * Message Service */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #define MSGSVCSEND_OPNUM_NetrSendMessage 0x00 diff --git a/usr/src/uts/common/smbsrv/ndl/netdfs.ndl b/usr/src/uts/common/smbsrv/ndl/netdfs.ndl index afc4c88385..7e9a0a42d1 100644 --- a/usr/src/uts/common/smbsrv/ndl/netdfs.ndl +++ b/usr/src/uts/common/smbsrv/ndl/netdfs.ndl @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _NETDFS_NDL_ @@ -30,7 +32,7 @@ * NT Distributed File Service (NETDFS) RPC interface definition. */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #define NETDFS_ABSTRACT_UUID "4fc742e0-4a10-11cf-8273-00aa004ae673" diff --git a/usr/src/uts/common/smbsrv/ndl/netlogon.ndl b/usr/src/uts/common/smbsrv/ndl/netlogon.ndl index 26df6a902a..907d52ec72 100644 --- a/usr/src/uts/common/smbsrv/ndl/netlogon.ndl +++ b/usr/src/uts/common/smbsrv/ndl/netlogon.ndl @@ -36,7 +36,7 @@ *********************************************************************** */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #define NETR_OPNUM_UasLogon 0x00 diff --git a/usr/src/uts/common/smbsrv/ndl/samrpc.ndl b/usr/src/uts/common/smbsrv/ndl/samrpc.ndl index f5ccfd75b8..ef47fff452 100644 --- a/usr/src/uts/common/smbsrv/ndl/samrpc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/samrpc.ndl @@ -31,7 +31,7 @@ * Security Accounts Manager RPC (SAMR) interface definition. */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> /* Windows NT */ #define SAMR_OPNUM_Connect 0x00 /* SamrConnect */ @@ -363,7 +363,7 @@ struct samr_logon_hours_all { #ifndef NDRGEN #define SAMR_USER_PWLEN 256 struct samr_user_password { - smb_wchar_t Buffer[SAMR_USER_PWLEN]; + ndr_wchar_t Buffer[SAMR_USER_PWLEN]; DWORD Length; }; #endif /* NDRGEN */ diff --git a/usr/src/uts/common/smbsrv/ndl/spoolss.ndl b/usr/src/uts/common/smbsrv/ndl/spoolss.ndl index a467b5638c..ef923797d4 100644 --- a/usr/src/uts/common/smbsrv/ndl/spoolss.ndl +++ b/usr/src/uts/common/smbsrv/ndl/spoolss.ndl @@ -20,12 +20,13 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SPOOLSS_NDL_ #define _SPOOLSS_NDL_ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> #include "security.ndl" #define TABLE_STRING 1 diff --git a/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl b/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl index dbc42578d1..5e345a9585 100644 --- a/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _MLSVC_LANMAN_NDL_ @@ -30,7 +32,7 @@ * LanMan RPC (WKSSVC and SRVSVC) interface definitions. */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> /* * WARNING: The cpp(1) macros in this file are not understood by diff --git a/usr/src/uts/common/smbsrv/ndl/svcctl.ndl b/usr/src/uts/common/smbsrv/ndl/svcctl.ndl index 5a6a9d034e..2509f62b52 100644 --- a/usr/src/uts/common/smbsrv/ndl/svcctl.ndl +++ b/usr/src/uts/common/smbsrv/ndl/svcctl.ndl @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _MLSVC_SVCCTL_NDL_ @@ -32,7 +34,7 @@ * stop services. */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> /* Windows NT */ #define SVCCTL_OPNUM_Close 0x00 diff --git a/usr/src/uts/common/smbsrv/ndl/winreg.ndl b/usr/src/uts/common/smbsrv/ndl/winreg.ndl index d09cc32ed2..5789a63e91 100644 --- a/usr/src/uts/common/smbsrv/ndl/winreg.ndl +++ b/usr/src/uts/common/smbsrv/ndl/winreg.ndl @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _MLSVC_WINREG_NDL_ @@ -43,7 +45,7 @@ * HKEY_PERFORMANCE_NLS (HKPN) Runtime performance information. */ -#include "ndrtypes.ndl" +#include <libmlrpc/ndrtypes.ndl> /* Windows NT */ #define WINREG_OPNUM_OpenHKCR 0x00 diff --git a/usr/src/uts/common/smbsrv/netrauth.h b/usr/src/uts/common/smbsrv/netrauth.h index bc11d81e8c..b621e2da1a 100644 --- a/usr/src/uts/common/smbsrv/netrauth.h +++ b/usr/src/uts/common/smbsrv/netrauth.h @@ -33,7 +33,7 @@ */ #include <sys/types.h> -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #include <smbsrv/netbios.h> #include <smbsrv/smbinfo.h> #include <netdb.h> diff --git a/usr/src/uts/common/smbsrv/smb_door.h b/usr/src/uts/common/smbsrv/smb_door.h index 31d32794eb..a59040ecdf 100644 --- a/usr/src/uts/common/smbsrv/smb_door.h +++ b/usr/src/uts/common/smbsrv/smb_door.h @@ -27,7 +27,7 @@ #define _SMBSRV_SMB_DOOR_H #include <sys/door.h> -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #include <smbsrv/smb_xdr.h> #include <smbsrv/smb_token.h> diff --git a/usr/src/uts/common/smbsrv/smb_privilege.h b/usr/src/uts/common/smbsrv/smb_privilege.h index 1a1ee196c1..cbca27107f 100644 --- a/usr/src/uts/common/smbsrv/smb_privilege.h +++ b/usr/src/uts/common/smbsrv/smb_privilege.h @@ -28,7 +28,7 @@ #ifndef _SMB_PRIVILEGE_H #define _SMB_PRIVILEGE_H -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #ifdef __cplusplus extern "C" { diff --git a/usr/src/uts/common/smbsrv/smb_share.h b/usr/src/uts/common/smbsrv/smb_share.h index cfb7551dec..b8cfba779a 100644 --- a/usr/src/uts/common/smbsrv/smb_share.h +++ b/usr/src/uts/common/smbsrv/smb_share.h @@ -29,11 +29,11 @@ #define _SMB_SHARE_H #include <sys/param.h> +#include <smb/lmerr.h> +#include <smb/wintypes.h> #include <smbsrv/string.h> #include <smbsrv/smb_inet.h> #include <smbsrv/hash_table.h> -#include <smbsrv/wintypes.h> -#include <smb/lmerr.h> #if !defined(_KERNEL) && !defined(_FAKE_KERNEL) #include <libshare.h> diff --git a/usr/src/uts/common/smbsrv/smb_sid.h b/usr/src/uts/common/smbsrv/smb_sid.h index 5091f419a4..d6c749e8c1 100644 --- a/usr/src/uts/common/smbsrv/smb_sid.h +++ b/usr/src/uts/common/smbsrv/smb_sid.h @@ -29,7 +29,7 @@ /* * Security Identifier (SID) interface definition. */ -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #ifdef __cplusplus extern "C" { diff --git a/usr/src/uts/common/smbsrv/smb_xdr.h b/usr/src/uts/common/smbsrv/smb_xdr.h index 51bf3b57e2..aaf0ff070f 100644 --- a/usr/src/uts/common/smbsrv/smb_xdr.h +++ b/usr/src/uts/common/smbsrv/smb_xdr.h @@ -34,14 +34,13 @@ extern "C" { #include <sys/param.h> #include <sys/avl.h> #include <sys/list.h> -#include <smbsrv/wintypes.h> +#include <smb/wintypes.h> #include <smbsrv/smb_sid.h> #include <smbsrv/smbinfo.h> #include <smbsrv/smb_ioctl.h> #include <smbsrv/smb_sid.h> #include <smbsrv/smb_share.h> #include <smbsrv/smb_dfs.h> -#include <smbsrv/wintypes.h> #if defined(_KERNEL) || defined(_FAKE_KERNEL) #include <sys/sysmacros.h> diff --git a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE index f8cd22f7df..7741eb3a6b 100644 --- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE +++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE @@ -1,6 +1,7 @@ -Copyright (c) 2013 LSI Corp. +Copyright (c) 2012-2015 LSI Corp. +Copyright (c) 2013-2016 Avago Technologies All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -12,7 +13,7 @@ are met: 3. Neither the name of the author nor the names of any co-contributors may be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE diff --git a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE.descrip b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE.descrip index 88aaf438dc..3d80aca794 100644 --- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE.descrip +++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mpi/THIRDPARTYLICENSE.descrip @@ -1 +1 @@ -LSI Fusion-MPT MPI 2.0 / 2.5 Header Files +LSI Fusion-MPT MPI 2.0 / 2.5 / 2.6 Header Files |