S3: New module interface for SMB message statistics gathering
authortodd stecher <todd.stecher@gmail.com>
Mon, 9 Feb 2009 07:10:34 +0000 (23:10 -0800)
committerTim Prouty <tprouty@samba.org>
Mon, 9 Feb 2009 21:23:44 +0000 (13:23 -0800)
This changelist allows for the addition of custom performance
monitoring modules through smb.conf. Entrypoints in the main message
processing code have been added to capture the command, subop, ioctl,
identity and message size statistics.

19 files changed:
docs-xml/smbdotconf/misc/perfcountmodule.xml [new file with mode: 0644]
source3/Makefile.in
source3/configure.in
source3/include/includes.h
source3/include/proto.h
source3/include/smb.h
source3/include/smb_perfcount.h [new file with mode: 0644]
source3/param/loadparm.c
source3/smbd/aio.c
source3/smbd/blocking.c
source3/smbd/ipc.c
source3/smbd/notify.c
source3/smbd/nttrans.c
source3/smbd/oplock.c
source3/smbd/perfcount.c [new file with mode: 0644]
source3/smbd/pipes.c
source3/smbd/process.c
source3/smbd/reply.c
source3/smbd/trans2.c

diff --git a/docs-xml/smbdotconf/misc/perfcountmodule.xml b/docs-xml/smbdotconf/misc/perfcountmodule.xml
new file mode 100644 (file)
index 0000000..f22c399
--- /dev/null
@@ -0,0 +1,13 @@
+<samba:parameter name="perfcount module"
+                context="G"
+                type="string"
+                advanced="1"
+                xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+       <para>This parameter specifies the perfcount backend to be used when monitoring SMB
+       operations.  Only one perfcount module may be used, and it must implement all of the
+       apis contained in the smb_perfcount_handler structure defined in smb.h.
+       </para>
+</description>
+
+</samba:parameter>
index ee75eb30e6b5b1ffda0a806e6369592d98b2ed48..a775eafe057caf8ddd6bc7c95e2b8a06c7550cac 100644 (file)
@@ -108,6 +108,7 @@ MODULESDIR = @modulesdir@
 INCLUDEDIR=@includedir@
 PAMMODULESDIR = @pammodulesdir@
 VFSLIBDIR = $(MODULESDIR)/vfs
 INCLUDEDIR=@includedir@
 PAMMODULESDIR = @pammodulesdir@
 VFSLIBDIR = $(MODULESDIR)/vfs
+PERFCOUNTLIBDIR = $(MODULESDIR)/perfcount
 PDBLIBDIR = $(MODULESDIR)/pdb
 RPCLIBDIR = $(MODULESDIR)/rpc
 IDMAPLIBDIR = $(MODULESDIR)/idmap
 PDBLIBDIR = $(MODULESDIR)/pdb
 RPCLIBDIR = $(MODULESDIR)/rpc
 IDMAPLIBDIR = $(MODULESDIR)/idmap
@@ -220,6 +221,7 @@ NSS_MODULES = @NSS_MODULES@
 SCRIPTS = $(srcdir)/script/smbtar $(builddir)/script/findsmb
 
 VFS_MODULES = @VFS_MODULES@
 SCRIPTS = $(srcdir)/script/smbtar $(builddir)/script/findsmb
 
 VFS_MODULES = @VFS_MODULES@
+PERFCOUNT_MODULES = @PERFCOUNT_MODULES@
 PDB_MODULES = @PDB_MODULES@
 RPC_MODULES = @RPC_MODULES@
 IDMAP_MODULES = @IDMAP_MODULES@
 PDB_MODULES = @PDB_MODULES@
 RPC_MODULES = @RPC_MODULES@
 IDMAP_MODULES = @IDMAP_MODULES@
@@ -229,7 +231,7 @@ NSS_INFO_MODULES = @NSS_INFO_MODULES@
 GPEXT_MODULES = @GPEXT_MODULES@
 MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) \
           $(CHARSET_MODULES) $(AUTH_MODULES) $(NSS_INFO_MODULES) \
 GPEXT_MODULES = @GPEXT_MODULES@
 MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) \
           $(CHARSET_MODULES) $(AUTH_MODULES) $(NSS_INFO_MODULES) \
-         $(GPEXT_MODULES)
+         $(GPEXT_MODULES) $(PERFCOUNT_MODULES)
 
 EXTRA_ALL_TARGETS = @EXTRA_ALL_TARGETS@
 
 
 EXTRA_ALL_TARGETS = @EXTRA_ALL_TARGETS@
 
@@ -698,7 +700,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
                smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
               smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
               smbd/blocking.o smbd/sec_ctx.o smbd/srvstr.o \
                smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
               smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
               smbd/blocking.o smbd/sec_ctx.o smbd/srvstr.o \
-              smbd/vfs.o smbd/statcache.o smbd/seal.o \
+              smbd/vfs.o smbd/perfcount.o smbd/statcache.o smbd/seal.o \
                smbd/posix_acls.o lib/sysacls.o $(SERVER_MUTEX_OBJ) \
               smbd/process.o smbd/service.o smbd/error.o \
               printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
                smbd/posix_acls.o lib/sysacls.o $(SERVER_MUTEX_OBJ) \
               smbd/process.o smbd/service.o smbd/error.o \
               printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
