summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb_perfcount.h8
-rw-r--r--source3/modules/perfcount_onefs.c64
-rw-r--r--source3/modules/perfcount_test.c47
-rw-r--r--source3/smbd/reply.c17
4 files changed, 120 insertions, 16 deletions
diff --git a/source3/include/smb_perfcount.h b/source3/include/smb_perfcount.h
index 218045be88..01a539d508 100644
--- a/source3/include/smb_perfcount.h
+++ b/source3/include/smb_perfcount.h
@@ -39,6 +39,8 @@ struct smb_perfcount_handlers {
uint64_t out_bytes);
void (*perfcount_set_client) (struct smb_perfcount_data *pcd, uid_t uid,
const char *user, const char *domain);
+ void (*perfcount_copy_context) (struct smb_perfcount_data *pcd,
+ struct smb_perfcount_data *new_pcd);
void (*perfcount_defer_op) (struct smb_perfcount_data *pcd,
struct smb_perfcount_data *def_pcd);
void (*perfcount_end) (struct smb_perfcount_data *pcd);
@@ -86,13 +88,17 @@ void smb_init_perfcount_data(struct smb_perfcount_data *pcd);
(_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_COPY_CONTEXT(_pcd_, _new_pcd_) \
+ do {if((_pcd_) && (_pcd_)->handlers) \
+ (_pcd_)->handlers->perfcount_copy_context((_pcd_), (_new_pcd_)); \
+ } while (0)
+
#define SMB_PERFCOUNT_DEFER_OP(_pcd_, _def_pcd_) \
do {if((_pcd_) && (_pcd_)->handlers) \
(_pcd_)->handlers->perfcount_defer_op((_pcd_), (_def_pcd_)); \
diff --git a/source3/modules/perfcount_onefs.c b/source3/modules/perfcount_onefs.c
index a4fbe6ad53..9b35af699a 100644
--- a/source3/modules/perfcount_onefs.c
+++ b/source3/modules/perfcount_onefs.c
@@ -29,7 +29,7 @@ struct onefs_op_counter {
};
struct onefs_stats_context {
- bool deferred;
+ bool alloced;
struct isp_op_delta iod;
/* ANDX commands stats stored here */
@@ -107,7 +107,6 @@ static void onefs_smb_statistics_set_op(struct smb_perfcount_data *pcd, int op)
if (pcd->context == NULL)
return;
-
iod = onefs_stats_get_op_delta(ctxt);
iod->op = isp_cifs_op_id(op);
@@ -197,6 +196,50 @@ static void onefs_smb_statistics_set_msglen_out(struct smb_perfcount_data *pcd,
ctxt->iod.out_bytes = out_bytes;
}
+static int onefs_copy_perfcount_context(struct onefs_stats_context *ctxt,
+ struct onefs_stats_context **dest)
+{
+ struct onefs_stats_context *new_ctxt;
+
+ /* make an alloc'd copy of the data */
+ new_ctxt = SMB_MALLOC_P(struct onefs_stats_context);
+ if (!new_ctxt) {
+ return -1;
+ }
+
+ memcpy(new_ctxt, ctxt, sizeof(struct onefs_stats_context));
+ new_ctxt->alloced = True;
+ *dest = new_ctxt;
+ return 0;
+}
+
+static void onefs_smb_statistics_copy_context(struct smb_perfcount_data *pcd,
+ struct smb_perfcount_data *dest)
+{
+ struct onefs_stats_context *ctxt = pcd->context;
+ struct onefs_stats_context *new_ctxt;
+ int ret;
+
+ /* not enabled */
+ if (pcd->context == NULL)
+ return;
+
+#ifdef ONEFS_PERF_DEBUG
+ DEBUG(0,("******** COPYING op %s(%d)\n",
+ onefs_stat_debug(&ctxt->iod), ctxt->iod.op));
+#endif
+
+ ret = onefs_copy_perfcount_context(ctxt, &new_ctxt);
+ if (ret)
+ return;
+
+ /* instrumentation */
+ if (ctxt == &g_context)
+ ZERO_STRUCT(g_context);
+
+ dest->context = new_ctxt;
+}
+
/*
* For perf reasons, we usually use the global - sometimes, though,
* when an operation is deferred, we need to alloc a copy.
@@ -206,35 +249,29 @@ static void onefs_smb_statistics_defer_op(struct smb_perfcount_data *pcd,
{
struct onefs_stats_context *ctxt = pcd->context;
struct onefs_stats_context *deferred_ctxt;
+ int ret;
/* not enabled */
if (pcd->context == NULL)
return;
/* already allocated ? */
- if (ctxt->deferred)
+ if (ctxt->alloced)
{
def_pcd->context = ctxt;
pcd->context = NULL;
return;
}
-
#ifdef ONEFS_PERF_DEBUG
DEBUG(0,("******** DEFERRING op %s(%d)\n",
onefs_stat_debug(&ctxt->iod), ctxt->iod.op));
#endif
- /* make an alloc'd copy of the data */
- deferred_ctxt = SMB_MALLOC_P(struct onefs_stats_context);
- if (!deferred_ctxt) {
- /* disable for now - we'll get bogus stats, though */
- def_pcd->context = NULL;
+ ret = onefs_copy_perfcount_context(ctxt, &deferred_ctxt);
+ if (ret)
return;
- }
- memcpy(deferred_ctxt, ctxt, sizeof(struct onefs_stats_context));
- deferred_ctxt->deferred = True;
def_pcd->context = (void*) deferred_ctxt;
/* instrumentation */
@@ -284,7 +321,7 @@ static void onefs_smb_statistics_end(struct smb_perfcount_data *pcd)
ctxt->iod.in_bytes, ctxt->iod.out_bytes));
#endif
- if (ctxt->deferred)
+ if (ctxt->alloced)
SAFE_FREE(ctxt);
else
ZERO_STRUCTP(ctxt);
@@ -302,6 +339,7 @@ static struct smb_perfcount_handlers onefs_pc_handlers = {
onefs_smb_statistics_set_msglen_in,
onefs_smb_statistics_set_msglen_out,
onefs_smb_statistics_set_client,
+ onefs_smb_statistics_copy_context,
onefs_smb_statistics_defer_op,
onefs_smb_statistics_end
};
diff --git a/source3/modules/perfcount_test.c b/source3/modules/perfcount_test.c
index b140172af4..418d83ace5 100644
--- a/source3/modules/perfcount_test.c
+++ b/source3/modules/perfcount_test.c
@@ -294,6 +294,52 @@ static void perfcount_test_set_msglen_out(struct smb_perfcount_data *pcd,
ctxt->ops->bytes_out = bytes_out;
}
+static void perfcount_test_copy_context(struct smb_perfcount_data *pcd,
+ struct smb_perfcount_data *new_pcd)
+{
+ struct perfcount_test_context *ctxt =
+ (struct perfcount_test_context *)pcd->context;
+ struct perfcount_test_context *new_ctxt;
+
+ struct perfcount_test_counter *ctr;
+ struct perfcount_test_counter *new_ctr;
+
+ if (pcd->context == NULL)
+ return;
+
+ new_ctxt = SMB_MALLOC_P(struct perfcount_test_context);
+ if (!new_ctxt) {
+ return;
+ }
+
+ memcpy(new_ctxt, ctxt, sizeof(struct perfcount_test_context));
+
+ for (ctr = ctxt->ops; ctr != NULL; ctr = ctr->next) {
+ new_ctr = SMB_MALLOC_P(struct perfcount_test_counter);
+ if (!new_ctr) {
+ goto error;
+ }
+
+ memcpy(new_ctr, ctr, sizeof(struct perfcount_test_counter));
+ new_ctr->next = NULL;
+ new_ctr->prev = NULL;
+ DLIST_ADD(new_ctxt->ops, new_ctr);
+ }
+
+ new_pcd->context = new_ctxt;
+ return;
+
+error:
+
+ for (ctr = new_ctxt->ops; ctr != NULL; ) {
+ new_ctr = ctr->next;
+ SAFE_FREE(ctr);
+ ctr = new_ctr;
+ }
+
+ SAFE_FREE(new_ctxt);
+}
+
/*
* For perf reasons, its best to use some global state
* when an operation is deferred, we need to alloc a copy.
@@ -337,6 +383,7 @@ static struct smb_perfcount_handlers perfcount_test_handlers = {
perfcount_test_set_msglen_in,
perfcount_test_set_msglen_out,
perfcount_test_set_client,
+ perfcount_test_copy_context,
perfcount_test_defer_op,
perfcount_test_end
};
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 1ceda99fa7..457f9412a9 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -4621,11 +4621,15 @@ void reply_tdis(struct smb_request *req)
void reply_echo(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ struct smb_perfcount_data local_pcd;
+ struct smb_perfcount_data *cur_pcd;
int smb_reverb;
int seq_num;
START_PROFILE(SMBecho);
+ smb_init_perfcount_data(&local_pcd);
+
if (req->wct < 1) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
END_PROFILE(SMBecho);
@@ -4646,14 +4650,23 @@ void reply_echo(struct smb_request *req)
smb_reverb = 100;
}
- for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
+ for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
+
+ /* this makes sure we catch the request pcd */
+ if (seq_num == smb_reverb) {
+ cur_pcd = &req->pcd;
+ } else {
+ SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
+ cur_pcd = &local_pcd;
+ }
+
SSVAL(req->outbuf,smb_vwv0,seq_num);
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
IS_CONN_ENCRYPTED(conn)||req->encrypted,
- &req->pcd))
+ cur_pcd))
exit_server_cleanly("reply_echo: srv_send_smb failed.");
}