[SCM] Samba Shared Repository - branch v4-7-test updated

Karolin Seeger kseeger at samba.org
Thu Jun 7 11:55:02 UTC 2018


The branch, v4-7-test has been updated
       via  d3c2cc2 smbd: Flush dfree memcache on service reload
       via  b310f37 smbd: Cache dfree information based on query path
       via  bf63e6f memcache: Add new cache type for dfree information
       via  5cbb3c3 selftest: Add test for 'dfree cache'
       via  9d9d959 selftest: Add dfq_cache share with 'dfree cache time' set
      from  f156d20 lib/util: Call log_stack_trace() in smb_panic_default()

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-7-test


- Log -----------------------------------------------------------------
commit d3c2cc28545b052754a2b77a5df0a7dc86e90766
Author: Christof Schmitt <cs at samba.org>
Date:   Fri May 18 20:51:58 2018 -0700

    smbd: Flush dfree memcache on service reload
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13446
    
    Signed-off-by: Christof Schmitt <cs at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit e30d0c0e0d11f65b2d1886be3c0fe9e32eaf3926)
    
    Autobuild-User(v4-7-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-7-test): Thu Jun  7 13:54:43 CEST 2018 on sn-devel-144

commit b310f375726afedbc33f9f9033f7f79772898dc9
Author: Christof Schmitt <cs at samba.org>
Date:   Wed May 16 13:17:52 2018 -0700

    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>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 8f121747b06ca78cf51801a3931b2ddd1a424c77)

commit bf63e6f23721487e1e582154b14ba7b069670d93
Author: Christof Schmitt <cs at samba.org>
Date:   Wed May 16 13:05:36 2018 -0700

    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>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit f5d05562679f6aa691b98b4a75952f7dda7ed343)

commit 5cbb3c35561b52369335020df7dc4d69bc49fc35
Author: Christof Schmitt <cs at samba.org>
Date:   Wed May 23 11:25:42 2018 -0700

    selftest: Add test for 'dfree cache'
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13446
    
    Signed-off-by: Christof Schmitt <cs at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit a55b3d2fcc2f7737a2702bf908dcf1f80969bf21)

commit 9d9d95965b425075d2c602cacc896ebd781b6ff8
Author: Christof Schmitt <cs at samba.org>
Date:   Wed May 23 11:07:54 2018 -0700

    selftest: Add dfq_cache share with 'dfree cache time' set
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13446
    
    Signed-off-by: Christof Schmitt <cs at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 7ffcbd5ce1222971cb9879f78765d87cdc4102a8)

-----------------------------------------------------------------------

Summary of changes:
 lib/util/memcache.h                      |   3 +-
 selftest/target/Samba3.pm                |   6 ++
 source3/script/tests/test_dfree_quota.sh |  35 +++++++++++
 source3/smbd/dfree.c                     | 104 +++++++++++++++++++++++++------
 source3/smbd/proto.h                     |   1 +
 source3/smbd/server_reload.c             |   1 +
 6 files changed, 130 insertions(+), 20 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/util/memcache.h b/lib/util/memcache.h