@@ -2689,6 +2691,7 @@ installmodules:: modules installdirs
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(CHARSETLIBDIR) $(CHARSET_MODULES)
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(AUTHLIBDIR) $(AUTH_MODULES)
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(GPEXTLIBDIR) $(GPEXT_MODULES)
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(CHARSETLIBDIR) $(CHARSET_MODULES)
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(AUTHLIBDIR) $(AUTH_MODULES)
        @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(GPEXTLIBDIR) $(GPEXT_MODULES)
+       @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(PERFCOUNTLIBDIR) $(PERFCOUNT_MODULES)
        @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ NDS_ldapsam.@SHLIBEXT@
        @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ NDS_ldapsam_compat.@SHLIBEXT@
        @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ ldapsam_compat.@SHLIBEXT@
        @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ NDS_ldapsam.@SHLIBEXT@
        @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ NDS_ldapsam_compat.@SHLIBEXT@
        @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ ldapsam_compat.@SHLIBEXT@
@@ -2780,6 +2783,7 @@ uninstallmodules::
        @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(CHARSETLIBDIR) $(CHARSET_MODULES)
        @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(AUTHLIBDIR) $(AUTH_MODULES)
        @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(GPEXTLIBDIR) $(GPEXT_MODULES)
        @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(CHARSETLIBDIR) $(CHARSET_MODULES)
        @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(AUTHLIBDIR) $(AUTH_MODULES)
        @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(GPEXTLIBDIR) $(GPEXT_MODULES)
+       @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS_BIN) $(DESTDIR) $(prefix) $(PERFCOUNTLIBDIR) $(PERFCOUNT_MODULES)
 
 uninstallscripts::
        @$(SHELL) $(srcdir)/script/uninstallscripts.sh $(INSTALLPERMS_BIN) $(DESTDIR)$(BINDIR) $(SCRIPTS)
 
 uninstallscripts::
        @$(SHELL) $(srcdir)/script/uninstallscripts.sh $(INSTALLPERMS_BIN) $(DESTDIR)$(BINDIR) $(SCRIPTS)
index 37ee9a131f92928ff98d3a73ad3ec92e023e9b5d..86fb84c37ec4165dc6c360d2205c91bee0f2a8bb 100644 (file)
@@ -6416,9 +6416,10 @@ SMB_MODULE(vfs_acl_xattr, \$(VFS_ACL_XATTR_OBJ), "bin/acl_xattr.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_acl_tdb, \$(VFS_ACL_TDB_OBJ), "bin/acl_tdb.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_smb_traffic_analyzer, \$(VFS_SMB_TRAFFIC_ANALYZER_OBJ), "bin/smb_traffic_analyzer.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_onefs, \$(VFS_ONEFS), "bin/onefs.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_acl_tdb, \$(VFS_ACL_TDB_OBJ), "bin/acl_tdb.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_smb_traffic_analyzer, \$(VFS_SMB_TRAFFIC_ANALYZER_OBJ), "bin/smb_traffic_analyzer.$SHLIBEXT", VFS)
 SMB_MODULE(vfs_onefs, \$(VFS_ONEFS), "bin/onefs.$SHLIBEXT", VFS)
-
 SMB_SUBSYSTEM(VFS,smbd/vfs.o)
 
 SMB_SUBSYSTEM(VFS,smbd/vfs.o)
 
+SMB_SUBSYSTEM(PERFCOUNT,smbd/perfcount.o)
+
 SMB_MODULE(gpext_registry, libgpo/gpext/registry.o, "bin/registry.$SHLIBEXT", GPEXT)
 SMB_MODULE(gpext_scripts, libgpo/gpext/scripts.o, "bin/scripts.$SHLIBEXT", GPEXT)
 SMB_MODULE(gpext_security, libgpo/gpext/security.o, "bin/security.$SHLIBEXT", GPEXT)
 SMB_MODULE(gpext_registry, libgpo/gpext/registry.o, "bin/registry.$SHLIBEXT", GPEXT)
 SMB_MODULE(gpext_scripts, libgpo/gpext/scripts.o, "bin/scripts.$SHLIBEXT", GPEXT)
 SMB_MODULE(gpext_security, libgpo/gpext/security.o, "bin/security.$SHLIBEXT", GPEXT)
index 930df6e36cd33227fe229b7f2d0549df934ee9ad..095fcaa3da2d33b12417bac24302f493cd1372a9 100644 (file)
@@ -597,6 +597,7 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx);
 #include "privileges.h"
 #include "messages.h"
 #include "locking.h"
 #include "privileges.h"
 #include "messages.h"
 #include "locking.h"
+#include "smb_perfcount.h"
 #include "smb.h"
 #include "nameserv.h"
 #include "secrets.h"
 #include "smb.h"
 #include "nameserv.h"
 #include "secrets.h"
index 537eb98ffc52acf76b6c582f25da3fc52e351176..7deaff3e190e638970822efa58934b8ab0c7909c 100644 (file)
@@ -4358,6 +4358,8 @@ void lp_set_posix_pathnames(void);
 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp);
 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val);
 int lp_min_receive_file_size(void);
 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp);
 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val);
 int lp_min_receive_file_size(void);
+char* lp_smb_perfcount_module(void);
+
 
 /* The following definitions come from param/params.c  */
 
 
 /* The following definitions come from param/params.c  */
 
