diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
commit | 4f5791ebd03eaec1c7da0865a383175b05102712 (patch) | |
tree | 8ce7b00f7a76baa386372422adebbe64510812d4 /source3/smbd/perfcount.c | |
parent | Initial commit. (diff) | |
download | samba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip |
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/smbd/perfcount.c')
-rw-r--r-- | source3/smbd/perfcount.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/source3/smbd/perfcount.c b/source3/smbd/perfcount.c new file mode 100644 index 0000000..c46cd3e --- /dev/null +++ b/source3/smbd/perfcount.c @@ -0,0 +1,195 @@ +/* + Unix SMB/Netbios implementation. + Perfcounter initialization and support functions + Copyright (C) Todd Stecher 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "includes.h" +#include "smbd/smbd.h" + +static struct smb_perfcount_handlers *g_smb_perfcount_handlers = NULL; + +struct smb_perfcount_module { + char *name; + struct smb_perfcount_handlers *handlers; + struct smb_perfcount_module *prev, *next; +}; + +struct smb_perfcount_module *modules = NULL; + + +/* + * a module is registered before it is actually loaded - keep a list + * + * @todo - currently perfcount modules are globally configured, so + * building the list is not strictly required. + * However, its a proven concept in VFS, and is here to allow a + * move to eventual per-service perfcount configuration. + * + * Note many pre-connection statistics are interesting + * (e.g. before binding to an individual share). + * + */ +static struct smb_perfcount_module *smb_perfcount_find_module(const char *name) +{ + struct smb_perfcount_module *entry = modules; + + while (entry) { + if (strcmp(entry->name, name)==0) + return entry; + + entry = entry->next; + } + + return NULL; +} +NTSTATUS smb_register_perfcounter(int interface_version, const char *name, + const struct smb_perfcount_handlers *handlers) +{ + struct smb_perfcount_module *entry = modules; + + if (interface_version != SMB_PERFCOUNTER_INTERFACE_VERSION) { + DEBUG(0, ("Failed to register perfcount module.\n" + "The module was compiled against " + "SMB_PERFCOUNTER_INTERFACE_VERSION %d,\n" + "current SMB_PERFCOUNTER_INTERFACE_VERSION is %d.\n" + "Please recompile against the current Samba Version!\n", + interface_version, SMB_PERFCOUNTER_INTERFACE_VERSION)); + return NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (!name || !name[0] || !handlers) { + DEBUG(0,("smb_register_perfcounter() called with NULL pointer " + "or empty name!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if (smb_perfcount_find_module(name)) { + DEBUG(3,("Perfcount Module %s already loaded!\n", name)); + return NT_STATUS_OK; + } + + entry = SMB_XMALLOC_P(struct smb_perfcount_module); + entry->name = smb_xstrdup(name); + entry->handlers = discard_const_p(struct smb_perfcount_handlers, handlers); + + DLIST_ADD(modules, entry); + DEBUG(3, ("Successfully added perfcounter module '%s'\n", name)); + return NT_STATUS_OK; +} + +/**************************************************************************** + initialise smb perf counters + ****************************************************************************/ +static bool smb_load_perfcount_module(const char *name) +{ + char *module_path = NULL; + char *module_name = NULL; + char *module_param = NULL, *p; + + const struct smb_perfcount_module *entry; + + DEBUG(3, ("Initialising perfcounter module [%s]\n", name)); + + if (g_smb_perfcount_handlers) { + DEBUG(3,("Only 1 perfcount handler may be registered in " + "smb.conf\n")); + return true; + } + + module_path = smb_xstrdup(name); + + p = strchr_m(module_path, ':'); + + if (p) { + *p = 0; + module_param = p+1; + trim_char(module_param, ' ', ' '); + } + + trim_char(module_path, ' ', ' '); + + module_name = smb_xstrdup(module_path); + + if (module_name[0] == '/') { + + /* + * Extract the module name from the path. Just use the base + * name of the last path component. + */ + + SAFE_FREE(module_name); + module_name = smb_xstrdup(strrchr_m(module_path, '/')+1); + + p = strchr_m(module_name, '.'); + + if (p != NULL) { + *p = '\0'; + } + } + + /* load the perfcounter module */ + if((entry = smb_perfcount_find_module(module_name)) || + (NT_STATUS_IS_OK(smb_probe_module_absolute_path(module_path)) && + (entry = smb_perfcount_find_module(module_name)))) { + + DEBUG(3,("Successfully loaded perfcounter module [%s] \n", name)); + } else { + DEBUG(0,("Can't find a perfcounter module [%s]\n",name)); + goto fail; + } + + g_smb_perfcount_handlers = entry->handlers; + + SAFE_FREE(module_path); + SAFE_FREE(module_name); + return True; + + fail: + SAFE_FREE(module_path); + SAFE_FREE(module_name); + return False; +} + +void smb_init_perfcount_data(struct smb_perfcount_data *pcd) +{ + + ZERO_STRUCTP(pcd); + pcd->handlers = g_smb_perfcount_handlers; +} + +bool smb_perfcount_init(void) +{ + const struct loadparm_substitution *lp_sub = + loadparm_s3_global_substitution(); + char *perfcount_object; + + perfcount_object = lp_perfcount_module(talloc_tos(), lp_sub); + + /* don't init */ + if (!perfcount_object || !perfcount_object[0]) + return True; + + if (!smb_load_perfcount_module(perfcount_object)) { + DEBUG(0, ("smbd_load_percount_module failed for %s\n", + perfcount_object)); + return False; + } + + + return True; +} |