diff options
-rw-r--r-- | source3/include/smb_perfcount.h | 8 | ||||
-rw-r--r-- | source3/modules/perfcount_onefs.c | 64 | ||||
-rw-r--r-- | source3/modules/perfcount_test.c | 47 | ||||
-rw-r--r-- | source3/smbd/reply.c | 17 |
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."); } |