@@ -6978,7 +6980,8 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname);
 
 void smbd_setup_sig_term_handler(void);
 void smbd_setup_sig_hup_handler(void);
 
 void smbd_setup_sig_term_handler(void);
 void smbd_setup_sig_hup_handler(void);
-bool srv_send_smb(int fd, char *buffer, bool do_encrypt);
+bool srv_send_smb(int fd, char *buffer, bool do_encrypt,
+                 struct smb_perfcount_data *pcd);
 int srv_set_message(char *buf,
                         int num_words,
                         int num_bytes,
 int srv_set_message(char *buf,
                         int num_words,
                         int num_bytes,
index eaf09dd09c3f375544851e86d577fe2653ad8a1c..3da63cfc2b15be1cb829b738031e6317bff346ac 100644 (file)
@@ -613,6 +613,7 @@ struct current_user {
        NT_USER_TOKEN *nt_user_token;
 };
 
        NT_USER_TOKEN *nt_user_token;
 };
 
+
 struct smb_request {
        uint8_t cmd;
        uint16 flags2;
 struct smb_request {
        uint8_t cmd;
        uint16 flags2;
@@ -640,6 +641,7 @@ struct smb_request {
        size_t unread_bytes;
        bool encrypted;
        connection_struct *conn;
        size_t unread_bytes;
        bool encrypted;
        connection_struct *conn;
+       struct smb_perfcount_data pcd;
 
        /*
         * Chained request handling
 
        /*
         * Chained request handling
@@ -717,6 +719,7 @@ struct pending_message_list {
        struct pending_message_list *next, *prev;
        struct timeval request_time; /* When was this first issued? */
        struct timed_event *te;
        struct pending_message_list *next, *prev;
        struct timeval request_time; /* When was this first issued? */
        struct timed_event *te;
+       struct smb_perfcount_data pcd;
        bool encrypted;
        DATA_BLOB buf;
        DATA_BLOB private_data;
        bool encrypted;
        DATA_BLOB buf;
        DATA_BLOB private_data;
diff --git a/source3/include/smb_perfcount.h b/source3/include/smb_perfcount.h
new file mode 100644 (file)
index 0000000..218045b
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+   Unix SMB/CIFS implementation.
+   Portable SMB Messaging statistics interfaces
+   Copyright (C) Todd Stecher (2008)
+
+   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/>.
+*/
+
+#ifndef _SMB_PERFCOUNT_H_
+#define _SMB_PERFCOUNT_H_
+
+#define SMB_PERFCOUNTER_INTERFACE_VERSION      1
+
+struct smb_perfcount_data{
+       struct smb_perfcount_handlers *handlers;
+       void *context;
+};
+
+struct smb_perfcount_handlers {
+       void (*perfcount_start) (struct smb_perfcount_data *pcd);
+       void (*perfcount_add) (struct smb_perfcount_data *pcd);
+       void (*perfcount_set_op) (struct smb_perfcount_data *pcd, int op);
+       void (*perfcount_set_subop) (struct smb_perfcount_data *pcd, int subop);
+       void (*perfcount_set_ioctl) (struct smb_perfcount_data *pcd, int io_ctl);
+       void (*perfcount_set_msglen_in) (struct smb_perfcount_data *pcd,
+                                        uint64_t in_bytes);
+       void (*perfcount_set_msglen_out) (struct smb_perfcount_data *pcd,
+                                         uint64_t out_bytes);
+       void (*perfcount_set_client) (struct smb_perfcount_data *pcd, uid_t uid,
+                                     const char *user, const char *domain);
+       void (*perfcount_defer_op) (struct smb_perfcount_data *pcd,
+                                   struct smb_perfcount_data *def_pcd);
+       void (*perfcount_end) (struct smb_perfcount_data *pcd);
+};
+
+bool smb_perfcount_init(void);
+
+NTSTATUS smb_register_perfcounter(int interface_version, const char *name,
+                                 const struct smb_perfcount_handlers *handlers);
+
+void smb_init_perfcount_data(struct smb_perfcount_data *pcd);
+
+#define SMB_PERFCOUNT_START(_pcd_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_start((_pcd_)); \
+    } while (0)
+
+#define SMB_PERFCOUNT_ADD(_pcd_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_add((_pcd_)); \
+    } while (0)
+
+#define SMB_PERFCOUNT_SET_OP(_pcd_,_op_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_set_op((_pcd_), (_op_)); \
+    } while (0)
+
+#define SMB_PERFCOUNT_SET_SUBOP(_pcd_,_subop_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_set_subop((_pcd_), (_subop_)); \
+    } while (0)
+
+#define SMB_PERFCOUNT_SET_IOCTL(_pcd_,_subop_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_set_ioctl((_pcd_), (_subop_)); \
+    } while (0)
+
+#define SMB_PERFCOUNT_SET_MSGLEN_IN(_pcd_,_in_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_set_msglen_in((_pcd_), (_in_));\
+    } while (0)
+
+#define SMB_PERFCOUNT_SET_MSGLEN_OUT(_pcd_,_out_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_set_msglen_out((_pcd_), (_out_));\
+    } while (0)
+
+
+#define SMB_PERFCOUNT_SET_CLIENT(_pcd_,_uid_, _user_, _domain_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_set_client((_pcd_), (_uid_), \
+              (_user_), (_domain_)); \
+    } while (0)
+
+#define SMB_PERFCOUNT_DEFER_OP(_pcd_, _def_pcd_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_defer_op((_pcd_), (_def_pcd_)); \
+    } while (0)
+
+#define SMB_PERFCOUNT_END(_pcd_) \
+    do {if((_pcd_) && (_pcd_)->handlers) \
+           (_pcd_)->handlers->perfcount_end((_pcd_));\
+    } while (0)
+
+#endif /* _SMB_PERFCOUNT_H_ */
index bc7d9974f44bbe2822c2627d671a29bb34d9c230..0dfbb09331fd459e2aa57f686944c40831e3266c 100644 (file)
@@ -344,6 +344,7 @@ struct global {
        int iminreceivefile;
        struct param_opt_struct *param_opt;
        int cups_connection_timeout;
        int iminreceivefile;
        struct param_opt_struct *param_opt;
        int cups_connection_timeout;
+       char *szSMBPerfcountModule;
 };
 
 static struct global Globals;
 };
 
 static struct global Globals;