index b87746b..c6a5b86 100644
--- a/lib/util/memcache.h
+++ b/lib/util/memcache.h
@@ -44,7 +44,8 @@ enum memcache_number {
 	SINGLETON_CACHE_TALLOC,	/* talloc */
 	SINGLETON_CACHE,
 	SMB1_SEARCH_OFFSET_MAP,
-	SHARE_MODE_LOCK_CACHE	/* talloc */
+	SHARE_MODE_LOCK_CACHE,	/* talloc */
+	DFREE_CACHE,
 };
 
 /*
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 299d55b..39a8f49 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -2007,6 +2007,12 @@ sub provision($$$$$$$$$)
 	vfs objects = acl_xattr fake_acls xattr_tdb fake_dfq
 	admin users = $unix_name
 	include = $dfqconffile
+[dfq_cache]
+	path = $shrdir/dfree
+	vfs objects = acl_xattr fake_acls xattr_tdb fake_dfq
+	admin users = $unix_name
+	include = $dfqconffile
+	dfree cache time = 60
 [dfq_owner]
 	path = $shrdir/dfree
 	vfs objects = acl_xattr fake_acls xattr_tdb fake_dfq
diff --git a/source3/script/tests/test_dfree_quota.sh b/source3/script/tests/test_dfree_quota.sh
index 6e227c4..abd82b4 100755
--- a/source3/script/tests/test_dfree_quota.sh
+++ b/source3/script/tests/test_dfree_quota.sh
@@ -130,6 +130,35 @@ test_smbclient_dfree() {
 	return $status
 }
 
+# Issue two queries to different directories in one session to test
+# caching effects
+test_smbclient_dfree_2() {
+	name="$1"
+	share="$2"
+	dir1="$3"
+	dir2="$4"
+	confs="$5"
+	expected="$6"
+	subunit_start_test "$name"
+	setup_conf $confs
+	output=$($VALGRIND $smbclient //$SERVER/$share \
+			   -c "cd $dir1; du; cd ..; cd $dir2 ; du" $@ 2>&1)
+	status=$?
+	if [ "$status" = "0" ]; then
+		received=$(echo "$output" | \
+				   awk '/blocks of size/ {print $1, $5, $6}' | \
+				   tr '\n' ' ')
+		if [ "$expected" = "$received" ]; then
+			subunit_pass_test "$name"
+		else
+			echo "$output" | subunit_fail_test "$name"
+		fi
+	else
+		echo "$output" | subunit_fail_test "$name"
+	fi
+	return $status
+}
+
 test_smbcquotas() {
 	name="$1"
     conf="$2"
@@ -164,6 +193,12 @@ test_smbclient_dfree "Test large disk" dfq "." "conf3 ." "1125899906842624 1024.
 #basic quota test (SMB1 only)
 test_smbcquotas "Test user quota" confq1 $USERNAME "40960/4096000/3072000" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=NT1 || failed=`expr $failed + 1`
 
+# Test dfree cache through queries in two different directories
+test_smbclient_dfree_2 "Test dfree cache" dfq_cache "." "subdir1" \
+		       "conf1 . conf2 subdir1" "10 1024. 5 20 1024. 10 " \
+		       -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 \
+	|| failed=`expr $failed + 1`
+
 #quota limit > disk size, remaining quota > disk free
 test_smbclient_dfree "Test dfree share root df vs quota case 1" dfq "." "confdfq1 ." "80 1024. 40" -U$USERNAME%$PASSWORD --option=clientmaxprotocol=SMB3 || failed=`expr $failed + 1`
 #quota limit > disk size, remaining quota < disk free
diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c
index a702d08..d280e1e 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,48 +168,113 @@ 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;
+	struct dfree_cached_info dfc_new = { 0 };
 	uint64_t dfree_ret;
+	char tmpbuf[PATH_MAX];
+	char *full_path = NULL;
+	char *to_free = NULL;
+	char *key_path = NULL;
+	size_t len;
+	DATA_BLOB key, value;
+	bool found;
 
 	if (!dfree_cache_time) {
 		return sys_disk_free(conn, fname, bsize, dfree, dsize);
 	}
 
+	len = full_path_tos(conn->connectpath,
+			    fname->base_name,
+			    tmpbuf,
+			    sizeof(tmpbuf),
+			    &full_path,
+			    &to_free);
+	if (len == -1) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	if (VALID_STAT(fname->st) && S_ISREG(fname->st.st_ex_mode)) {
+		/*
+		 * In case of a file use the parent directory to reduce number
+		 * of cache entries.
+		 */
+		bool ok;
+
+		ok = parent_dirname(talloc_tos(),
+				    full_path,
+				    &key_path,
+				    NULL);
+		TALLOC_FREE(to_free); /* We're done with full_path */
+
+		if (!ok) {
+			errno = ENOMEM;
+			return -1;
+		}
+
+		/*
+		 * key_path is always a talloced object.
+		 */
+		to_free = key_path;
+	} else {
+		/*
+		 * key_path might not be a talloced object; rely on
+		 * to_free set from full_path_tos.
+		 */
+		key_path = full_path;
+	}
+
+	key = data_blob_const(key_path, strlen(key_path));
+	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 dfree cache entry for %s\n", key_path);
 		*bsize = dfc->bsize;
 		*dfree = dfc->dfree;
 		*dsize = dfc->dsize;
-		return dfc->dfree_ret;
+		dfree_ret = dfc->dfree_ret;
+		goto out;
 	}
 
 	dfree_ret = sys_disk_free(conn, fname, bsize, dfree, dsize);
 
 	if (dfree_ret == (uint64_t)-1) {
 		/* Don't cache bad data. */
-		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;
+		goto out;
 	}
 
-	dfc->bsize = *bsize;
-	dfc->dfree = *dfree;
-	dfc->dsize = *dsize;
-	dfc->dfree_ret = dfree_ret;
-	dfc->last_dfree_time = conn->lastused;
-
+	DBG_DEBUG("Creating dfree cache entry for %s\n", key_path);
+	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;
+	memcache_add(smbd_memcache(),
+		     DFREE_CACHE,
+		     key,
+		     data_blob_const(&dfc_new, sizeof(dfc_new)));
+
+out:
+	TALLOC_FREE(to_free);
 	return dfree_ret;
 }
+
+void flush_dfree_cache(void)
+{
+	memcache_flush(smbd_memcache(), DFREE_CACHE);
+}
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index a688341..d814a30 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -176,6 +176,7 @@ uint64_t sys_disk_free(connection_struct *conn, struct smb_filename *fname,
 		       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);
+void flush_dfree_cache(void);
 
 /* The following definitions come from smbd/dir.c  */
 
diff --git a/source3/smbd/server_reload.c b/source3/smbd/server_reload.c
index c93c077..9b62096 100644
--- a/source3/smbd/server_reload.c
+++ b/source3/smbd/server_reload.c
@@ -164,6 +164,7 @@ bool reload_services(struct smbd_server_connection *sconn,
 
 	mangle_reset_cache();
 	reset_stat_cache();
+	flush_dfree_cache();
 
 	/* this forces service parameters to be flushed */
 	set_current_service(NULL,0,True);


-- 
Samba Shared Repository



More information about the samba-cvs mailing list