Enabling profiling globally ...

Ralph Boehme slow at samba.org
Thu Apr 7 10:34:48 UTC 2016


On Wed, Apr 06, 2016 at 04:59:32PM -0700, Richard Sharpe wrote:
> On Wed, Apr 6, 2016 at 11:54 AM, Richard Sharpe
> <realrichardsharpe at gmail.com> wrote:
> >> that put it in your smb.conf. Cf man smb.conf, this is an existing
> >> parameter.
> >>
> >> This seems so obvious that I'm suspecting that I miss something
> >> here...
> >
> > Actually, there is one additional thing I would like to be able to do,
> > and that is have this switched on dynamically when the smb.conf
> > changes.
> >
> > Currently it is only checked/change when the smbd starts.
> 
> It turns out I was asking the wrong question.
> 
> What I really want is profiling on a per-share basis so I can figure
> out which shares to co-locate on the same nodes in a cluster and so
> forth based on which ones are getting more or less ops.

I have some dated wip patches that do just that afair. Attached, feel
free to munge and make something usable out of it. They don't apply to
master, but should be easy to massage them so they do.

The main problem is, that the stats aggregation becomes expensive with
many users and shares.

Cheerio!
-slow
-------------- next part --------------
From 30a2bbf7f39cdfd78636a54712c35fbe782c649e Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 10 Feb 2015 01:58:36 +0100
Subject: [PATCH 1/3] s3:smbprofile: collect share stats

Collect share stats into a stats array that is allocated and resized as
needed while traversing the db. The final stats array after traverse
contains one stats element per share.

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/include/smbprofile.h   |  10 +++-
 source3/profile/profile.c      | 101 +++++++++++++++++++++++++++++++++++------
 source3/utils/status_profile.c |  61 +++++++++++++++++++++----
 3 files changed, 150 insertions(+), 22 deletions(-)

diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h
index 05cf479..7e33994 100644
--- a/source3/include/smbprofile.h
+++ b/source3/include/smbprofile.h
@@ -547,7 +547,15 @@ void smbprofile_dump(void);
 void smbprofile_cleanup(pid_t pid);
 void smbprofile_stats_accumulate(struct profile_stats *acc,
 				 const struct profile_stats *add);