@@ -4258,6 +4259,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
                .enum_list      = NULL,
                .flags          = FLAG_ADVANCED,
        },
+       {
+               .label          = "perfcount module",
+               .type           = P_STRING,
+               .p_class        = P_GLOBAL,
+               .ptr            = &Globals.szSMBPerfcountModule,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_ADVANCED,
+       },
 
        {N_("VFS module options"), P_SEP, P_SEPARATOR},
 
 
        {N_("VFS module options"), P_SEP, P_SEPARATOR},
 
@@ -5163,6 +5173,7 @@ FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
+FN_GLOBAL_STRING(lp_smb_perfcount_module, &Globals.szSMBPerfcountModule)
 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
index 64d512d675dd34cd3a077942cc218d85934165bb..75ce07d41a9d4c4921c96d9228e26964f95b9985 100644 (file)
@@ -301,7 +301,8 @@ bool schedule_aio_write_and_X(connection_struct *conn,
                 SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
                show_msg(aio_ex->outbuf);
                if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf,
                 SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
                show_msg(aio_ex->outbuf);
                if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf,
-                               IS_CONN_ENCRYPTED(fsp->conn))) {
+                               IS_CONN_ENCRYPTED(fsp->conn),
+                               &req->pcd)) {
                        exit_server_cleanly("handle_aio_write: srv_send_smb "
                                            "failed.");
                }
                        exit_server_cleanly("handle_aio_write: srv_send_smb "
                                            "failed.");
                }
@@ -375,7 +376,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
        smb_setlen(outbuf,outsize - 4);
        show_msg(outbuf);
        if (!srv_send_smb(smbd_server_fd(),outbuf,
        smb_setlen(outbuf,outsize - 4);
        show_msg(outbuf);
        if (!srv_send_smb(smbd_server_fd(),outbuf,
-                       IS_CONN_ENCRYPTED(aio_ex->fsp->conn))) {
+                       IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) {
                exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
                                    "failed.");
        }
                exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
                                    "failed.");
        }
@@ -472,7 +473,8 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
        }
 
        show_msg(outbuf);
        }
 
        show_msg(outbuf);
-       if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn))) {
+       if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn),
+                         NULL)) {
                exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
        }
 
                exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
        }
 
index ac1ff008589c9fc787cdfa045d950c6f3a1030ad..659ef700cb4a8a3c0cb42df97a1577eae3ac0ee4 100644 (file)
@@ -192,6 +192,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
                return False;
        }
 
                return False;
        }
 
+       SMB_PERFCOUNT_DEFER_OP(&req->pcd, &req->pcd);
        blr->req = talloc_move(blr, &req);
 
        DLIST_ADD_END(blocking_lock_queue, blr, blocking_lock_record *);
        blr->req = talloc_move(blr, &req);
 
        DLIST_ADD_END(blocking_lock_queue, blr, blocking_lock_record *);
@@ -266,7 +267,7 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat
 
        reply_nterror(blr->req, status);
        if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf,
 
        reply_nterror(blr->req, status);
        if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf,
-                         blr->req->encrypted)) {
+                         blr->req->encrypted, NULL)) {
                exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
        }
        TALLOC_FREE(blr->req->outbuf);
                exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
        }
        TALLOC_FREE(blr->req->outbuf);
@@ -347,7 +348,8 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status
 
                if (!srv_send_smb(smbd_server_fd(),
                                  (char *)blr->req->outbuf,
 
                if (!srv_send_smb(smbd_server_fd(),
                                  (char *)blr->req->outbuf,
-                                 IS_CONN_ENCRYPTED(blr->fsp->conn))) {
+                                 IS_CONN_ENCRYPTED(blr->fsp->conn),
+                                 NULL)) {
                        exit_server_cleanly("blocking_lock_reply_error: "
                                            "srv_send_smb failed.");
                }
                        exit_server_cleanly("blocking_lock_reply_error: "
                                            "srv_send_smb failed.");
                }
