[PATCH] Bunch of options for vfs_fileid

Ralph Böhme slow at samba.org
Fri Jan 5 09:44:27 UTC 2018


Hi!

Attached is a patchset with a bunch of new options for vfs_fileid. They have
been in use downstream by a vendor for quite some time and I would like to bring
them upstream.

The following options are added:

  fileid:fstype deny = LIST
  fileid:fstype allow = LIST
  fileid:mntdir deny = LIST
  fileid:mntdir allow = LIST

  fileid:algorithm = hostname
  fileid:algorithm = fsname_nodirs
  fileid:nolockinode
  fileid:algorithm = fsname_norootdir

The patch that adds the fstype/mntdir options has been discussed previously
about two years ago:
https://lists.samba.org/archive/samba-technical/2016-January/111553.html

Afaict consensus was that it's a useful addition and concerns raised by Jeremey
where addressed by better explanation of the use case. The patch then never went
upstream though.

All parameters are explained in manpage updates.

The use case of the new algorithms is to mitigate contention on locking.tdb
records in a cluster.

"fileid:algorithm = fsname_norootdir" is probably the most useful one as it
mitigates contention on the locking.tdb record on the root directory of shares
which was seen frequently with certain workloads.

I'm wrapping all patches in one patchset, as the patches build on top of one
another, eg the algorithm added for "fileid:algorithm = hostname" is used by the
the other new algorithm.

Please review&push if happy. Thanks!

-slow

-- 
Ralph Boehme, Samba Team       https://samba.org/
Samba Developer, SerNet GmbH   https://sernet.de/en/samba/
-------------- next part --------------
From e5e0bd3f08fb27853b689b7ce1bab37af2c9d4fb Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 4 Jan 2018 17:25:07 +0100
Subject: [PATCH 1/8] vfs_fileid: add a DEBUG message to log dev and inode

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

diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index a7c4a49d553..9a8f3f99193 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -249,6 +249,9 @@ static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle,
 	id.devid	= data->device_mapping_fn(data, sbuf->st_ex_dev);
 	id.inode	= sbuf->st_ex_ino;
 
+	DBG_DEBUG("Returning dev [%jx] inode [%jx]\n",
+		  (uintmax_t)id.devid, (uintmax_t)id.inode);
+
 	return id;
 }
 
-- 
2.13.6


From 0253a6a5bfd826da2083f64d3d117357d93f82d3 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 5 Jan 2018 10:23:30 +0100
Subject: [PATCH 2/8] vfs_fileid: preserve errno in an error code path

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

diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index 9a8f3f99193..fedcac7e6d5 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -183,6 +183,7 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 {
 	struct fileid_handle_data *data;
 	const char *algorithm;
+	int saved_errno;
 	int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
 
 	if (ret < 0) {
@@ -191,8 +192,10 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 
 	data = talloc_zero(handle->conn, struct fileid_handle_data);
 	if (!data) {
+		saved_errno = errno;
 		SMB_VFS_NEXT_DISCONNECT(handle);
 		DEBUG(0, ("talloc_zero() failed\n"));
+		errno = saved_errno;
 		return -1;
 	}
 
-- 
2.13.6


From 3ea7e228f1255bb2d4a59f458b42c81792409f38 Mon Sep 17 00:00:00 2001
From: Ralph Wuerthner <ralph.wuerthner at de.ibm.com>
Date: Tue, 12 Jan 2016 16:00:24 +0100
Subject: [PATCH 3/8] vfs_fileid: add "fstype/mntdir deny/allow list" option

When using the fsname or fsid algorithm a stat() and statfs() call is
required for all mounted file systems to generate the file_id. If e.g.
an NFS file system is unresponsive such a call might block and the smbd
process will become unresponsive. Add "fileid:fstype deny",
"fileid:fstype allow", "fileid:mntdir deny", and "fileid:mntdir allow"
options to ignore potentially unresponsive file systems.

See also https://lists.samba.org/archive/samba-technical/2016-January/111553.html
for a discussion about why this is useful.

Signed-off-by: Ralph Wuerthner <ralph.wuerthner at de.ibm.com>
Reviewed-by: Ralph Boehme <slow at samba.org>
---
 docs-xml/manpages/vfs_fileid.8.xml |  47 +++++++++++++++
 source3/modules/vfs_fileid.c       | 114 +++++++++++++++++++++++++++++++++++++
 2 files changed, 161 insertions(+)

diff --git a/docs-xml/manpages/vfs_fileid.8.xml b/docs-xml/manpages/vfs_fileid.8.xml
index 5a3a70e9b95..568756ba519 100644
--- a/docs-xml/manpages/vfs_fileid.8.xml
+++ b/docs-xml/manpages/vfs_fileid.8.xml
@@ -40,6 +40,15 @@
 	generates the device number based on the configured algorithm
 	(see the "fileid:algorithm" option).
 	</para>
+
+	<para>When using the fsname or fsid algorithm a
+	<command>stat()</command> and <command>statfs()</command> call is
+	required for all mounted file systems to generate the file_id. If e.g.
+	an NFS file system is unresponsive such a call might block and the smbd
+	process will become unresponsive. Use the "fileid:fstype deny",
+	"fileid:fstype allow", "fileid:mntdir deny", or "fileid:mntdir allow"
+	options to ignore potentially unresponsive file systems.
+	</para>
 </refsect1>
 
 
@@ -75,6 +84,44 @@
 		</listitem>
 		</varlistentry>
 
+		<varlistentry>
+		<term>fileid:fstype deny = LIST</term>
+		<listitem>
+		<para>List of file system types to be ignored for file_id
+		generation.
+		</para>
+		</listitem>
+		</varlistentry>
+
+		<varlistentry>
+		<term>fileid:fstype allow = LIST</term>
+		<listitem>
+		<para>List of file system types to be allowed for file_id
+		generation. If this option is set, file system types not listed
+		here are ignored.
+		</para>
+		</listitem>
+		</varlistentry>
+
+		<varlistentry>
+		<term>fileid:mntdir deny = LIST</term>
+		<listitem>
+		<para>List of file system mount points to be ignored for
+		file_id	generation.
+		</para>
+		</listitem>
+		</varlistentry>
+
+		<varlistentry>
+		<term>fileid:mntdir allow = LIST</term>
+		<listitem>
+		<para>List of file system mount points to be allowed for file_id
+		generation. If this option is set, file system mount points
+		not listed here are ignored.
+		</para>
+		</listitem>
+		</varlistentry>
+
 	</variablelist>
 </refsect1>
 
diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index fedcac7e6d5..583665775b2 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -38,10 +38,62 @@ struct fileid_mount_entry {
 struct fileid_handle_data {
 	uint64_t (*device_mapping_fn)(struct fileid_handle_data *data,
 				      SMB_DEV_T dev);
+	char **fstype_deny_list;
+	char **fstype_allow_list;
+	char **mntdir_deny_list;
+	char **mntdir_allow_list;
 	unsigned num_mount_entries;
 	struct fileid_mount_entry *mount_entries;
 };
 
+/* check if a mount entry is allowed based on fstype and mount directory */
+static bool fileid_mount_entry_allowed(struct fileid_handle_data *data,
+				       struct mntent *m)
+{
+	int i;
+	char **fstype_deny = data->fstype_deny_list;
+	char **fstype_allow = data->fstype_allow_list;
+	char **mntdir_deny = data->mntdir_deny_list;
+	char **mntdir_allow = data->mntdir_allow_list;
+
+	if (fstype_deny != NULL) {
+		for (i = 0; fstype_deny[i] != NULL; i++) {
+			if (strcmp(m->mnt_type, fstype_deny[i]) == 0) {
+				return false;
+			}
+		}
+	}
+	if (fstype_allow != NULL) {
+		for (i = 0; fstype_allow[i] != NULL; i++) {
+			if (strcmp(m->mnt_type, fstype_allow[i]) == 0) {
+				break;
+			}
+		}
+		if (fstype_allow[i] == NULL) {
+			return false;
+		}
+	}
+	if (mntdir_deny != NULL) {
+		for (i=0; mntdir_deny[i] != NULL; i++) {
+			if (strcmp(m->mnt_dir, mntdir_deny[i]) == 0) {
+				return false;
+			}
+		}
+	}
+	if (mntdir_allow != NULL) {
+		for (i=0; mntdir_allow[i] != NULL; i++) {
+			if (strcmp(m->mnt_dir, mntdir_allow[i]) == 0) {
+				break;
+			}
+		}
+		if (mntdir_allow[i] == NULL) {
+			return false;
+		}
+	}
+	return true;
+}
+
+
 /* load all the mount entries from the mtab */
 static void fileid_load_mount_entries(struct fileid_handle_data *data)
 {
@@ -58,7 +110,13 @@ static void fileid_load_mount_entries(struct fileid_handle_data *data)
 		struct stat st;
 		struct statfs sfs;
 		struct fileid_mount_entry *cur;
+		bool allowed;
 
+		allowed = fileid_mount_entry_allowed(data, m);
+		if (!allowed) {
+			DBG_DEBUG("skipping mount entry %s\n", m->mnt_dir);
+			continue;
+		}
 		if (stat(m->mnt_dir, &st) != 0) continue;
 		if (statfs(m->mnt_dir, &sfs) != 0) continue;
 
@@ -183,6 +241,10 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 {
 	struct fileid_handle_data *data;
 	const char *algorithm;
+	const char **fstype_deny_list = NULL;
+	const char **fstype_allow_list = NULL;
+	const char **mntdir_deny_list = NULL;
+	const char **mntdir_allow_list = NULL;
 	int saved_errno;
 	int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
 
@@ -219,6 +281,58 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 		return -1;
 	}
 
+	fstype_deny_list = lp_parm_string_list(SNUM(handle->conn), "fileid",
+					       "fstype deny", NULL);
+	if (fstype_deny_list != NULL) {
+		data->fstype_deny_list = str_list_copy(data, fstype_deny_list);
+		if (data->fstype_deny_list == NULL) {
+			saved_errno = errno;
+			DBG_ERR("str_list_copy failed\n");
+			SMB_VFS_NEXT_DISCONNECT(handle);
+			errno = saved_errno;
+			return -1;
+		}
+	}
+
+	fstype_allow_list = lp_parm_string_list(SNUM(handle->conn), "fileid",
+						"fstype allow", NULL);
+	if (fstype_allow_list != NULL) {
+		data->fstype_allow_list = str_list_copy(data, fstype_allow_list);
+		if (data->fstype_allow_list == NULL) {
+			saved_errno = errno;
+			DBG_ERR("str_list_copy failed\n");
+			SMB_VFS_NEXT_DISCONNECT(handle);
+			errno = saved_errno;
+			return -1;
+		}
+	}
+
+	mntdir_deny_list = lp_parm_string_list(SNUM(handle->conn), "fileid",
+					       "mntdir deny", NULL);
+	if (mntdir_deny_list != NULL) {
+		data->mntdir_deny_list = str_list_copy(data, mntdir_deny_list);
+		if (data->mntdir_deny_list == NULL) {
+			saved_errno = errno;
+			DBG_ERR("str_list_copy failed\n");
+			SMB_VFS_NEXT_DISCONNECT(handle);
+			errno = saved_errno;
+			return -1;
+		}
+	}
+
+	mntdir_allow_list = lp_parm_string_list(SNUM(handle->conn), "fileid",
+						"mntdir allow", NULL);
+	if (mntdir_allow_list != NULL) {
+		data->mntdir_allow_list = str_list_copy(data, mntdir_allow_list);
+		if (data->mntdir_allow_list == NULL) {
+			saved_errno = errno;
+			DBG_ERR("str_list_copy failed\n");
+			SMB_VFS_NEXT_DISCONNECT(handle);
+			errno = saved_errno;
+			return -1;
+		}
+	}
+
 	SMB_VFS_HANDLE_SET_DATA(handle, data, NULL,
 				struct fileid_handle_data,
 				return -1);
-- 
2.13.6


From 6d11e8ceefda2f0d864694abdf48f556c5750b98 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 4 Jan 2018 16:35:38 +0100
Subject: [PATCH 4/8] vfs_fileid: convert dev argument of the device_mapping_fn
 to SMB_STRUCT_STAT

This is in preperation of adding an additional mapping function that
acts differently depending of the file type. No change in behaviour.

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_fileid.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index 583665775b2..d3aa4e4057d 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -37,7 +37,7 @@ struct fileid_mount_entry {
 
 struct fileid_handle_data {
 	uint64_t (*device_mapping_fn)(struct fileid_handle_data *data,
-				      SMB_DEV_T dev);
+				      const SMB_STRUCT_STAT *sbuf);
 	char **fstype_deny_list;
 	char **fstype_allow_list;
 	char **mntdir_deny_list;
@@ -194,12 +194,12 @@ static uint64_t fileid_uint64_hash(const uint8_t *s, size_t len)
 
 /* a device mapping using a fsname */
 static uint64_t fileid_device_mapping_fsname(struct fileid_handle_data *data,
-					     SMB_DEV_T dev)
+					     const SMB_STRUCT_STAT *sbuf)
 {
 	struct fileid_mount_entry *m;
 
-	m = fileid_find_mount_entry(data, dev);
-	if (!m) return dev;
+	m = fileid_find_mount_entry(data, sbuf->st_ex_dev);
+	if (!m) return sbuf->st_ex_dev;
 
 	if (m->devid == (uint64_t)-1) {
 		m->devid = fileid_uint64_hash((const uint8_t *)m->mnt_fsname,
@@ -211,12 +211,12 @@ static uint64_t fileid_device_mapping_fsname(struct fileid_handle_data *data,
 
 /* device mapping functions using a fsid */
 static uint64_t fileid_device_mapping_fsid(struct fileid_handle_data *data,
-					   SMB_DEV_T dev)
+					   const SMB_STRUCT_STAT *sbuf)
 {
 	struct fileid_mount_entry *m;
 
-	m = fileid_find_mount_entry(data, dev);
-	if (!m) return dev;
+	m = fileid_find_mount_entry(data, sbuf->st_ex_dev);
+	if (!m) return sbuf->st_ex_dev;
 
 	if (m->devid == (uint64_t)-1) {
 		if (sizeof(fsid_t) > sizeof(uint64_t)) {
@@ -363,7 +363,7 @@ static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle,
 				struct fileid_handle_data,
 				return id);
 
-	id.devid	= data->device_mapping_fn(data, sbuf->st_ex_dev);
+	id.devid	= data->device_mapping_fn(data, sbuf);
 	id.inode	= sbuf->st_ex_ino;
 
 	DBG_DEBUG("Returning dev [%jx] inode [%jx]\n",
-- 
2.13.6


From b993fa259c877f76c9289c8fb1b4fcc2752b240b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 4 Jan 2018 16:59:54 +0100
Subject: [PATCH 5/8] vfs_fileid: add fileid:algorithm = hostname

Using fileid:algorithm = hostname makes fileid generate
fileids based on the hostname. This breaks cluster lock coherence.

Based-on-a-patch-by: Christian Ambach <ambi at samba.org>

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 docs-xml/manpages/vfs_fileid.8.xml | 10 +++++++---
 source3/modules/vfs_fileid.c       | 31 +++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/docs-xml/manpages/vfs_fileid.8.xml b/docs-xml/manpages/vfs_fileid.8.xml
index 568756ba519..6a09f16cf79 100644
--- a/docs-xml/manpages/vfs_fileid.8.xml
+++ b/docs-xml/manpages/vfs_fileid.8.xml
@@ -60,9 +60,9 @@
 		<varlistentry>
 		<term>fileid:algorithm = ALGORITHM</term>
 		<listitem>
-		<para>Available algorithms are <command>fsname</command>
-		and <command>fsid</command>. The default value is
-		<command>fsname</command>.
+		<para>Available algorithms are <command>fsname</command>,
+		<command>fsid</command> and <command>hostname</command>. The
+		default value is <command>fsname</command>.
 		</para>
 		<para>The <command>fsname</command> algorithm generates
 		device id by hashing the kernel device name.
@@ -71,6 +71,10 @@
 		the device id from the <command>f_fsid</command> returned
 		from the <command>statfs()</command> syscall.
 		</para>
+		<para>The <command>hostname</command> algorithm generates device
+		id by hashing the hostname. This can be used to deliberately
+		break lock coherency in a cluster.
+		</para>
 		</listitem>
 		</varlistentry>
 
diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index d3aa4e4057d..76f08f31a9e 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -209,6 +209,35 @@ static uint64_t fileid_device_mapping_fsname(struct fileid_handle_data *data,
 	return m->devid;
 }
 
+/* a device mapping using a hostname */
+static uint64_t fileid_device_mapping_hostname(struct fileid_handle_data *data,
+					       const SMB_STRUCT_STAT *sbuf)
+{
+	char hostname[HOST_NAME_MAX+1];
+	char *devname = NULL;
+	uint64_t id;
+	size_t devname_len;
+	int rc;
+
+	rc = gethostname(hostname, HOST_NAME_MAX+1);
+	if (rc != 0) {
+		DBG_ERR("gethostname failed\n");
+		return UINT64_MAX;
+	}
+
+	devname = talloc_asprintf(talloc_tos(), "%s%lu",
+				  hostname, sbuf->st_ex_dev);
+	if (devname == NULL) {
+		DBG_ERR("talloc_asprintf failed\n");
+		return UINT64_MAX;
+	}
+	devname_len = talloc_array_length(devname) - 1;
+	TALLOC_FREE(devname);
+
+	id = fileid_uint64_hash((uint8_t *)devname, devname_len);
+	return id;
+}
+
 /* device mapping functions using a fsid */
 static uint64_t fileid_device_mapping_fsid(struct fileid_handle_data *data,
 					   const SMB_STRUCT_STAT *sbuf)
@@ -275,6 +304,8 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 		data->device_mapping_fn	= fileid_device_mapping_fsname;
 	} else if (strcmp("fsid", algorithm) == 0) {
 		data->device_mapping_fn	= fileid_device_mapping_fsid;
+	} else if (strcmp("hostname", algorithm) == 0) {
+		data->device_mapping_fn = fileid_device_mapping_hostname;
 	} else {
 		SMB_VFS_NEXT_DISCONNECT(handle);
 		DEBUG(0,("fileid_connect(): unknown algorithm[%s]\n", algorithm));
-- 
2.13.6


From 6064edc9e6c7a18b95ac22b93ccf8716bc97eea3 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 4 Jan 2018 17:02:53 +0100
Subject: [PATCH 6/8] vfs_fileid: add fileid:algorithm = fsname_nodirs

Enabling fileid:algorithm = fsname_nodirs uses the hostname algorithm
for directories and thus breaks cluster lock coherence for directories.

Based-on-a-patch-by: Christian Ambach <ambi at samba.org>

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 docs-xml/manpages/vfs_fileid.8.xml | 10 ++++++++--
 source3/modules/vfs_fileid.c       | 14 ++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/docs-xml/manpages/vfs_fileid.8.xml b/docs-xml/manpages/vfs_fileid.8.xml
index 6a09f16cf79..9e8becb6b0c 100644
--- a/docs-xml/manpages/vfs_fileid.8.xml
+++ b/docs-xml/manpages/vfs_fileid.8.xml
@@ -61,12 +61,18 @@
 		<term>fileid:algorithm = ALGORITHM</term>
 		<listitem>
 		<para>Available algorithms are <command>fsname</command>,
-		<command>fsid</command> and <command>hostname</command>. The
-		default value is <command>fsname</command>.
+		<command>fsname_nodirs</command>, <command>fsid</command> and
+		<command>hostname</command>. The default value is
+		<command>fsname</command>.
 		</para>
 		<para>The <command>fsname</command> algorithm generates
 		device id by hashing the kernel device name.
 		</para>
+		<para>The <command>fsname_nodirs</command> algorithm generates
+		device id by hashing the kernel device name for files and by hashing
+		the hostname for directories. This can be used to deliberately
+		break lock coherency for directories in a cluster.
+		</para>
 		<para>The <command>fsid</command> algorithm generates
 		the device id from the <command>f_fsid</command> returned
 		from the <command>statfs()</command> syscall.
diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index 76f08f31a9e..4752bc55286 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -238,6 +238,18 @@ static uint64_t fileid_device_mapping_hostname(struct fileid_handle_data *data,
 	return id;
 }
 
+/* a device mapping using a fsname for files and hostname for dirs */
+static uint64_t fileid_device_mapping_fsname_nodirs(
+	struct fileid_handle_data *data,
+	const SMB_STRUCT_STAT *sbuf)
+{
+	if (S_ISDIR(sbuf->st_ex_mode)) {
+		return fileid_device_mapping_hostname(data, sbuf);
+	}
+
+	return fileid_device_mapping_fsname(data, sbuf);
+}
+
 /* device mapping functions using a fsid */
 static uint64_t fileid_device_mapping_fsid(struct fileid_handle_data *data,
 					   const SMB_STRUCT_STAT *sbuf)
@@ -302,6 +314,8 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 					 algorithm);
 	if (strcmp("fsname", algorithm) == 0) {
 		data->device_mapping_fn	= fileid_device_mapping_fsname;
+	} else if (strcmp("fsname_nodirs", algorithm) == 0) {
+		data->device_mapping_fn = fileid_device_mapping_fsname_nodirs;
 	} else if (strcmp("fsid", algorithm) == 0) {
 		data->device_mapping_fn	= fileid_device_mapping_fsid;
 	} else if (strcmp("hostname", algorithm) == 0) {
-- 
2.13.6


From 785f19a3d07d31ce43a987057d142e940f294a9b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 4 Jan 2018 17:09:21 +0100
Subject: [PATCH 7/8] vfs_fileid: add fileid:nolockinode parameter

Based-on-a-patch-by: Ralph Wuerthner <ralph.wuerthner at de.ibm.com>

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 docs-xml/manpages/vfs_fileid.8.xml | 10 ++++++++++
 source3/modules/vfs_fileid.c       | 13 ++++++++++++-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/docs-xml/manpages/vfs_fileid.8.xml b/docs-xml/manpages/vfs_fileid.8.xml
index 9e8becb6b0c..78f054aa0e5 100644
--- a/docs-xml/manpages/vfs_fileid.8.xml
+++ b/docs-xml/manpages/vfs_fileid.8.xml
@@ -132,6 +132,16 @@
 		</listitem>
 		</varlistentry>
 
+		<varlistentry>
+		<term>fileid:nolockinode</term>
+		<listitem>
+		<para>This option triggers use of the fileid hostname algorithm
+		for the configured inode which can be used to deliberately break
+		lock coherency for the corresponding file or directory in a
+		cluster.
+		</para>
+		</listitem>
+		</varlistentry>
 	</variablelist>
 </refsect1>
 
diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index 4752bc55286..bac8ff08731 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -44,6 +44,7 @@ struct fileid_handle_data {
 	char **mntdir_allow_list;
 	unsigned num_mount_entries;
 	struct fileid_mount_entry *mount_entries;
+	ino_t nolockinode;
 };
 
 /* check if a mount entry is allowed based on fstype and mount directory */
@@ -378,6 +379,9 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 		}
 	}
 
+	data->nolockinode = lp_parm_ulong(SNUM(handle->conn), "fileid",
+					  "nolockinode", 0);
+
 	SMB_VFS_HANDLE_SET_DATA(handle, data, NULL,
 				struct fileid_handle_data,
 				return -1);
@@ -401,6 +405,7 @@ static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle,
 {
 	struct fileid_handle_data *data;
 	struct file_id id;
+	uint64_t devid;
 
 	ZERO_STRUCT(id);
 
@@ -408,8 +413,14 @@ static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle,
 				struct fileid_handle_data,
 				return id);
 
-	id.devid	= data->device_mapping_fn(data, sbuf);
+	if ((data->nolockinode != 0) && (id.inode == data->nolockinode)) {
+		devid = fileid_device_mapping_hostname(data, sbuf);
+	} else {
+		devid = data->device_mapping_fn(data, sbuf);
+	}
+
 	id.inode	= sbuf->st_ex_ino;
+	id.devid        = devid;
 
 	DBG_DEBUG("Returning dev [%jx] inode [%jx]\n",
 		  (uintmax_t)id.devid, (uintmax_t)id.inode);
-- 
2.13.6


From ebbae2093bf49e9acaa9f6eed35df0e4ee2cb1b8 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 4 Jan 2018 17:22:16 +0100
Subject: [PATCH 8/8] vfs_fileid: add fileid:algorithm = fsname_norootdir

Based-on-a-patch-by: Ralph Wuerthner <ralph.wuerthner at de.ibm.com>

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 docs-xml/manpages/vfs_fileid.8.xml |  6 +++++
 source3/modules/vfs_fileid.c       | 45 +++++++++++++++++++++++++++++++++++---
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/docs-xml/manpages/vfs_fileid.8.xml b/docs-xml/manpages/vfs_fileid.8.xml
index 78f054aa0e5..edfdef20712 100644
--- a/docs-xml/manpages/vfs_fileid.8.xml
+++ b/docs-xml/manpages/vfs_fileid.8.xml
@@ -81,6 +81,12 @@
 		id by hashing the hostname. This can be used to deliberately
 		break lock coherency in a cluster.
 		</para>
+		<para>The <command>fsname_norootdir</command> algorithm
+		generates device ids by hashing the kernel device name, except
+		for the root directory of shares where it will use the hostname
+		algorithm. This can be used to deliberately break lock coherency
+		in a cluster for the root directory of a share.
+		</para>
 		</listitem>
 		</varlistentry>
 
diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index bac8ff08731..98cc32d62d5 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -278,6 +278,33 @@ static uint64_t fileid_device_mapping_fsid(struct fileid_handle_data *data,
 	return m->devid;
 }
 
+static int get_connectpath_ino(struct vfs_handle_struct *handle,
+			       ino_t *ino)
+{
+	struct smb_filename *fname = NULL;
+	int ret;
+
+	fname = synthetic_smb_fname(talloc_tos(),
+				    handle->conn->connectpath,
+				    NULL,
+				    NULL,
+				    0);
+	if (fname == NULL) {
+		DBG_ERR("synthetic_smb_fname failed\n");
+		return -1;
+	}
+
+	ret = SMB_VFS_NEXT_STAT(handle, fname);
+	TALLOC_FREE(fname);
+	if (ret != 0) {
+		DBG_ERR("stat failed for %s with %s\n",
+			handle->conn->connectpath, strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
 static int fileid_connect(struct vfs_handle_struct *handle,
 			  const char *service, const char *user)
 {
@@ -303,6 +330,8 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 		return -1;
 	}
 
+	data->nolockinode = 0;
+
 	/*
 	 * "fileid:mapping" is only here as fallback for old setups
 	 * "fileid:algorithm" is the option new setups should use
@@ -321,6 +350,16 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 		data->device_mapping_fn	= fileid_device_mapping_fsid;
 	} else if (strcmp("hostname", algorithm) == 0) {
 		data->device_mapping_fn = fileid_device_mapping_hostname;
+	} else if (strcmp("fsname_norootdir", algorithm) == 0) {
+		data->device_mapping_fn	= fileid_device_mapping_fsname;
+
+		ret = get_connectpath_ino(handle, &data->nolockinode);
+		if (ret != 0) {
+			saved_errno = errno;
+			SMB_VFS_NEXT_DISCONNECT(handle);
+			errno = saved_errno;
+			return -1;
+		}
 	} else {
 		SMB_VFS_NEXT_DISCONNECT(handle);
 		DEBUG(0,("fileid_connect(): unknown algorithm[%s]\n", algorithm));
@@ -380,14 +419,14 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 	}
 
 	data->nolockinode = lp_parm_ulong(SNUM(handle->conn), "fileid",
-					  "nolockinode", 0);
+					  "nolockinode", data->nolockinode);
 
 	SMB_VFS_HANDLE_SET_DATA(handle, data, NULL,
 				struct fileid_handle_data,
 				return -1);
 
-	DEBUG(10, ("fileid_connect(): connect to service[%s] with algorithm[%s]\n",
-		service, algorithm));
+	DBG_DEBUG("connect to service[%s] with algorithm[%s] nolockinode %lli\n",
+		  service, algorithm, (long long) data->nolockinode);
 
 	return 0;
 }
-- 
2.13.6



More information about the samba-technical mailing list