[PATCH] DFS referral shuffling

Robin McCorkell rmccorkell at karoshi.org.uk
Sun Feb 15 10:34:03 MST 2015


Hi,

I've implemented DFS referral shuffling to enable a primitive sort of
load balancing for a DFS path. Yes, the MS docs say the client should
decide which to pick, but from my testing smbclient and mount.cifs only
ever choose the first one. The behaviour is controlled by a config
paramater, `msdfs shuffle referrals`, which should be set in the DFS
root share and defaults to off. The actual shuffling code is very
similar to the DFS DC shuffling code in vfs_dfs_samba4, which does the
same thing but for DCs rather than DFS referrals.

Like the previous email, ignore the [PATCH] 1/2 in the patch header,
this is the only patch.

Regards,
Robin McCorkell
The Linux Schools Project
-------------- next part --------------
From aea01b7562a73e53d739e1c8bb17fd7c105ec520 Mon Sep 17 00:00:00 2001
From: Robin McCorkell <rmccorkell at karoshi.org.uk>
Date: Thu, 5 Feb 2015 14:06:15 +0000
Subject: [PATCH 1/2] MSDFS referral shuffling

---
 docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml | 16 ++++++++++++++
 lib/param/param_table.c                           |  9 ++++++++
 source3/param/loadparm.c                          |  1 +
 source3/smbd/msdfs.c                              | 27 ++++++++++++++++++++---
 4 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100644 docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml

diff --git a/docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml b/docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml
new file mode 100644
index 0000000..771982f
--- /dev/null
+++ b/docs-xml/smbdotconf/vfs/msdfsshufflereferrals.xml
@@ -0,0 +1,16 @@
+<samba:parameter name="msdfs shuffle referrals"
+                 context="S"
+				 type="boolean"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+	<para>If set to <constant>yes</constant>, Samba will shuffle
+	Dfs referrals for a given Dfs link if multiple are available,
+	allowing for load balancing across clients. For more information
+	on setting up a Dfs tree on	Samba, refer to the MSDFS chapter in
+	the Samba3-HOWTO book.</para>
+</description>
+
+<related>host msdfs</related>
+<related>msdfs root</related>
+<value type="default">no</value>
+</samba:parameter>
diff --git a/lib/param/param_table.c b/lib/param/param_table.c
index 18b0628..00274ca 100644
--- a/lib/param/param_table.c
+++ b/lib/param/param_table.c
@@ -3942,6 +3942,15 @@ struct parm_struct parm_table[] = {
 		.flags		= FLAG_ADVANCED | FLAG_SHARE,
 	},
 	{
+		.label		= "msdfs shuffle referrals",
+		.type		= P_BOOL,
+		.p_class	= P_LOCAL,
+		.offset		= LOCAL_VAR(msdfs_shuffle_referrals),
+		.special	= NULL,
+		.enum_list	= NULL,
+		.flags		= FLAG_ADVANCED | FLAG_SHARE,
+	},
+	{
 		.label		= "host msdfs",
 		.type		= P_BOOL,
 		.p_class	= P_GLOBAL,
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index da50e3a..4a74843 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -222,6 +222,7 @@ static struct loadparm_service sDefault =
 	.inherit_acls = false,
 	.inherit_owner = false,
 	.msdfs_root = false,
+	.msdfs_shuffle_referrals = false,
 	.use_client_driver = false,
 	.default_devmode = true,
 	.force_printername = false,
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 3bd8a09..94724d7 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -428,6 +428,21 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
 	return NT_STATUS_OK;
 }
 
+static void shuffle_referrals(const char **list, int count) {
+	int i, r;
+	const char *tmp;
+
+	srandom(time(NULL));
+
+	for (i = count; i > 1; i--) {
+		r = random() % i;
+
+		tmp = list[i-1];
+		list[i-1] = list[r];
+		list[r] = tmp;
+	}
+}
+
 /**********************************************************************
  Parse the contents of a symlink to verify if it is an msdfs referral
  A valid referral is of the form:
@@ -448,6 +463,7 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
  **********************************************************************/
 
 static bool parse_msdfs_symlink(TALLOC_CTX *ctx,
+				int snum,
 				const char *target,
 				struct referral **preflist,
 				int *refcount)
@@ -480,6 +496,11 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx,
 		count++;
 	}
 
+	/* shuffle alternate paths */
+	if (lp_msdfs_shuffle_referrals(snum)) {
+		shuffle_referrals(alt_path, count);
+	}
+
 	DEBUG(10,("parse_msdfs_symlink: count=%d\n", count));
 
 	if (count) {
@@ -1007,7 +1028,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
 			return NT_STATUS_NO_MEMORY;
 		}
 
-		if (!parse_msdfs_symlink(ctx, tmp, &ref, &refcount)) {
+		if (!parse_msdfs_symlink(ctx, snum, tmp, &ref, &refcount)) {
 			TALLOC_FREE(tmp);
 			TALLOC_FREE(pdp);
 			return NT_STATUS_INVALID_PARAMETER;
@@ -1056,7 +1077,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
 	}
 
 	/* We know this is a valid dfs link. Parse the targetpath. */
-	if (!parse_msdfs_symlink(ctx, targetpath,
+	if (!parse_msdfs_symlink(ctx, snum, targetpath,
 				&jucn->referral_list,
 				&jucn->referral_count)) {
 		DEBUG(3,("get_referred_path: failed to parse symlink "
@@ -1517,7 +1538,7 @@ static int form_junctions(TALLOC_CTX *ctx,
 					conn,
 					dname, &link_target,
 					NULL)) {
-			if (parse_msdfs_symlink(ctx,
+			if (parse_msdfs_symlink(ctx, snum,
 					link_target,
 					&jucn[cnt].referral_list,
 					&jucn[cnt].referral_count)) {
-- 
1.9.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20150215/0b9d3120/attachment.pgp>


More information about the samba-technical mailing list