[PATCHES BUG 13446] smbd: Cache dfree information based on query path

Christof Schmitt cs at samba.org
Fri May 18 23:45:18 UTC 2018


From dfb466ef2d647c5436d32379e0f36f6779255a44 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Wed, 16 May 2018 13:05:36 -0700
Subject: [PATCH 1/3] memcache: Add new cache type for dfree information

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13446

Signed-off-by: Christof Schmitt <cs at samba.org>
---
 lib/util/memcache.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/util/memcache.h b/lib/util/memcache.h
index 670cbd6..4331c2f 100644
--- a/lib/util/memcache.h
+++ b/lib/util/memcache.h
@@ -45,7 +45,8 @@ enum memcache_number {
 	SINGLETON_CACHE,
 	SMB1_SEARCH_OFFSET_MAP,
 	SHARE_MODE_LOCK_CACHE,	/* talloc */
-	VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC /* talloc */
+	VIRUSFILTER_SCAN_RESULTS_CACHE_TALLOC, /* talloc */
+	DFREE_CACHE,
 };
 
 /*
-- 
1.8.3.1


From 9ff637d587f6e30376ce93236163a0dfe2ba710f Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Wed, 16 May 2018 13:17:52 -0700
Subject: [PATCH 2/3] smbd: Cache dfree information based on query path

Sub directories in a SMB share can have different free space information
(e.g. when a different file system is mounted there). Caching the dfree
information per SMB share will return invalid data. Address this by
switching to memcache and store the cached data based on the query path.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13446

Signed-off-by: Christof Schmitt <cs at samba.org>
---
 source3/smbd/dfree.c | 39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
index a702d08..841d537 100644
--- a/source3/smbd/dfree.c
+++ b/source3/smbd/dfree.c
@@ -21,6 +21,7 @@
 #include "smbd/smbd.h"
 #include "smbd/globals.h"
 #include "lib/util_file.h"
+#include "lib/util/memcache.h"
 
 /****************************************************************************
  Normalise for DOS usage.
@@ -167,21 +168,33 @@ dfree_done:
 
 /****************************************************************************
  Potentially returned cached dfree info.
+
+ Depending on the file system layout and file system features, the free space
+ information can be different for different sub directories underneath a SMB
+ share. Store the cache information in memcache using the query path as the
+ key to accomodate this.
 ****************************************************************************/
 
 uint64_t get_dfree_info(connection_struct *conn, struct smb_filename *fname,
 			uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
 {
 	int dfree_cache_time = lp_dfree_cache_time(SNUM(conn));
-	struct dfree_cached_info *dfc = conn->dfree_info;
+	struct dfree_cached_info *dfc = NULL, dfc_new;
 	uint64_t dfree_ret;
+	DATA_BLOB key, value;
+	bool found;
 
 	if (!dfree_cache_time) {
 		return sys_disk_free(conn, fname, bsize, dfree, dsize);
 	}
 
+	key = data_blob_const(fname->base_name, strlen(fname->base_name));
+	found = memcache_lookup(smbd_memcache(), DFREE_CACHE, key, &value);
+	dfc = found ? (struct dfree_cached_info *)value.data : NULL;
+
 	if (dfc && (conn->lastused - dfc->last_dfree_time < dfree_cache_time)) {
-		/* Return cached info. */
+		DBG_DEBUG("Returning cached dfree info for %s\n",
+			  fname->base_name);
 		*bsize = dfc->bsize;
 		*dfree = dfc->dfree;
 		*dsize = dfc->dsize;
@@ -195,20 +208,14 @@ uint64_t get_dfree_info(connection_struct *conn, struct smb_filename *fname,
 		return dfree_ret;
 	}
 
-	/* No cached info or time to refresh. */
-	if (!dfc) {
-		dfc = talloc(conn, struct dfree_cached_info);
-		if (!dfc) {
-			return dfree_ret;
-		}
-		conn->dfree_info = dfc;
-	}
-
-	dfc->bsize = *bsize;
-	dfc->dfree = *dfree;
-	dfc->dsize = *dsize;
-	dfc->dfree_ret = dfree_ret;
-	dfc->last_dfree_time = conn->lastused;
+	dfc_new.bsize = *bsize;
+	dfc_new.dfree = *dfree;
+	dfc_new.dsize = *dsize;
+	dfc_new.dfree_ret = dfree_ret;
+	dfc_new.last_dfree_time = conn->lastused;
+	DBG_DEBUG("Creating cached dfree entry for %s\n", fname->base_name);
+	memcache_add(smbd_memcache(), DFREE_CACHE,
+		     key, data_blob_const(&dfc_new, sizeof(dfc_new)));
 
 	return dfree_ret;
 }
-- 
1.8.3.1


From 066de08f5ae5cbd5cb68c3b595867fde8ee0ea73 Mon Sep 17 00:00:00 2001
From: Christof Schmitt <cs at samba.org>
Date: Wed, 16 May 2018 13:25:54 -0700
Subject: [PATCH 3/3] smbd: Move dfree_info struct

As the struct is no longer used as part of connection_struct, move it to
dfree.c

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13446

Signed-off-by: Christof Schmitt <cs at samba.org>
---
 source3/include/vfs.h | 9 ---------
 source3/smbd/dfree.c  | 8 ++++++++
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index cc7948a..cdf6fb3 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -409,14 +409,6 @@ typedef struct {
 	bool is_wild;
 } name_compare_entry;
 
-struct dfree_cached_info {
-	time_t last_dfree_time;
-	uint64_t dfree_ret;
-	uint64_t bsize;
-	uint64_t dfree;
-	uint64_t dsize;
-};
-
 struct share_params {
 	int service;
 };
@@ -479,7 +471,6 @@ typedef struct connection_struct {
 	name_compare_entry *veto_list; /* Per-share list of files to veto (never show). */
 	name_compare_entry *veto_oplock_list; /* Per-share list of files to refuse oplocks on. */       
 	name_compare_entry *aio_write_behind_list; /* Per-share list of files to use aio write behind on. */       
-	struct dfree_cached_info *dfree_info;
 	struct trans_state *pending_trans;
 
 	struct rpc_pipe_client *spoolss_pipe;
diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
index 841d537..8863e58 100644
--- a/source3/smbd/dfree.c
+++ b/source3/smbd/dfree.c
@@ -175,6 +175,14 @@ dfree_done:
  key to accomodate this.
 ****************************************************************************/
 
+struct dfree_cached_info {
+	time_t last_dfree_time;
+	uint64_t dfree_ret;
+	uint64_t bsize;
+	uint64_t dfree;
+	uint64_t dsize;
+};
+
 uint64_t get_dfree_info(connection_struct *conn, struct smb_filename *fname,
 			uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
 {
-- 
1.8.3.1



More information about the samba-technical mailing list