index 9c7528dfa7af34af545921f5f6b740fa9d8d65f7..d18b5debe0da46acfeb7126e22e7bb38348f2f88 100644 (file)
@@ -134,7 +134,7 @@ void send_trans_reply(connection_struct *conn,
 
        show_msg((char *)req->outbuf);
        if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
 
        show_msg((char *)req->outbuf);
        if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
-                         IS_CONN_ENCRYPTED(conn))) {
+                         IS_CONN_ENCRYPTED(conn), &req->pcd)) {
                exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
        }
 
                exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
        }
 
@@ -190,7 +190,7 @@ void send_trans_reply(connection_struct *conn,
 
                show_msg((char *)req->outbuf);
                if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
 
                show_msg((char *)req->outbuf);
                if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
-                                 IS_CONN_ENCRYPTED(conn)))
+                                 IS_CONN_ENCRYPTED(conn), &req->pcd))
                        exit_server_cleanly("send_trans_reply: srv_send_smb "
                                            "failed.");
 
                        exit_server_cleanly("send_trans_reply: srv_send_smb "
                                            "failed.");
 
@@ -298,7 +298,8 @@ static void api_dcerpc_cmd_write_done(struct async_req *subreq)
  send:
        if (!srv_send_smb(
                    smbd_server_fd(), (char *)req->outbuf,
  send:
        if (!srv_send_smb(
                    smbd_server_fd(), (char *)req->outbuf,
-                   IS_CONN_ENCRYPTED(req->conn) || req->encrypted)) {
+                   IS_CONN_ENCRYPTED(req->conn) || req->encrypted,
+                   &req->pcd)) {
                exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
        TALLOC_FREE(req);
                exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
        TALLOC_FREE(req);
@@ -324,7 +325,7 @@ static void api_dcerpc_cmd_read_done(struct async_req *subreq)
 
                if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
                                  IS_CONN_ENCRYPTED(req->conn)
 
                if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
                                  IS_CONN_ENCRYPTED(req->conn)
-                                 ||req->encrypted)) {
+                                 ||req->encrypted, &req->pcd)) {
                        exit_server_cleanly("construct_reply: srv_send_smb "
                                            "failed.");
                }
                        exit_server_cleanly("construct_reply: srv_send_smb "
                                            "failed.");
                }
index 7ffe62058c36be78a51557ba8ac5922de92650ec..1d4f5e8c5b3f6e9c22ecb8ad45d7285bc22eabf3 100644 (file)
@@ -144,7 +144,7 @@ static void change_notify_reply_packet(connection_struct *conn,
 
        show_msg((char *)req->outbuf);
        if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
 
        show_msg((char *)req->outbuf);
        if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
-                         req->encrypted)) {
+                         req->encrypted, &req->pcd)) {
                exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
                                    "failed.");
        }
                exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
                                    "failed.");
        }
