S3: Make changes to perfcount API set for when a single request leads to multiple...
authortodd stecher <todd.stecher@gmail.com>
Tue, 17 Feb 2009 04:45:45 +0000 (20:45 -0800)
committerTim Prouty <tprouty@samba.org>
Thu, 19 Feb 2009 08:01:00 +0000 (00:01 -0800)
(e.g. reply_echo). Change test and onefs modules to match new api set (thanks Volker!).

source3/include/smb_perfcount.h
source3/modules/perfcount_onefs.c
source3/modules/perfcount_test.c
source3/smbd/reply.c

index 218045be88c847c067e0c0e53d8d0a37bc797432..01a539d508c2db84286041818251965c143ad955 100644 (file)
@@ -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_)); \
index a4fbe6ad5318423e3efa9f836552dc3c8496d995..9b35af699a665ecfcfbbf74d74d09e25ab6a3b08 100644 (file)
@@ -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
 };
index b140172af40eef8337009e9fb6fdeb6eb4f8c857..418d83ace571a3ccf7e6c6ede36694c695e4cd07 100644 (file)
@@ -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
 };
index 1ceda99fa7d41fea729f94632226729fba451355..457f9412a91d0bbe771c56437c0868c38061f825 100644 (file)
@@ -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.");
        }