DO_PROFILE_INC(authentication); \
DO_PROFILE_INC(authentication_failed); \
+struct profile_stats_persvc {
+ struct profile_stats stats;
+ int snum;
+ int refcnt;
+ bool active;
+ char dbkey[];
+};
+
extern struct profile_stats *profile_p;
struct smbprofile_global_state {
struct {
struct profile_stats global;
} stats;
+
+ struct {
+ struct profile_stats_persvc **tbl;
+ } persvc;
};
extern struct smbprofile_global_state smbprofile_state;
struct messaging_context;
bool profile_setup(struct messaging_context *msg_ctx, bool rdonly);
+/* Per-share profiling */
+#ifdef WITH_PROFILE
+
+void smbprofile_persvc_mkref(int snum, const char *svc, const char *remote);
+void smbprofile_persvc_unref(int snum);
+struct profile_stats *smbprofile_persvc_get(int snum);
+
+#else /* WITH_PROFILE */
+
+static inline void smbprofile_persvc_mkref(int snum,
+ const char *svc,
+ const char *remote)
+{
+ return;
+}
+
+static inline void smbprofile_persvc_unref(int snum)
+{
+ return;
+}
+
+static inline struct profile_stats *smbprofile_persvc_get(int snum)
+{
+ return NULL;
+}
+
+#endif /* WITH_PROFILE */
+
#endif
#include "messages.h"
#include "smbprofile.h"
#include "lib/tdb_wrap/tdb_wrap.h"
+#include "lib/util/util_tdb.h"
#include <tevent.h>
#include "../lib/crypto/crypto.h"
#include "source3/smbd/globals.h"
#include <sys/resource.h>
#endif
+static void smbprofile_persvc_dump(void);
+
struct profile_stats *profile_p;
struct smbprofile_global_state smbprofile_state;
tdb_chainunlock(smbprofile_state.internal.db->tdb, key);
ZERO_STRUCT(profile_p->values);
+ smbprofile_persvc_dump();
+
return;
}
profile_p->magic,
stats);
}
+
+/* Per-share profiling */
+
+static bool smbprofile_persvc_grow(int snum)
+{
+ struct profile_stats_persvc **new_tbl = NULL;
+ const size_t cur_cap = talloc_array_length(smbprofile_state.persvc.tbl);
+ size_t new_cap = 0;
+
+ if ((size_t)snum < cur_cap) {
+ return true;
+ }
+
+ new_cap = (size_t)snum + 1;
+ new_tbl = talloc_realloc(NULL,
+ smbprofile_state.persvc.tbl,
+ struct profile_stats_persvc *,
+ new_cap);
+
+ if (new_tbl == NULL) {
+ DBG_ERR("Failed to realloc persvc table for snum %d\n", snum);
+ return false;
+ }
+
+ memset(&new_tbl[cur_cap], 0, (new_cap - cur_cap) * sizeof(*new_tbl));
+
+ smbprofile_state.persvc.tbl = new_tbl;
+ return true;
+}
+
+static struct profile_stats_persvc *smbprofile_persvc_lookup(int snum)
+{
+ if (!smbprofile_active() || (snum < 0) ||
+ (snum >= (int)talloc_array_length(smbprofile_state.persvc.tbl))) {
+ return NULL;
+ }
+
+ return smbprofile_state.persvc.tbl[snum];
+}
+
+static struct profile_stats_persvc *smbprofile_persvc_insert(int snum,
+ const char *svc,
+ const char *remote)
+{
+ struct profile_stats_persvc *entry = NULL;
+ char *dbkey = NULL;
+ size_t len = 0;
+ bool ok;
+
+ ok = smbprofile_persvc_grow(snum);
+ if (!ok) {
+ return NULL;
+ }
+
+ dbkey = talloc_asprintf(talloc_tos(),
+ "%s:%d.%d[%s]",
+ svc,
+ (int)tevent_cached_getpid(),
+ snum,
+ remote);
+ if (dbkey == NULL) {
+ return NULL;
+ }
+
+ len = strlen(dbkey);
+ entry = talloc_zero_size(NULL, sizeof(*entry) + len + 1);
+ if (entry == NULL) {
+ TALLOC_FREE(dbkey);
+ DBG_ERR("Failed to allocate entry for snum %d\n", snum);
+ return NULL;
+ }
+
+ entry->snum = snum;
+ entry->refcnt = 0;
+ memcpy(entry->dbkey, dbkey, len);
+ TALLOC_FREE(dbkey);
+
+ smbprofile_state.persvc.tbl[snum] = entry;
+ return entry;
+}
+
+static void smbprofile_persvc_delete(struct profile_stats_persvc *entry)
+{
+ SMB_ASSERT(entry->snum >= 0);
+ SMB_ASSERT(smbprofile_state.persvc.tbl[entry->snum] == entry);
+
+ smbprofile_state.persvc.tbl[entry->snum] = NULL;
+ TALLOC_FREE(entry);
+}
+
+void smbprofile_persvc_mkref(int snum, const char *svc, const char *remote)
+{
+ struct profile_stats_persvc *persvc = NULL;
+
+ if (!smbprofile_active() || (snum < 0) || (svc == NULL)) {
+ return;
+ }
+
+ persvc = smbprofile_persvc_lookup(snum);
+ if (persvc == NULL) {
+ persvc = smbprofile_persvc_insert(snum, svc, remote);
+ }
+
+ if (persvc != NULL) {
+ persvc->refcnt++;
+ persvc->active = true;
+ }
+}
+
+void smbprofile_persvc_unref(int snum)
+{
+ struct profile_stats_persvc *persvc = NULL;
+
+ persvc = smbprofile_persvc_lookup(snum);
+ if (persvc != NULL) {
+ persvc->refcnt--;
+ }
+}
+
+struct profile_stats *smbprofile_persvc_get(int snum)
+{
+ struct profile_stats_persvc *persvc = NULL;
+
+ if (!smbprofile_active() || (snum < 0)) {
+ return NULL;
+ }
+
+ persvc = smbprofile_persvc_lookup(snum);
+ if (persvc == NULL) {
+ return NULL;
+ }
+
+ persvc->active = true;
+ return &persvc->stats;
+}
+
+static TDB_DATA tdb_keyof(struct profile_stats_persvc *persvc)
+{
+ return string_tdb_data(persvc->dbkey);
+}
+
+static void smbprofile_persvc_store(struct profile_stats_persvc *persvc)
+{
+ TDB_DATA val = {.dptr = (uint8_t *)(&persvc->stats),
+ .dsize = sizeof(persvc->stats)};
+
+ tdb_store(smbprofile_state.internal.db->tdb, tdb_keyof(persvc), val, 0);
+}
+
+static void smbprofile_persvc_clear(struct profile_stats_persvc *persvc)
+{
+ tdb_delete(smbprofile_state.internal.db->tdb, tdb_keyof(persvc));
+ smbprofile_persvc_delete(persvc);
+}
+
+static void smbprofile_persvc_dump(void)
+{
+ struct profile_stats_persvc *entry = NULL;
+ size_t i, cap;
+
+ if (!smbprofile_active()) {
+ return;
+ }
+
+ if (smbprofile_state.internal.db == NULL) {
+ return;
+ }
+
+ cap = talloc_array_length(smbprofile_state.persvc.tbl);
+ for (i = 0; i < cap; ++i) {
+ entry = smbprofile_state.persvc.tbl[i];
+ if (entry != NULL) {
+ if (entry->refcnt == 0) {
+ smbprofile_persvc_clear(entry);
+ } else if (entry->active) {
+ smbprofile_persvc_store(entry);
+ entry->active = false;
+ }
+ }
+ }
+}
+