index 0ad4df6e90dcc1accf2d995bf1c0fed91ff3ae22..ad2366efae446276e5dc02632d9e1d7ff2cefaed 100644 (file)
@@ -230,7 +230,8 @@ void send_nt_replies(connection_struct *conn,
                show_msg((char *)req->outbuf);
                if (!srv_send_smb(smbd_server_fd(),
                                (char *)req->outbuf,
                show_msg((char *)req->outbuf);
                if (!srv_send_smb(smbd_server_fd(),
                                (char *)req->outbuf,
-                               IS_CONN_ENCRYPTED(conn))) {
+                               IS_CONN_ENCRYPTED(conn),
+                               &req->pcd)) {
                        exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
                }
 
                        exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
                }
 
@@ -1823,6 +1824,8 @@ static void call_nt_transact_ioctl(connection_struct *conn,
           because I don't want to break anything... --metze
        FSP_BELONGS_CONN(fsp,conn);*/
 
           because I don't want to break anything... --metze
        FSP_BELONGS_CONN(fsp,conn);*/
 
+       SMB_PERFCOUNT_SET_IOCTL(&req->pcd, function);
+
        switch (function) {
        case FSCTL_SET_SPARSE:
                /* pretend this succeeded - tho strictly we should
        switch (function) {
        case FSCTL_SET_SPARSE:
                /* pretend this succeeded - tho strictly we should
@@ -2489,6 +2492,9 @@ static void handle_nttrans(connection_struct *conn,
                SSVAL(req->inbuf,smb_flg2,req->flags2);
        }
 
                SSVAL(req->inbuf,smb_flg2,req->flags2);
        }
 
+
+       SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
+
        /* Now we must call the relevant NT_TRANS function */
        switch(state->call) {
                case NT_TRANSACT_CREATE:
        /* Now we must call the relevant NT_TRANS function */
        switch(state->call) {
                case NT_TRANSACT_CREATE:
index 788d2f7238cbf88a87ec9244d07dd84736f4b520..3dac674c17a1d4b22727464161f6ea7f616943e3 100644 (file)
@@ -406,7 +406,8 @@ static void process_oplock_async_level2_break_message(struct messaging_context *
        show_msg(break_msg);
        if (!srv_send_smb(smbd_server_fd(),
                        break_msg,
        show_msg(break_msg);
        if (!srv_send_smb(smbd_server_fd(),
                        break_msg,
-                       IS_CONN_ENCRYPTED(fsp->conn))) {
+                       IS_CONN_ENCRYPTED(fsp->conn),
+                       NULL)) {
                exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
                exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
@@ -513,7 +514,8 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
        show_msg(break_msg);
        if (!srv_send_smb(smbd_server_fd(),
                        break_msg,
        show_msg(break_msg);
        if (!srv_send_smb(smbd_server_fd(),
                        break_msg,
-                       IS_CONN_ENCRYPTED(fsp->conn))) {
+                       IS_CONN_ENCRYPTED(fsp->conn),
+                       NULL)) {
                exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
                exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
@@ -592,7 +594,8 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
        show_msg(break_msg);
        if (!srv_send_smb(smbd_server_fd(),
                        break_msg,
        show_msg(break_msg);
        if (!srv_send_smb(smbd_server_fd(),
                        break_msg,
-                       IS_CONN_ENCRYPTED(fsp->conn))) {
+                       IS_CONN_ENCRYPTED(fsp->conn),
+                       NULL)) {
                exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
                exit_server_cleanly("oplock_break: srv_send_smb failed.");
        }
 
diff --git a/source3/smbd/perfcount.c b/source3/smbd/perfcount.c
new file mode 100644 (file)
index 0000000..0ad706c
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+   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"
+
+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(0,("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 = (struct smb_perfcount_handlers*) handlers;
+
+       DLIST_ADD(modules, entry);
+       DEBUG(0, ("Successfully added perfcounter module '%s'\n", name));
+       return NT_STATUS_OK;
+}
+
+/****************************************************************************
+  initialise smb perf counters
+ ****************************************************************************/
+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(0,("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("perfcount", module_path)) &&
+               (entry = smb_perfcount_find_module(module_name)))) {
+
+               DEBUG(0,("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)
+{
+       char *perfcount_object;
+
+       perfcount_object = lp_smb_perfcount_module();
+
+       /* 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;
+}
index f287adc92d4462fef87c523436c3486e1b1295e3..6fd4031f3d60ba4b9fe3e2068f97f2354a5b6c0b 100644 (file)
@@ -216,7 +216,8 @@ static void pipe_write_done(struct async_req *subreq)
 
  send:
        if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
 
  send:
        if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
-                         IS_CONN_ENCRYPTED(req->conn)||req->encrypted)) {
+                         IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
+                         &req->pcd)) {
                exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
        TALLOC_FREE(req);
                exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
        TALLOC_FREE(req);
index 8539e04bd50c892a4df7a4d8ce6cf6f7a9fc6758..1262d018409bc710fb53586a183c5ed7eacf76a8 100644 (file)
@@ -32,9 +32,10 @@ static void construct_reply_common(struct smb_request *req, const char *inbuf,
  Send an smb to a fd.
 ****************************************************************************/
 
  Send an smb to a fd.
 ****************************************************************************/
 
-bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
+bool srv_send_smb(int fd, char *buffer, bool do_encrypt,
+                 struct smb_perfcount_data *pcd)
 {
 {
-       size_t len;
+       size_t len = 0;
        size_t nwritten=0;
        ssize_t ret;
        char *buf_out = buffer;
        size_t nwritten=0;
        ssize_t ret;
        char *buf_out = buffer;
@@ -48,7 +49,7 @@ bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
                        DEBUG(0, ("send_smb: SMB encryption failed "
                                "on outgoing packet! Error %s\n",
                                nt_errstr(status) ));
                        DEBUG(0, ("send_smb: SMB encryption failed "
                                "on outgoing packet! Error %s\n",
                                nt_errstr(status) ));
-                       return false;
+                       goto out;
                }
        }
 
                }
        }
 
@@ -60,12 +61,15 @@ bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
                        DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
                                (int)len,(int)ret, strerror(errno) ));
                        srv_free_enc_buffer(buf_out);
                        DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
                                (int)len,(int)ret, strerror(errno) ));
                        srv_free_enc_buffer(buf_out);
-                       return false;
+                       goto out;
                }
                nwritten += ret;
        }
 
                }
                nwritten += ret;
        }
 
+       SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
        srv_free_enc_buffer(buf_out);
        srv_free_enc_buffer(buf_out);
+out:
+       SMB_PERFCOUNT_END(pcd);
        return true;
 }
 
        return true;
 }
 
@@ -373,6 +377,7 @@ void init_smb_request(struct smb_request *req,
        req->conn = conn_find(req->tid);
        req->chain_fsp = NULL;
        req->chain_outbuf = NULL;
        req->conn = conn_find(req->tid);
        req->chain_fsp = NULL;
        req->chain_outbuf = NULL;
+       smb_init_perfcount_data(&req->pcd);
 
        /* Ensure we have at least wct words and 2 bytes of bcc. */
        if (smb_size + req->wct*2 > req_size) {
 
        /* Ensure we have at least wct words and 2 bytes of bcc. */
        if (smb_size + req->wct*2 > req_size) {
@@ -390,12 +395,13 @@ void init_smb_request(struct smb_request *req,
                        (unsigned int)req_size));
                exit_server_cleanly("Invalid SMB request");
        }
                        (unsigned int)req_size));
                exit_server_cleanly("Invalid SMB request");
        }
+
        req->outbuf = NULL;
 }
 
 static void process_smb(struct smbd_server_connection *conn,
                        uint8_t *inbuf, size_t nread, size_t unread_bytes,
        req->outbuf = NULL;
 }
 
 static void process_smb(struct smbd_server_connection *conn,
                        uint8_t *inbuf, size_t nread, size_t unread_bytes,
-                       bool encrypted);
+                       bool encrypted, struct smb_perfcount_data *deferred_pcd);
 
 static void smbd_deferred_open_timer(struct event_context *ev,
                                     struct timed_event *te,
 
 static void smbd_deferred_open_timer(struct event_context *ev,
                                     struct timed_event *te,
@@ -421,7 +427,7 @@ static void smbd_deferred_open_timer(struct event_context *ev,
 
        process_smb(smbd_server_conn, inbuf,
                    msg->buf.length, 0,
 
        process_smb(smbd_server_conn, inbuf,
                    msg->buf.length, 0,
-                   msg->encrypted);
+                   msg->encrypted, &msg->pcd);
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
@@ -453,6 +459,7 @@ static bool push_queued_message(struct smb_request *req,
 
        msg->request_time = request_time;
        msg->encrypted = req->encrypted;
 
        msg->request_time = request_time;
        msg->encrypted = req->encrypted;
+       SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
 
        if (private_data) {
                msg->private_data = data_blob_talloc(msg, private_data,
 
        if (private_data) {
                msg->private_data = data_blob_talloc(msg, private_data,
@@ -1354,7 +1361,9 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
  Construct a reply to the incoming packet.
 ****************************************************************************/
 
  Construct a reply to the incoming packet.
 ****************************************************************************/
 
-static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
+static void construct_reply(char *inbuf, int size, size_t unread_bytes,
+                           bool encrypted,
+                           struct smb_perfcount_data *deferred_pcd)
 {
        connection_struct *conn;
        struct smb_request *req;
 {
        connection_struct *conn;
        struct smb_request *req;
@@ -1362,9 +1371,19 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool enc
        if (!(req = talloc(talloc_tos(), struct smb_request))) {
                smb_panic("could not allocate smb_request");
        }
        if (!(req = talloc(talloc_tos(), struct smb_request))) {
                smb_panic("could not allocate smb_request");
        }
+
        init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
        req->inbuf  = (uint8_t *)talloc_move(req, &inbuf);
 
        init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
        req->inbuf  = (uint8_t *)talloc_move(req, &inbuf);
 
+       /* we popped this message off the queue - keep original perf data */
+       if (deferred_pcd)
+               req->pcd = *deferred_pcd;
+       else {
+               SMB_PERFCOUNT_START(&req->pcd);
+               SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
+               SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
+       }
+
        conn = switch_message(req->cmd, req, size);
 
        if (req->unread_bytes) {
        conn = switch_message(req->cmd, req, size);
 
        if (req->unread_bytes) {
@@ -1386,7 +1405,8 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool enc
 
        if (!srv_send_smb(smbd_server_fd(),
                        (char *)req->outbuf,
 
        if (!srv_send_smb(smbd_server_fd(),
                        (char *)req->outbuf,
-                       IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
+                       IS_CONN_ENCRYPTED(conn)||req->encrypted,
+                       &req->pcd)) {
                exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
 
                exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
 
@@ -1398,10 +1418,9 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool enc
 /****************************************************************************
  Process an smb from the client
 ****************************************************************************/
 /****************************************************************************
  Process an smb from the client
 ****************************************************************************/
-
 static void process_smb(struct smbd_server_connection *conn,
                        uint8_t *inbuf, size_t nread, size_t unread_bytes,
 static void process_smb(struct smbd_server_connection *conn,
                        uint8_t *inbuf, size_t nread, size_t unread_bytes,
-                       bool encrypted)
+                       bool encrypted, struct smb_perfcount_data *deferred_pcd)
 {
        int msg_type = CVAL(inbuf,0);
 
 {
        int msg_type = CVAL(inbuf,0);
 
@@ -1423,8 +1442,7 @@ static void process_smb(struct smbd_server_connection *conn,
 
        show_msg((char *)inbuf);
 
 
        show_msg((char *)inbuf);
 
-       construct_reply((char *)inbuf,nread,unread_bytes,encrypted);
-
+       construct_reply((char *)inbuf,nread,unread_bytes,encrypted,deferred_pcd);
        trans_num++;
 
 done:
        trans_num++;
 
 done:
@@ -1617,16 +1635,24 @@ void chain_reply(struct smb_request *req)
                 */
                smb_setlen((char *)(req->chain_outbuf),
                           talloc_get_size(req->chain_outbuf) - 4);
                 */
                smb_setlen((char *)(req->chain_outbuf),
                           talloc_get_size(req->chain_outbuf) - 4);
+
                if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
                                  IS_CONN_ENCRYPTED(req->conn)
                if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
                                  IS_CONN_ENCRYPTED(req->conn)
-                                 ||req->encrypted)) {
+                                 ||req->encrypted,
+                                 &req->pcd)) {
                        exit_server_cleanly("chain_reply: srv_send_smb "
                                            "failed.");
                }
                TALLOC_FREE(req);
                        exit_server_cleanly("chain_reply: srv_send_smb "
                                            "failed.");
                }
                TALLOC_FREE(req);
+
                return;
        }
 
                return;
        }
 
+       /* add a new perfcounter for this element of chain */
+       SMB_PERFCOUNT_ADD(&req->pcd);
+       SMB_PERFCOUNT_SET_OP(&req->pcd, chain_cmd);
+       SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
+
        /*
         * Check if the client tries to fool us. The request so far uses the
         * space to the end of the byte buffer in the request just
        /*
         * Check if the client tries to fool us. The request so far uses the
         * space to the end of the byte buffer in the request just
@@ -1735,7 +1761,8 @@ void chain_reply(struct smb_request *req)
        show_msg((char *)(req->chain_outbuf));
 
        if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
        show_msg((char *)(req->chain_outbuf));
 
        if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
-                         IS_CONN_ENCRYPTED(req->conn)||req->encrypted)) {
+                         IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
+                         &req->pcd)) {
                exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
        TALLOC_FREE(req);
                exit_server_cleanly("construct_reply: srv_send_smb failed.");
        }
        TALLOC_FREE(req);
@@ -1823,7 +1850,7 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c
        }
 
 process:
        }
 
 process:
-       process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted);
+       process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted, NULL);
 }
 
 static void smbd_server_connection_handler(struct event_context *ev,
 }
 
 static void smbd_server_connection_handler(struct event_context *ev,
@@ -1988,7 +2015,7 @@ void smbd_process(void)
                unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
                DEBUG( 1, ("Connection denied from %s\n",
                           client_addr(get_client_fd(),addr,sizeof(addr)) ) );
                unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
                DEBUG( 1, ("Connection denied from %s\n",
                           client_addr(get_client_fd(),addr,sizeof(addr)) ) );
-               (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
+               (void)srv_send_smb(smbd_server_fd(),(char *)buf,false, NULL);
                exit_server_cleanly("connection denied");
        }
 
                exit_server_cleanly("connection denied");
        }
 
@@ -1996,6 +2023,8 @@ void smbd_process(void)
 
        init_modules();
 
 
        init_modules();
 
+       smb_perfcount_init();
+
        if (!init_account_policy()) {
                exit_server("Could not open account policy tdb.\n");
        }
        if (!init_account_policy()) {
                exit_server("Could not open account policy tdb.\n");
        }
index bb5fadd4658c4e768048a93c0be18c4474d199f2..60e2e5dc7a525cb878c54748fd821db57b906d09 100644 (file)
@@ -492,7 +492,7 @@ void reply_special(char *inbuf)
        DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
                    msg_type, msg_flags));
 
        DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
                    msg_type, msg_flags));
 
-       srv_send_smb(smbd_server_fd(), outbuf, false);
+       srv_send_smb(smbd_server_fd(), outbuf, false, NULL);
        return;
 }
 
        return;
 }
 
@@ -3293,6 +3293,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
 
                /* No outbuf here means successful sendfile. */
                TALLOC_FREE(req->outbuf);
 
                /* No outbuf here means successful sendfile. */
                TALLOC_FREE(req->outbuf);
+               SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
+               SMB_PERFCOUNT_END(&req->pcd);
                return;
        }
 #endif
                return;
        }
 #endif
@@ -3590,7 +3592,8 @@ void reply_writebraw(struct smb_request *req)
        show_msg(buf);
        if (!srv_send_smb(smbd_server_fd(),
                        buf,
        show_msg(buf);
        if (!srv_send_smb(smbd_server_fd(),
                        buf,
-                       IS_CONN_ENCRYPTED(conn))) {
+                       IS_CONN_ENCRYPTED(conn),
+                       &req->pcd)) {
                exit_server_cleanly("reply_writebraw: srv_send_smb "
                        "failed.");
        }
                exit_server_cleanly("reply_writebraw: srv_send_smb "
                        "failed.");
        }
@@ -4647,7 +4650,8 @@ void reply_echo(struct smb_request *req)
                show_msg((char *)req->outbuf);
                if (!srv_send_smb(smbd_server_fd(),
                                (char *)req->outbuf,
                show_msg((char *)req->outbuf);
                if (!srv_send_smb(smbd_server_fd(),
                                (char *)req->outbuf,
-                               IS_CONN_ENCRYPTED(conn)||req->encrypted))
+                               IS_CONN_ENCRYPTED(conn)||req->encrypted,
+                               &req->pcd))
                        exit_server_cleanly("reply_echo: srv_send_smb failed.");
        }
 
                        exit_server_cleanly("reply_echo: srv_send_smb failed.");
        }
 
index 6c082a8273e64a59dbce0b75881a394cc07b84fb..6a6e59a581a9dfbafaef08e983a12ac5b735451b 100644 (file)
@@ -832,7 +832,8 @@ void send_trans2_replies(connection_struct *conn,
                show_msg((char *)req->outbuf);
                if (!srv_send_smb(smbd_server_fd(),
                                (char *)req->outbuf,
                show_msg((char *)req->outbuf);
                if (!srv_send_smb(smbd_server_fd(),
                                (char *)req->outbuf,
-                               IS_CONN_ENCRYPTED(conn)))
+                               IS_CONN_ENCRYPTED(conn),
+                               &req->pcd))
                        exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
 
                TALLOC_FREE(req->outbuf);
                        exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
 
                TALLOC_FREE(req->outbuf);
@@ -7468,6 +7469,8 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req,
                }
        }
 
                }
        }
 
+       SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
+
        /* Now we must call the relevant TRANS2 function */
        switch(state->call)  {
        case TRANSACT2_OPEN:
        /* Now we must call the relevant TRANS2 function */
        switch(state->call)  {
        case TRANSACT2_OPEN: