From: Volker Lendecke Date: Tue, 9 Jan 2024 15:12:20 +0000 (+0100) Subject: smbprofile: Count failed requests X-Git-Tag: tevent-0.17.0~340 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8ea5b91dfdc73431d0f343dda66b4622d7140ed3;p=thirdparty%2Fsamba.git smbprofile: Count failed requests Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme Reviewed-by: Guenther Deschner --- diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index 3354770efe7..9692ebadef1 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -24,6 +24,8 @@ #include "replace.h" #include #include "lib/util/time.h" +#include "libcli/smb/smb2_constants.h" +#include "libcli/util/ntstatus.h" struct smbd_server_connection; struct tevent_context; @@ -293,6 +295,7 @@ struct smbprofile_stats_bytes_async { struct smbprofile_stats_iobytes { uint64_t count; /* number of events */ + uint64_t failed_count; /* number of unsuccessful events */ uint64_t time; /* microseconds */ uint64_t buckets[10]; /* 1,2,4,...256,Inf msecs */ uint64_t idle; /* idle time compared to 'time' microseconds */ @@ -459,10 +462,11 @@ struct profile_stats { _SMBPROFILE_TIMER_ASYNC_SET_IDLE(_async) #define SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(_async) \ _SMBPROFILE_TIMER_ASYNC_SET_BUSY(_async) -#define SMBPROFILE_IOBYTES_ASYNC_END(_async, _outbytes) do { \ +#define SMBPROFILE_IOBYTES_ASYNC_END(_async, _outbytes, _opcode, _status) do { \ if ((_async).stats != NULL) { \ (_async).stats->outbytes += (_outbytes); \ _SMBPROFILE_TIMER_ASYNC_END(_async); \ + smbprofile_update_failed_count((_async.stats), (_opcode), (_status)); \ smbprofile_update_hist((_async).stats, profile_timestamp() - (_async).start); \ (_async) = (struct smbprofile_stats_iobytes_async) {}; \ smbprofile_dump_schedule(); \ @@ -513,6 +517,37 @@ static inline bool smbprofile_active(void) return smbprofile_state.config.do_count; } +static inline void smbprofile_update_failed_count( + struct smbprofile_stats_iobytes *s, + uint16_t opcode, + NTSTATUS status) +{ + bool ok = NT_STATUS_IS_OK(status); + + switch (opcode) { + case SMB2_OP_SESSSETUP: + if (NT_STATUS_EQUAL(status, + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + ok = true; + } + break; + case SMB2_OP_QUERY_DIRECTORY: + if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_FILES)) { + ok = true; + } + break; + case SMB2_OP_NOTIFY: + if (NT_STATUS_EQUAL(status, NT_STATUS_CANCELLED)) { + ok = true; + } + break; + } + + if (!ok) { + s->failed_count += 1; + } +} + static inline void smbprofile_update_hist(struct smbprofile_stats_iobytes *s, uint64_t microsecs) { @@ -626,7 +661,7 @@ static inline uint64_t profile_timestamp(void) #define SMBPROFILE_IOBYTES_ASYNC_START(_name, _area, _async, _inbytes) #define SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(_async) #define SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(_async) -#define SMBPROFILE_IOBYTES_ASYNC_END(_async, _outbytes) +#define SMBPROFILE_IOBYTES_ASYNC_END(_async, _outbytes, _opcode, _status) #define DO_PROFILE_INC(x) #define START_PROFILE(x) diff --git a/source3/profile/profile_read.c b/source3/profile/profile_read.c index 3c4e6ebcfa3..c4b99b80e92 100644 --- a/source3/profile/profile_read.c +++ b/source3/profile/profile_read.c @@ -63,6 +63,8 @@ void smbprofile_stats_accumulate(struct profile_stats *acc, do { \ acc->values.name##_stats.count += \ add->values.name##_stats.count; \ + acc->values.name##_stats.failed_count += \ + add->values.name##_stats.failed_count; \ acc->values.name##_stats.time += \ add->values.name##_stats.time; \ acc->values.name##_stats.buckets[0] += \ diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 59f4a4aad5b..5c3b7b90dc9 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -3561,7 +3561,10 @@ skipped_signing: SMBPROFILE_IOBYTES_ASYNC_START(smb2_cancel, profile_p, req->profile, _INBYTES(req)); return_value = smbd_smb2_request_process_cancel(req); - SMBPROFILE_IOBYTES_ASYNC_END(req->profile, 0); + SMBPROFILE_IOBYTES_ASYNC_END(req->profile, + 0, + SMB2_OP_CANCEL, + NT_STATUS_OK); /* * We don't need the request anymore cancel requests never @@ -3746,8 +3749,11 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) } TALLOC_FREE(req->last_sign_key); - SMBPROFILE_IOBYTES_ASYNC_END(req->profile, - iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ-1)); + SMBPROFILE_IOBYTES_ASYNC_END( + req->profile, + iov_buflen(outhdr, SMBD_SMB2_NUM_IOV_PER_REQ - 1), + PULL_LE_U16(outhdr->iov_base, SMB2_HDR_OPCODE), + NT_STATUS(IVAL(outhdr->iov_base, SMB2_HDR_STATUS))); req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ; diff --git a/source3/utils/smb_prometheus_endpoint.c b/source3/utils/smb_prometheus_endpoint.c index 2fa1da9c6b2..3959a8511cc 100644 --- a/source3/utils/smb_prometheus_endpoint.c +++ b/source3/utils/smb_prometheus_endpoint.c @@ -28,10 +28,10 @@ struct export_state { struct evbuffer *buf; bool sent_help_cpu_seconds : 1; bool sent_help_smb1_request_total : 1; - bool sent_help_smb2_request_total : 1; bool sent_help_smb2_request_inbytes : 1; bool sent_help_smb2_request_outbytes : 1; bool sent_help_smb2_request_hist : 1; + bool sent_help_smb2_request_failed : 1; }; static void export_count(const char *name, @@ -202,6 +202,32 @@ static void export_iobytes_buckets(const char *name, } } +static void export_iobytes_failed(const char *name, + const struct smbprofile_stats_iobytes *val, + struct export_state *state) +{ + bool is_smb2; + + is_smb2 = (strncmp(name, "smb2_", 5) == 0); + if (is_smb2) { + if (!state->sent_help_smb2_request_failed) { + evbuffer_add_printf( + state->buf, + "# HELP smb_smb2_request_failed Number " + "of failed SMB2 requests\n" + "# TYPE smb_smb2_request_failed counter\n"); + state->sent_help_smb2_request_failed = true; + } + + evbuffer_add_printf( + state->buf, + "smb_smb2_request_failed { operation=\"%s\" } " + "%" PRIu64 "\n", + name + 5, + val->failed_count); + } +} + static void metrics_handler(struct evhttp_request *req, void *arg) { struct export_state state = {.buf = NULL}; @@ -389,6 +415,31 @@ static void metrics_handler(struct evhttp_request *req, void *arg) #undef SMBPROFILE_STATS_BYTES #undef SMBPROFILE_STATS_IOBYTES #undef SMBPROFILE_STATS_SECTION_END +#undef SMBPROFILE_STATS_END + +#define SMBPROFILE_STATS_START +#define SMBPROFILE_STATS_SECTION_START(name, display) +#define SMBPROFILE_STATS_COUNT(name) +#define SMBPROFILE_STATS_TIME(name) +#define SMBPROFILE_STATS_BASIC(name) +#define SMBPROFILE_STATS_BYTES(name) +#define SMBPROFILE_STATS_IOBYTES(name) \ + do { \ + export_iobytes_failed(#name, \ + &stats.values.name##_stats, \ + &state); \ + } while (0); +#define SMBPROFILE_STATS_SECTION_END +#define SMBPROFILE_STATS_END + SMBPROFILE_STATS_ALL_SECTIONS +#undef SMBPROFILE_STATS_START +#undef SMBPROFILE_STATS_SECTION_START +#undef SMBPROFILE_STATS_COUNT +#undef SMBPROFILE_STATS_TIME +#undef SMBPROFILE_STATS_BASIC +#undef SMBPROFILE_STATS_BYTES +#undef SMBPROFILE_STATS_IOBYTES +#undef SMBPROFILE_STATS_SECTION_END #undef SMBPROFILE_STATS_END evhttp_send_reply(req, HTTP_OK, "OK", state.buf); diff --git a/source3/utils/status_profile.c b/source3/utils/status_profile.c index 082bc5cb61e..299731b4813 100644 --- a/source3/utils/status_profile.c +++ b/source3/utils/status_profile.c @@ -125,6 +125,7 @@ bool status_profile_dump(bool verbose, } while(0); #define SMBPROFILE_STATS_IOBYTES(name) do { \ __PRINT_FIELD_LINE(#name, name##_stats, count); \ + __PRINT_FIELD_LINE(#name, name##_stats, failed_count); \ __PRINT_FIELD_LINE(#name, name##_stats, time); \ print_buckets(state, #name, &stats.values.name##_stats); \ __PRINT_FIELD_LINE(#name, name##_stats, idle); \