-void smbprofile_collect(struct profile_stats *stats);
+enum stats_collect {
+	ACCUMULATED_STATS = 0x01,
+	SHARES_STATS = 0x02
+};
+
+int smbprofile_collect(TALLOC_CTX *mem_ctx,
+		       enum stats_collect stats,
+		       struct profile_stats *acc_stats,
+		       struct profile_stats **dyn_stats);
 
 static inline uint64_t profile_timestamp(void)
 {
diff --git a/source3/profile/profile.c b/source3/profile/profile.c
index 50ad8a3..5451242 100644
--- a/source3/profile/profile.c
+++ b/source3/profile/profile.c
@@ -550,14 +550,25 @@ void smbprofile_stats_accumulate(struct profile_stats *acc,
 #undef SMBPROFILE_STATS_END
 }
 
+struct collect_state {
+	TALLOC_CTX *mem_ctx;
+	enum stats_collect stats;
+	struct profile_stats *acc_stats;
+	int dyn_count;
+	struct profile_stats **dyn_stats;
+};
+
 static int smbprofile_collect_fn(struct tdb_context *tdb,
 				 TDB_DATA key, TDB_DATA value,
 				 void *private_data)
 {
-	struct profile_stats *acc = (struct profile_stats *)private_data;
+	struct collect_state *collect_state = (struct collect_state *)private_data;
+	struct profile_stats *acc = collect_state->acc_stats;
+	struct profile_stats *dyn = *(collect_state->dyn_stats);
+	struct profile_stats *sh;
 	const struct profile_stats *v;
 	size_t num_stats;
-	size_t i;
+	size_t i, j;
 
 	if ((value.dsize % sizeof(struct profile_stats)) != 0) {
 		return 0;
@@ -575,32 +586,96 @@ static int smbprofile_collect_fn(struct tdb_context *tdb,
 	}
 
 	for (i = 0; i < num_stats; i++) {
-		smbprofile_stats_accumulate(acc, &v[i]);
+		/*
+		 * Loop through all stats from the db and accumulate
+		 * to the requested stats
+		 */
+
+		if (collect_state->stats & ACCUMULATED_STATS) {
+			smbprofile_stats_accumulate(acc, &v[i]);
+		}
+
+		if (collect_state->stats & SHARES_STATS) {
+			if (strnequal(v[i].keys.primary,
+				      "GLOBAL-STATS",
+				      strlen("GLOBAL-STATS"))) {
+				continue;
+			}
+
+			/*
+			 * Loop through the array where we collect the
+			 * stats and see if there's already stats
+			 * element for this share. Allocate one if
+			 * not.
+			 */
+
+			sh = NULL;
+			for (j = 0; j < collect_state->dyn_count; j++) {
+				if (strequal(v[i].keys.secondary,
+					     dyn[j].keys.secondary)) {
+					sh = &dyn[j];
+					break;
+				}
+			}
+
+			if (sh == NULL) {
+				/*
+				 * No stats element for this share
+				 * yet, add one.
+				 */
+				dyn = *(collect_state->dyn_stats) = talloc_realloc(
+					collect_state->mem_ctx,
+					dyn,
+					struct profile_stats,
+					collect_state->dyn_count + 1);
+				if (dyn == NULL) {
+					return 0;
+				}
+				sh = &dyn[collect_state->dyn_count++];
+				*sh = (struct profile_stats) {};
+				strncpy(sh->keys.secondary,
+					v[i].keys.secondary,
+					sizeof(sh->keys.secondary));
+			}
+			smbprofile_stats_accumulate(sh, &v[i]);
+		}
 	}
 
 	return 0;
 }
 
-void smbprofile_collect(struct profile_stats *stats)
+int smbprofile_collect(TALLOC_CTX *mem_ctx,
+		       enum stats_collect stats,
+		       struct profile_stats *acc_stats,
+		       struct profile_stats **dyn_stats)
 {
 	int count;
-
-	*stats = (struct profile_stats) {};
-
-	snprintf(stats->keys.primary,
-		 sizeof(stats->keys.primary),
+	struct collect_state collect_state = {
+		.mem_ctx = mem_ctx,
+		.stats = stats,
+		.acc_stats = acc_stats,
+		.dyn_count = 0,
+		.dyn_stats = dyn_stats
+	};
+
+	*acc_stats = (struct profile_stats) {};
+
+	snprintf(acc_stats->keys.primary,
+		 sizeof(acc_stats->keys.primary),
 		 "%s", "ACCUMULATED-STATS");
 
 	if (smbprofile_state.internal.db == NULL) {
-		return;
+		return -1;
 	}
 
 	count = tdb_traverse_read(smbprofile_state.internal.db->tdb,
-				  smbprofile_collect_fn, stats);
+				  smbprofile_collect_fn, &collect_state);
 
-	snprintf(stats->keys.additional,
-		 sizeof(stats->keys.additional),
+	snprintf(acc_stats->keys.additional,
+		 sizeof(acc_stats->keys.additional),
 		 "num_profile_stat records: %d", count);
+
+	return collect_state.dyn_count;
 }
 
 struct profile_stats *smbprofile_setup_stats_area(const char *primary_key,
diff --git a/source3/utils/status_profile.c b/source3/utils/status_profile.c
index cc0ddc4..2df45c7 100644
--- a/source3/utils/status_profile.c
+++ b/source3/utils/status_profile.c
@@ -44,13 +44,17 @@ static void profile_separator(const char * title)
 bool status_profile_dump(bool verbose)
 {
 	struct profile_stats stats = {};
+	int result;
 
 	if (!profile_setup(NULL, True)) {
 		fprintf(stderr,"Failed to initialise profile memory\n");
 		return False;
 	}
 
-	smbprofile_collect(&stats);
+	result = smbprofile_collect(NULL, ACCUMULATED_STATS, &stats, NULL);
+	if (result == -1) {
+		return false;
+	}
 
 #define __PRINT_FIELD_LINE(name, _stats, field) do { \
 	d_printf("%-59s%20ju\n", \
@@ -332,6 +336,7 @@ bool status_profile_rates(bool verbose)
 	int last = 0;
 	int current = 1;
 	int tmp;
+	int result;
 
 	if (verbose) {
 	    fprintf(stderr, "Sampling stats at %d sec intervals\n",
@@ -343,13 +348,20 @@ bool status_profile_rates(bool verbose)
 		return False;
 	}
 
-	smbprofile_collect(&sample_data[last]);
+	result = smbprofile_collect(NULL, ACCUMULATED_STATS, &sample_data[last], NULL);
+	if (result == -1) {
+		return false;
+	}
+
 	for (;;) {
 		sample_time[current] = profile_timestamp();
 		next_usec = sample_time[current] + sample_interval_usec;
 
 		/* Take a sample. */
-		smbprofile_collect(&sample_data[current]);
+		result = smbprofile_collect(NULL, ACCUMULATED_STATS, &sample_data[current], NULL);
+		if (result == -1) {
+			return false;
+		}
 
 		/* Rate convert some values and print results. */
 		delta_usec = sample_time[current] - sample_time[last];
@@ -422,11 +434,17 @@ struct status_profile_prompt_state {
 		 */
 		bool accumulated_needed;
 		bool accumulated_loaded;
+		bool shares_needed;
+		bool shares_loaded;
 	} current_cache, prev_cache;
 
 	struct {
 		struct profile_stats stats;
 	} accumulated;
+
+	struct {
+		struct profile_stats *stats;
+	} shares;
 };
 
 static int status_profile_prompt_options(struct status_profile_prompt_state *state)
@@ -503,6 +521,8 @@ static int status_profile_prompt_options(struct status_profile_prompt_state *sta
 static int status_profile_reload_cache(struct status_profile_prompt_state *state)
 {
 	uint64_t current_time = profile_timestamp();
+	int result = 0;
+	enum stats_collect req_stats;
 
 	if (!state->current_cache.accumulated_loaded &&
 	    state->current_cache.accumulated_needed)
@@ -510,10 +530,17 @@ static int status_profile_reload_cache(struct status_profile_prompt_state *state
 		state->current_cache.expire_time = 0;
 	}
 
+	if (!state->current_cache.shares_loaded &&
+	    state->current_cache.shares_needed)
+	{
+		state->current_cache.expire_time = 0;
+	}
+
 	if (state->current_cache.expire_time > current_time) {
 		return 0;
 	}
 
+	TALLOC_FREE(state->shares.stats);
 	state->prev_cache = state->current_cache;
 
 	/*
@@ -523,18 +550,36 @@ static int status_profile_reload_cache(struct status_profile_prompt_state *state
 		.expire_time = current_time + (1 * 1000 * 1000),
 	};
 
-	if (state->prev_cache.accumulated_needed) {
-		smbprofile_collect(&state->accumulated.stats);
-		state->current_cache.accumulated_loaded = true;
+	if (state->prev_cache.accumulated_needed ||
+	    state->prev_cache.shares_needed) {
+
+		req_stats = state->prev_cache.accumulated_needed ? ACCUMULATED_STATS : 0;
+		req_stats |= state->prev_cache.shares_needed ? SHARES_STATS : 0;
+
+		result = smbprofile_collect(NULL,
+					    req_stats,
+					    &state->accumulated.stats,
+					    &state->shares.stats);
+		if (result == -1) {
+			return 0;
+		}
+		state->current_cache.accumulated_loaded = state->prev_cache.accumulated_needed;
+		state->current_cache.shares_loaded = state->prev_cache.shares_needed;
 	}
 
-	return 0;
+	return result;
 }
 
 static int status_profile_accumulated(struct status_profile_prompt_state *state)
 {
+	int result;
+
 	state->current_cache.accumulated_needed = true;
-	status_profile_reload_cache(state);
+	result = status_profile_reload_cache(state);
+	if (result == -1) {
+		d_printf("ERROR: can't reload cache\n");
+		return -1;
+	}
 
 	if (strcmp(state->output.format, "oneline-item") == 0) {
 #define SMBPROFILE_STATS_START \
-- 
2.5.0


From 78e9f7008ae2ac22df6b45921874a4b4b13f8c89 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 10 Feb 2015 04:59:20 +0100
Subject: [PATCH 2/3] s3:smbprofile: add get-shares command

TODO: output format "oneline-section"

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/utils/status_profile.c | 155 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 155 insertions(+)

diff --git a/source3/utils/status_profile.c b/source3/utils/status_profile.c
index 2df45c7..6db56c1 100644
--- a/source3/utils/status_profile.c
+++ b/source3/utils/status_profile.c
@@ -794,6 +794,156 @@ static int status_profile_accumulated(struct status_profile_prompt_state *state)
 	return 0;
 }
 
+static int status_profile_shares(struct status_profile_prompt_state *state)
+{
+	int result;
+	int i;
+
+	state->current_cache.shares_needed = true;
+	result = status_profile_reload_cache(state);
+	if (result == -1) {
+		d_printf("ERROR: can't reload cache\n");
+		return -1;
+	}
+
+	d_printf("_response_ begin shares\n");
+
+	for (i = 0;  i < result; i++) {
+		d_printf("_share_ begin %s\n", state->shares.stats[i].keys.secondary);
+
+		if (strcmp(state->output.format, "oneline-function") == 0) {
+#define SMBPROFILE_STATS_START
+#define SMBPROFILE_STATS_SECTION_START(name, display) do {    		\
+			if (state->output.sections == NULL ||		\
+				str_list_check(state->output.sections, #name)) \
+			{						\
+				const char *__section = #name;		\
+				size_t __len = strlen(__section); 	\
+				d_printf("_section_ begin %s\n", __section);
+#define __PREPARE_FIELD_NAME(name) \
+				const char *__n = name; 		\
+				int __cmp;				\
+				__cmp = strncmp(__section, __n, __len); \
+				if (__cmp == 0) {			\
+					__n += __len;			\
+					if (__n[0] == '_') {		\
+						__n += 1;		\
+					}				\
+				}
+#define __PRINT_FIELD_LINE(__s, __f) \
+				if (state->output.field_##__f) { 	\
+					d_printf(" _%s_ %ju",		\
+						 #__f,			\
+						 (uintmax_t)(state->shares.stats[i].values.__s.__f)); \
+				}
+#define __PRINT_DIFF_LINE(__s1, __s2, __f) \
+			if (state->output.field_##__f) {		\
+				d_printf(" _%s_ %ju",			\
+					 #__f,				\
+					 (uintmax_t)(state->accumulated.stats.values.__s1.__f - \
+						     state->accumulated.stats.values.__s2.__f)); \
+	}
+#define SMBPROFILE_STATS_COUNT(name) do { \
+				if (state->output.field_count) { 	\
+					__PREPARE_FIELD_NAME(#name);	\
+					d_printf("%s:", __n);		\
+					__PRINT_FIELD_LINE(name##_stats, count); \
+					d_printf("\n");			\
+				}					\
+} while(0);
+#define SMBPROFILE_STATS_TIME(name) do { \
+				if (state->output.field_time) { 	\
+					__PREPARE_FIELD_NAME(#name);	\
+					d_printf("%s:", __n);		\
+					__PRINT_FIELD_LINE(name##_stats, time); \
+					d_printf("\n");			\
+				}					\
+} while(0);
+#define SMBPROFILE_STATS_BASIC(name) do { \
+				if (state->output.field_count ||	\
+				    state->output.field_time)		\
+				{					\
+					__PREPARE_FIELD_NAME(#name);	\
+					d_printf("%s:", __n);		\
+					__PRINT_FIELD_LINE(name##_stats, count); \
+					__PRINT_FIELD_LINE(name##_stats, time); \
+					d_printf("\n");			\
+				}					\
+} while(0);
+#define SMBPROFILE_STATS_BYTES(name) do { \
+				if (state->output.field_count ||	\
+				    state->output.field_time ||		\
+				    state->output.field_idle ||		\
+				    state->output.field_bytes)		\
+				{					\
+					__PREPARE_FIELD_NAME(#name);	\
+					d_printf("%s:", __n);		\
+					__PRINT_FIELD_LINE(name##_stats, count); \
+					__PRINT_FIELD_LINE(name##_stats, time); \
+					__PRINT_FIELD_LINE(name##_stats, idle); \
+					__PRINT_FIELD_LINE(name##_stats, bytes); \
+					d_printf("\n");			\
+				}					\
+} while(0);
+#define SMBPROFILE_STATS_IOBYTES(name) do { \
+				if (state->output.field_count ||	\
+				    state->output.field_time ||		\
+				    state->output.field_idle ||		\
+				    state->output.field_inbytes ||	\
+				    state->output.field_outbytes)	\
+				{					\
+					__PREPARE_FIELD_NAME(#name);	\
+					d_printf("%s:", __n);		\
+					__PRINT_FIELD_LINE(name##_stats, count); \
+					__PRINT_FIELD_LINE(name##_stats, time); \
+					__PRINT_FIELD_LINE(name##_stats, idle); \
+					__PRINT_FIELD_LINE(name##_stats, inbytes); \
+					__PRINT_FIELD_LINE(name##_stats, outbytes); \
+					d_printf("\n");			\
+				}					\
+} while(0);
+#define SMBPROFILE_STATS_DIFF(display, name1, name2, metric) do {	\
+				if (state->output.field_##metric) {	\
+					__PREPARE_FIELD_NAME(#display);	\
+					d_printf("%s:", __n);		\
+					__PRINT_DIFF_LINE(name1##_stats, name2##_stats, metric); \
+					d_printf("\n");			\
+				}					\
+} while(0);
+#define SMBPROFILE_STATS_SECTION_END \
+				d_printf("_section_ end\n");	\
+			}					\
+} while(0);
+#define SMBPROFILE_STATS_END
+
+	SMBPROFILE_STATS_ALL_SECTIONS
+
+#undef SMBPROFILE_STATS_START
+#undef SMBPROFILE_STATS_SECTION_START
+#undef __PRINT_FIELD_LINE
+#undef __PRINT_DIFF_LINE
+#undef SMBPROFILE_STATS_COUNT
+#undef SMBPROFILE_STATS_TIME
+#undef SMBPROFILE_STATS_BASIC
+#undef SMBPROFILE_STATS_BYTES
+#undef SMBPROFILE_STATS_IOBYTES
+#undef SMBPROFILE_STATS_DIFF
+#undef SMBPROFILE_STATS_SECTION_END
+#undef SMBPROFILE_STATS_END
+
+		} else {
+			d_printf("ERROR: %s: invalid format[%s]\n",
+				 state->tmp.cmd, state->output.format);
+			return -1;
+		}
+		d_printf("_share_ end\n");
+	} /* for (i) */
+
+	d_printf("_response_ end\n");
+
+	return 0;
+}
+
 static int status_profile_prompt_flush(struct status_profile_prompt_state *state)
 {
 	struct server_id src = pid_to_procid(getpid());
@@ -830,6 +980,11 @@ int status_profile_prompt(void)
 		.fn = status_profile_accumulated,
 	},
 	{
+		.name = "get-shares",
+		.options = true,
+		.fn = status_profile_shares,
+	},
+	{
 		.name = "flush",
 		.fn = status_profile_prompt_flush,
 	},
-- 
2.5.0


From 9f9016ab5b3542822f0eb9f7b06355346ea79a01 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Wed, 11 Feb 2015 14:52:47 +0100
Subject: [PATCH 3/3] TODO/TESTING: s3:smbprofile: stats aggregation

Aggregating stats over a set of records USERS X SHARES may turn out to
be quite expensive, therefor add config switches that add aggregations
on just users or shares and a third option detailed.

TODO:
* testing!
* check copying and comparisons functions of keys: string vs block
---
 docs-xml/smbdotconf/misc/smbdprofilingstats.xml | 27 +++++++++++++++++++++++++
 lib/param/loadparm.c                            |  2 ++
 lib/param/loadparm.h                            |  3 +++
 lib/param/param_table.c                         |  7 +++++++
 source3/profile/profile.c                       |  2 ++
 source3/smbd/service.c                          | 15 +++++++++++---
 6 files changed, 53 insertions(+), 3 deletions(-)
 create mode 100644 docs-xml/smbdotconf/misc/smbdprofilingstats.xml

diff --git a/docs-xml/smbdotconf/misc/smbdprofilingstats.xml b/docs-xml/smbdotconf/misc/smbdprofilingstats.xml
new file mode 100644
index 0000000..75e66b1
--- /dev/null
+++ b/docs-xml/smbdotconf/misc/smbdprofilingstats.xml
@@ -0,0 +1,27 @@
+<samba:parameter name="smbd profiling stats"
+	         context="G"
+		 type="enum"
+		 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>
+	  This parameter allows the administrator to specify into which
+	  set stats are aggregated.
+	</para>
+	<para>
+	  Possible values are <constant>users</constant>,
+	  <constant>shares</constant> and
+	  <constant>detailed</constant>. Detailed will aggregate both
+	  <constant>users</constant> and <constant>shares</constant>
+	  stats.
+	</para>
+	<para>
+	  Please note that aggregating <constant>detailed</constant>
+	  stats may have some performance impact when reading the
+	  stats with smbstatus, due to the necessary processing of a
+	  set of num(users) X num(shares) records.
+	</para>
+</description>
+<value type="default">shares</value>
+<value type="example">users</value>
+<value type="example">detailed</value>
+</samba:parameter>
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
index 0a1c29a..5e10689 100644
--- a/lib/param/loadparm.c
+++ b/lib/param/loadparm.c
@@ -2684,6 +2684,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 
 	lpcfg_do_global_parameter(lp_ctx, "smbd profiling level", "off");
 
+	lpcfg_do_global_parameter(lp_ctx, "smbd profiling stats", "shares");
+
 	lpcfg_do_global_parameter(lp_ctx, "winbind cache time", "300");
 
 	lpcfg_do_global_parameter(lp_ctx, "level2 oplocks", "yes");
diff --git a/lib/param/loadparm.h b/lib/param/loadparm.h
index 89dcb17..43e759e 100644
--- a/lib/param/loadparm.h
+++ b/lib/param/loadparm.h
@@ -208,6 +208,9 @@ enum mapreadonly_options {MAP_READONLY_NO, MAP_READONLY_YES, MAP_READONLY_PERMIS
 /* case handling */
 enum case_handling {CASE_LOWER,CASE_UPPER};
 
+/* profiling aggregation */
+enum smbd_profile_stats {SMBD_PROFILE_SHARES, SMBD_PROFILE_USERS, SMBD_PROFILE_DETAILED};
+
 /*
  * Default passwd chat script.
  */
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index 92a7619..e856b07 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -180,6 +180,13 @@ static const struct enum_list enum_smbd_profiling_level[] = {
 	{0, "off"}, {1, "count"}, {2, "on"}, {-1, NULL}
 };
 
+static const struct enum_list enum_smbd_profiling_stats[] = {
+	{SMBD_PROFILE_SHARES, "shares"},
+	{SMBD_PROFILE_USERS, "users"},
+	{SMBD_PROFILE_DETAILED, "detailed"},
+	{-1, NULL}
+};
+
 
 /* ADS kerberos ticket verification options */
 
diff --git a/source3/profile/profile.c b/source3/profile/profile.c
index 5451242..9b976b6 100644
--- a/source3/profile/profile.c
+++ b/source3/profile/profile.c
@@ -684,6 +684,8 @@ struct profile_stats *smbprofile_setup_stats_area(const char *primary_key,
 {
 	struct smbprofile_stats_ref *s;
 
+	DEBUG(1,("pk: '%s', sk: '%s'\n", primary_key, secondary_key));
+
 	if (smbprofile_state.internal.db == NULL) {
 		return NULL;
 	}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 9076ef3..b747a82 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -530,6 +530,7 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
 	uid_t effuid;
 	gid_t effgid;
 	NTSTATUS status;
+	const char *key1, *key2;
 
 	fstrcpy(dev, pdev);
 
@@ -855,10 +856,18 @@ static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
 
 	conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
 
+	if (lp_smbd_profiling_stats() == SMBD_PROFILE_DETAILED) {
+		key1 = dom_sid_string(talloc_tos(), &conn->session_info->security_token->sids[0]);
+		key2 = lp_servicename(talloc_tos(), snum);
+	} else if (lp_smbd_profiling_stats() == SMBD_PROFILE_USERS) {
+		key1 = dom_sid_string(talloc_tos(), &conn->session_info->security_token->sids[0]);
+		key2 = "*SHARES*";
+	} else { /* SMBD_PROFILE_SHARES */
+		key1 = "*USERS*";
+		key2 = lp_servicename(talloc_tos(), snum);
+	}
 	conn->profile_area = smbprofile_setup_stats_area(
-			dom_sid_string(talloc_tos(), &conn->session_info->security_token->sids[0]),
-			lp_servicename(talloc_tos(), snum),
-			conn->session_info->unix_info->unix_name);
+		key1, key2, conn->session_info->unix_info->unix_name);
 
 	/*
 	 * Print out the 'connected as' stuff here as we need
-- 
2.5.0



More information about the samba-technical mailing list