[SCM] Samba Shared Repository - branch master updated

Ralph Böhme slow at samba.org
Tue Jul 5 16:02:01 UTC 2022


The branch, master has been updated
       via  4f5faa806e8 docs-xml:manpages: update vfs_fileid.8.xml for the recent changes
       via  a63087f527e s3:vfs_fileid: add 'fileid:nolock_all_inodes = BOOL'
       via  dc478f4897f s3:vfs_fileid: add 'fileid:nolock_all_dirs = BOOL'
       via  d0d9732acd3 s3:vfs_fileid: introduce 'fileid:nolock_paths'
       via  c040b811eb2 s3:vfs_fileid: introduce 'fileid:nolock_max_slots'
       via  f99b617c0c0 s3:vfs_fileid: also imply the generic nolock logic to the legacy 'hostname' algorithm
       via  48403b0ebba s3:vfs_fileid: also handle 'fsname_nodirs' via fileid_is_nolock_inode()
       via  72419736bda s3:vfs_fileid: always add the 'nolock' behavior via file_id.extid
       via  a1882538299 s3:vfs_fileid: introduce algorithm 'next_module'
       via  2668700f1e8 s3:vfs_fileid: maintain an array of nolock inodes
       via  3ec4dddb54c s3:vfs_fileid: move to a single mapping_fn() returning struct file_id
       via  2dfb334f8cb s4:torture/smb2: add smb2.bench.path-contention-shared
       via  090c46a5473 s4:torture/smb2: rename 'smb2.bench-oplock' to 'smb2.bench.oplock'
      from  96a649efd8d s3: libads: Fix coverity false positive.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 4f5faa806e8cdb1c979ca4fd71e04504eeb53cb0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 28 16:25:46 2022 +0000

    docs-xml:manpages: update vfs_fileid.8.xml for the recent changes
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Ralph Böhme <slow at samba.org>
    Autobuild-Date(master): Tue Jul  5 16:01:10 UTC 2022 on sn-devel-184

commit a63087f527eceeba1def358435dc3e5fb8059b26
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 17:50:08 2022 +0200

    s3:vfs_fileid: add 'fileid:nolock_all_inodes = BOOL'
    
    This adds the feature of the 'hostname' algorithm,
    but provides it for all algorithms, including 'next_module'.
    
    This can be used to deliberately break lock coherency, but
    keep the devid/inode pair untouched, as this will only
    alter file_id.extid:
    
      vfs objects = fileid
      fileid:algorithm = next_module
      fileid:nolock_all_inodes = yes
    
    This should be preferred unless someone is already using the
    'hostname' algorithm.
    
    Note this is only for testing (or read only shares if at all...)
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit dc478f4897fe5b8b1ca941f44d1b025a3130ae0a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 17:50:08 2022 +0200

    s3:vfs_fileid: add 'fileid:nolock_all_dirs = BOOL'
    
    This adds the feature of the 'fsname_nodirs' algorithm,
    but provides it for all algorithms, including 'next_module'.
    
    This can be used to deliberately break lock coherency, but
    keep the devid/inode pair untouched, e.g.
    
      vfs objects = fileid
      fileid:algorithm = next_module
      fileid:nolock_all_dirs = yes
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit d0d9732acd3dff2511f5a9c0a80aba372b6255e2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 17:14:22 2022 +0200

    s3:vfs_fileid: introduce 'fileid:nolock_paths'
    
    This brings much more flexibility compared to:
    - 'fsname_norootdir', 'fsname_norootdir_ext',
      which only allow the nolock behavior for the share root
    - 'fileid:nolockinode', which only gets a single inode number,
      and ignores the devide id completely.
    
    You can specify path names, which are relative to the shareroot
    or absolute.
    
    These names are only evaluated at SMB_VFS_CONNECT() time,
    where they are converted into devide and inode pairs.
    It means they are completely ignored if the path doesn't
    exist yet, or is replaced by a new inode later.
    
    This allows:
    
    - 'fileid:algorithm = fsname_norootdir'
      to be replaced by:
      'fileid:algorithm = fsname' (the default)
      'fileid:nolock_paths = .'
    
    - 'fileid:algorithm = fsname_norootdir_ext'
      to be replaced by:
      'fileid:algorithm = fsname' (the default)
      'fileid:nolock_paths = .'
      'fileid:nolock_max_slots = 18446744073709551615'
    
    And 'fileid:nolockinode = 1234567' and be replaced by
    'fileid:nolock_paths = Very/Contended/Path' or
    'fileid:nolock_paths = . Very/Contended/Path1 /data/conteded.dir',
    if the share root and two additional inodes should be handled
    by the 'nolock' behavior.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit c040b811eb2b866184cde18145b4a14f249792c9
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 17:09:51 2022 +0200

    s3:vfs_fileid: introduce 'fileid:nolock_max_slots'
    
    This controlls the maximum number of concurrent locking slots
    on each host. It specifies the maximal number of locking.tdb
    records for a single inode.
    
    It can be used to deliberately break lock coherency not
    only between cluster nodes, but also between processes on
    each node.
    
    This allows administrators to control the behavior that's
    currently only available by 'fsname_norootdir_ext' to
    other cases as well.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit f99b617c0c0cb4ffa52d8ac0732b8600974693d0
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 17:06:12 2022 +0200

    s3:vfs_fileid: also imply the generic nolock logic to the legacy 'hostname' algorithm
    
    That way the file_id.extid is consistenly filled for all cases
    where we deliberately break lock coherency.
    
    This will simplify further changes and give administrators more
    flexibility.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 48403b0ebba2d0d8372cfa0d4ad6d418b7bc07a6
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 17:02:32 2022 +0200

    s3:vfs_fileid: also handle 'fsname_nodirs' via fileid_is_nolock_inode()
    
    This means we'll be able to provide the 'nolock' feature for all
    directories also with other algorithms than 'fsname' in future.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 72419736bdad62a82b81e8c870f5305d92a6d77d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 16:47:50 2022 +0200

    s3:vfs_fileid: always add the 'nolock' behavior via file_id.extid
    
    file_id.extid was filled with getpid() by 'fsname_norootdir_ext'.
    
    However instead of forcing the existing 'hostname' algorithm for the 'nolock'
    case, we'll now generate file_id.extid also based the hostname, vnn
    and for 'fsname_norootdir_ext' also the pid.
    
    This simplifies further changes and gives us the ability to generate stable
    results for file_id.{devid,inode} based on the main algorithm. This is important
    as we have a push_file_id_16() helper function used in places to generate a
    stable identifier of the file that is also client visible and might be stored on
    stable storage (acl_tdb, xattr_tdb). While the file_id.extid is only used
    internally in volatile databases.
    
    Review with: git show --patience
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit a1882538299a79a55c1155197621a2459d413fe2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 16:35:47 2022 +0200

    s3:vfs_fileid: introduce algorithm 'next_module'
    
    This can be use to get just bypass the fileid module for the
    common case. But it allows 'fileid:nolockinode' (and in future
    other things) to work in order to avoid lock contention
    for all 'nolock' inodes.
    
    If we would have started from scratch all the nolock
    logic would have been in its own vfs module, just
    altering file_id.extid
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 2668700f1e8287114f0a2a0b6b14f1eebd2501a7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 29 16:31:22 2022 +0200

    s3:vfs_fileid: maintain an array of nolock inodes
    
    This way 'fsname_norootdir[_ext]' is not overwritten by
    'fileid:nolockinode' and both can work independently.
    
    It will also allow us to add more nolock inodes under
    other conditions in the following changes.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 3ec4dddb54c75f6cc123b42d6c625a0d1f8b28c6
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 22 17:33:49 2022 +0200

    s3:vfs_fileid: move to a single mapping_fn() returning struct file_id
    
    This makes the code much less magic (at least for me) and
    it will allow further changes to be made easier.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 2dfb334f8cb848671a8f6e46bebe83b62fe380e5
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jun 23 12:23:53 2022 +0200

    s4:torture/smb2: add smb2.bench.path-contention-shared
    
    This test tortures contention on a single path where
    all opens are shared stat opens without any oplock/lease
    interaction.
    
    It opens 'nproc' connections to the share and runs
    for 'timelimit' seconds, while it opens and closes
    the 'bench_path' on each connection as fast as possible.
    
    The number of concurrent connections can be specified
    with:
    
      --option="torture:nprocs=256"
    
    while the default is 4.
    
    The runtime can be specified by
    
      --option='torture:timelimit=30'
    
    the default being 10.
    
    By default the test operates on the share root directory, but
    the path can be changed with:
    
      --option='torture:bench_path=Apps\1\2\3\4\5\6\7\8\9\10'
    
    pointing to an existing file or directory.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 090c46a547361b08f1d93d77c0503b9c88179c15
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Jun 28 14:44:51 2022 +0000

    s4:torture/smb2: rename 'smb2.bench-oplock' to 'smb2.bench.oplock'
    
    We should have a toplevel 'smb2.bench' suite for all benchmark tests.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

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

Summary of changes:
 docs-xml/manpages/vfs_fileid.8.xml | 143 +++++++++---
 source3/modules/vfs_fileid.c       | 333 +++++++++++++++++++++-------
 source4/torture/smb2/create.c      | 435 +++++++++++++++++++++++++++++++++++++
 source4/torture/smb2/smb2.c        |   2 +-
 4 files changed, 812 insertions(+), 101 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/manpages/vfs_fileid.8.xml b/docs-xml/manpages/vfs_fileid.8.xml
index defb71229e9..8732f951121 100644
--- a/docs-xml/manpages/vfs_fileid.8.xml
+++ b/docs-xml/manpages/vfs_fileid.8.xml
@@ -14,7 +14,7 @@
 <refnamediv>
 	<refname>vfs_fileid</refname>
 	<refpurpose>Generates file_id structs with unique device id values for
-	cluster setups</refpurpose>
+	cluster setups. It also adds ways to deliberately break lock coherency for specific inodes</refpurpose>
 </refnamediv>
 
 <refsynopsisdiv>
@@ -61,40 +61,61 @@
 		<term>fileid:algorithm = ALGORITHM</term>
 		<listitem>
 		<para>Available algorithms are <command>fsname</command>,
-		<command>fsname_nodirs</command>, <command>fsid</command> and
-		<command>hostname</command>. The default value is
-		<command>fsname</command>.
+		<command>fsid</command>, <command>next_module</command>. The default value is
+		<command>fsname</command>. As well as the following legacy
+		algorithms: <command>fsname_nodirs</command>, <command>fsname_norootdir</command>,
+		<command>fsname_norootdir_ext</command> and <command>hostname</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.
 		</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>The <command>next_module</command> algorithm lets the next vfs module
+		in the module chain generate the id. This is mainly used in combination
+		with the various 'nolock' features the fileid module provides.
+		</para>
+
+		<para>The legacy <command>hostname</command> algorithm generates unique
+		devid by hashing the hostname and low level device id.
+		It also implies <command>fileid:nolock_all_inodes=yes</command>.
+		This can be used to deliberately break lock coherency in a cluster
+		and with <command>fileid:nolock_max_slots</command> also between local processes
+		within a node. NOTE: Do not use this without knowing what you are doing!
+		It breaks SMB semantics and it can lead to data corruption!
+		This implies <command>fileid:nolock_all_inodes=yes</command>.
 		</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
+
+		<para>The legacy <command>fsname_nodirs</command> algorithm is an alias
+		for using the <command>fsname</command> algorithm together with
+		<command>fileid:nolock_all_dirs=yes</command>.
+		NOTE: Do not use this without knowing what you are doing!
+		It breaks SMB semantics!
+		See <command>fileid:nolock_paths</command> for a more fine grained
+		approach.
+		</para>
+
+		<para>The legacy <command>fsname_norootdir</command> algorithm is an alias
+		for using the <command>fsname</command> algorithm together with
+		<command>fileid:nolock_paths= <quote>.</quote> </command>. It means
+		this can be used to deliberately break lock coherency
 		in a cluster for the root directory of a share.
 		</para>
-		<para>The <command>fsname_norootdir_ext</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. Additionally it generates an extid based on the
-		process pid. This can be used to deliberately break lock
-		coherency between all smbd processes in the whole cluster for
-		the root directory of a share.
+
+		<para>The legacy <command>fsname_norootdir_ext</command> algorithm is an alias
+		for using the <command>fsname</command> algorithm together with
+		<command>fileid:nolock_paths= <quote>.</quote></command> and
+		<command>fileid:nolock_max_slots = 18446744073709551615</command>.
+		It means this can be used to deliberately break lock coherency
+		completely for the root directory of a share. Even local processes
+		are no longer lock coherent.
 		</para>
+
 		</listitem>
 		</varlistentry>
 
@@ -147,12 +168,69 @@
 		</varlistentry>
 
 		<varlistentry>
-		<term>fileid:nolockinode</term>
+		<term>fileid:nolock_max_slots = NUMBER(1-18446744073709551615)</term>
 		<listitem>
-		<para>This option triggers use of the fileid hostname algorithm
-		for the configured inode which can be used to deliberately break
+		<para>This option alters the behavior of the <command>nolock</command> algorithm
+		in a ways that it also breaks the lock coherency between individual processes
+		on the same host. The default is to have just 1 concurrent slot available per host.
+		By incressing the number of slots you can specify how many concurrent processes
+		can work on a given inode without contention, the number should typically be larger
+		than the a number of logical cpus, maybe 2 times of num_cpus.
+		</para>
+		</listitem>
+		</varlistentry>
+
+		<varlistentry>
+		<term>fileid:nolock_all_dirs = BOOL</term>
+		<listitem>
+		<para>This option triggers the use of the fileid nolock behavior
+		for all directory inodes, which can be used to deliberately break
+		the lock coherency for all directories.
+		NOTE: Do not use this without knowing what you are doing!
+		It breaks SMB semantics!
+		See <command>fileid:nolock_paths</command> for a more fine grained
+		approach.
+		</para>
+		</listitem>
+		</varlistentry>
+
+		<varlistentry>
+		<term>fileid:nolock_all_inodes = BOOL</term>
+		<listitem>
+		<para>This option triggers the use of the fileid nolock algorithm
+		for all directoriy inode, which can be used to deliberately break
+		the lock coherency for all directories.
+		NOTE: Do not use this without knowing what you are doing!
+		It breaks SMB semantics and it can lead to data corruption!
+		See <command>fileid:nolock_paths</command> for a more fine grained
+		approach.
+		</para>
+		</listitem>
+		</varlistentry>
+
+		<varlistentry>
+		<term>fileid:nolock_paths = LIST</term>
+		<listitem>
+		<para>This option specifies a path list referring to files and/or directories,
+		which should use fileid nolock algorithm in order to deliberately break
+		the lock coherency for them. The specified paths can be relative to
+		the share root directory or absolute. The names are case sensitive unix pathnames!
+		Note all paths are only evaluated at tree connect time, when the share is being connected, from there on
+		only the related device and inode numbers from the stat() syscall are compared.
+		Non existing paths will generate a log level 0 message.
+		NOTE: This option should be used with care as it breaks SMB semantics!
+		But it may help in situation where a specific (commonly read-only) inode is highly contended.
+		</para>
+		</listitem>
+		</varlistentry>
+
+		<varlistentry>
+		<term>fileid:nolockinode = NUMBER</term>
+		<listitem>
+		<para>This legacy option triggers use of the fileid nolock behavior
+		for the configured inode, while ignoring and device id. This can be used to deliberately break
 		lock coherency for the corresponding file or directory in a
-		cluster.
+		cluster. Using the <command>fileid:nolock_paths</command> option is much more flexible and simpler to use.
 		</para>
 		</listitem>
 		</varlistentry>
@@ -171,6 +249,17 @@
 	<smbconfoption name="fileid:algorithm">fsid</smbconfoption>
 </programlisting>
 
+	<para>Usage of the <command>fileid</command> module in order
+	avoid load on heavily contended (most likely read-only) inodes.</para>
+
+<programlisting>
+        <smbconfsection name="[global]"/>
+	<smbconfoption name="vfs objects">fileid</smbconfoption>
+	<smbconfoption name="fileid:algorithm">next_module</smbconfoption>
+	<smbconfoption name="fileid:nolock_paths">. ContendedFolder1 /path/to/contended.exe</smbconfoption>
+	<smbconfoption name="fileid:nolock_max_slots">256</smbconfoption>
+</programlisting>
+
 </refsect1>
 
 <refsect1>
diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c
index 3c9cd33f6f2..2c67946efb3 100644
--- a/source3/modules/vfs_fileid.c
+++ b/source3/modules/vfs_fileid.c
@@ -35,18 +35,28 @@ struct fileid_mount_entry {
 	uint64_t devid;
 };
 
+struct fileid_nolock_inode {
+	dev_t dev;
+	ino_t ino;
+};
+
 struct fileid_handle_data {
-	uint64_t (*device_mapping_fn)(struct fileid_handle_data *data,
-				      const SMB_STRUCT_STAT *sbuf);
-	uint64_t (*extid_mapping_fn)(struct fileid_handle_data *data,
-				      const SMB_STRUCT_STAT *sbuf);
+	struct vfs_handle_struct *handle;
+	struct file_id (*mapping_fn)(struct fileid_handle_data *data,
+				     const SMB_STRUCT_STAT *sbuf);
 	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;
-	ino_t nolockinode;
+	struct {
+		bool force_all_inodes;
+		bool force_all_dirs;
+		uint64_t extid;
+		size_t num_inodes;
+		struct fileid_nolock_inode *inodes;
+	} nolock;
 };
 
 /* check if a mount entry is allowed based on fstype and mount directory */
@@ -212,6 +222,16 @@ static uint64_t fileid_device_mapping_fsname(struct fileid_handle_data *data,
 	return m->devid;
 }
 
+static struct file_id fileid_mapping_fsname(struct fileid_handle_data *data,
+					    const SMB_STRUCT_STAT *sbuf)
+{
+	struct file_id id = { .inode = sbuf->st_ex_ino, };
+
+	id.devid = fileid_device_mapping_fsname(data, sbuf);
+
+	return id;
+}
+
 /* a device mapping using a hostname */
 static uint64_t fileid_device_mapping_hostname(struct fileid_handle_data *data,
 					       const SMB_STRUCT_STAT *sbuf)
@@ -243,16 +263,107 @@ 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)
+static struct file_id fileid_mapping_hostname(struct fileid_handle_data *data,
+					      const SMB_STRUCT_STAT *sbuf)
+{
+	struct file_id id = { .inode = sbuf->st_ex_ino, };
+
+	id.devid = fileid_device_mapping_hostname(data, sbuf);
+
+	return id;
+}
+
+static bool fileid_is_nolock_inode(struct fileid_handle_data *data,
+				   const SMB_STRUCT_STAT *sbuf)
 {
-	if (S_ISDIR(sbuf->st_ex_mode)) {
-		return fileid_device_mapping_hostname(data, sbuf);
+	size_t i;
+
+	if (data->nolock.force_all_inodes) {
+		return true;
 	}
 
-	return fileid_device_mapping_fsname(data, sbuf);
+	if (S_ISDIR(sbuf->st_ex_mode) && data->nolock.force_all_dirs) {
+		return true;
+	}
+
+	/*
+	 * We could make this a binary search over an sorted array,
+	 * but for now we keep things simple.
+	 */
+
+	for (i=0; i < data->nolock.num_inodes; i++) {
+		if (data->nolock.inodes[i].ino != sbuf->st_ex_ino) {
+			continue;
+		}
+
+		if (data->nolock.inodes[i].dev == 0) {
+			/*
+			 * legacy "fileid:nolockinode"
+			 * handling ignoring dev
+			 */
+			return true;
+		}
+
+		if (data->nolock.inodes[i].dev != sbuf->st_ex_dev) {
+			continue;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static int fileid_add_nolock_inode(struct fileid_handle_data *data,
+				   const SMB_STRUCT_STAT *sbuf)
+{
+	bool exists = fileid_is_nolock_inode(data, sbuf);
+	struct fileid_nolock_inode *inodes = NULL;
+
+	if (exists) {
+		return 0;
+	}
+
+	inodes = talloc_realloc(data, data->nolock.inodes,
+				struct fileid_nolock_inode,
+				data->nolock.num_inodes + 1);
+	if (inodes == NULL) {
+		return -1;
+	}
+
+	inodes[data->nolock.num_inodes] = (struct fileid_nolock_inode) {
+		.dev = sbuf->st_ex_dev,
+		.ino = sbuf->st_ex_ino,
+	};
+	data->nolock.inodes = inodes;
+	data->nolock.num_inodes += 1;
+
+	return 0;
+}
+
+static uint64_t fileid_mapping_nolock_extid(uint64_t max_slots)
+{
+	char buf[8+4+HOST_NAME_MAX+1] = { 0, };
+	uint64_t slot = 0;
+	uint64_t id;
+	int rc;
+
+	if (max_slots > 1) {
+		slot = getpid() % max_slots;
+	}
+
+	PUSH_LE_U64(buf, 0, slot);
+	PUSH_LE_U32(buf, 8, get_my_vnn());
+
+	rc = gethostname(&buf[12], HOST_NAME_MAX+1);
+	if (rc != 0) {
+		DBG_ERR("gethostname failed\n");
+		return UINT64_MAX;
+	}
+
+	id = fileid_uint64_hash((uint8_t *)buf, ARRAY_SIZE(buf));
+
+	return id;
 }
 
 /* device mapping functions using a fsid */
@@ -282,44 +393,68 @@ static uint64_t fileid_device_mapping_fsid(struct fileid_handle_data *data,
 	return m->devid;
 }
 
-static uint64_t fileid_extid_mapping_zero(struct fileid_handle_data *data,
+static struct file_id fileid_mapping_fsid(struct fileid_handle_data *data,
 					  const SMB_STRUCT_STAT *sbuf)
 {
-	return 0;
+	struct file_id id = { .inode = sbuf->st_ex_ino, };
+
+	id.devid = fileid_device_mapping_fsid(data, sbuf);
+
+	return id;
 }
 
-static uint64_t fileid_extid_mapping_pid(struct fileid_handle_data *data,
-					 const SMB_STRUCT_STAT *sbuf)
+static struct file_id fileid_mapping_next_module(struct fileid_handle_data *data,
+						 const SMB_STRUCT_STAT *sbuf)
 {
-	return getpid();
+	return SMB_VFS_NEXT_FILE_ID_CREATE(data->handle, sbuf);
 }
 
 static int get_connectpath_ino(struct vfs_handle_struct *handle,
-			       ino_t *ino)
+			       const char *path,
+			       SMB_STRUCT_STAT *psbuf)
 {
+	TALLOC_CTX *frame = talloc_stackframe();
 	struct smb_filename *fname = NULL;
+	const char *fullpath = NULL;
 	int ret;
 
-	fname = synthetic_smb_fname(talloc_tos(),
-				    handle->conn->connectpath,
+	if (path[0] == '/') {
+		fullpath = path;
+	} else {
+		fullpath = talloc_asprintf(frame,
+					   "%s/%s",
+					   handle->conn->connectpath,
+					   path);
+		if (fullpath == NULL) {
+			DBG_ERR("talloc_asprintf() failed\n");
+			TALLOC_FREE(frame);
+			return -1;
+		}
+	}
+
+	fname = synthetic_smb_fname(frame,
+				    fullpath,
 				    NULL,
 				    NULL,
 				    0,
 				    0);
 	if (fname == NULL) {
-		DBG_ERR("synthetic_smb_fname failed\n");
+		DBG_ERR("synthetic_smb_fname(%s) failed - %s\n",
+			fullpath, strerror(errno));
+		TALLOC_FREE(frame);
 		return -1;
 	}
 
 	ret = SMB_VFS_NEXT_STAT(handle, fname);
 	if (ret != 0) {
 		DBG_ERR("stat failed for %s with %s\n",
-			handle->conn->connectpath, strerror(errno));
-		TALLOC_FREE(fname);
+			fullpath, strerror(errno));
+		TALLOC_FREE(frame);
 		return -1;
 	}
-	*ino = fname->st.st_ex_ino;
-	TALLOC_FREE(fname);
+	*psbuf = fname->st;
+
+	TALLOC_FREE(frame);
 
 	return 0;
 }
@@ -333,6 +468,11 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 	const char **fstype_allow_list = NULL;
 	const char **mntdir_deny_list = NULL;
 	const char **mntdir_allow_list = NULL;
+	ino_t nolockinode;
+	uint64_t max_slots = 0;
+	bool rootdir_nolock = false;
+	const char **nolock_paths = NULL;
+	size_t i;
 	int saved_errno;
 	int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
 
@@ -340,7 +480,7 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 		return ret;
 	}
 
-	data = talloc_zero(handle->conn, struct fileid_handle_data);
+	data = talloc_zero(handle, struct fileid_handle_data);
 	if (!data) {
 		saved_errno = errno;
 		SMB_VFS_NEXT_DISCONNECT(handle);
@@ -348,8 +488,7 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 		errno = saved_errno;
 		return -1;
 	}
-
-	data->nolockinode = 0;
+	data->handle = handle;
 
 	/*
 	 * "fileid:mapping" is only here as fallback for old setups
@@ -362,39 +501,24 @@ static int fileid_connect(struct vfs_handle_struct *handle,
 					 "fileid", "algorithm",
 					 algorithm);
 	if (strcmp("fsname", algorithm) == 0) {
-		data->device_mapping_fn	= fileid_device_mapping_fsname;
-		data->extid_mapping_fn = fileid_extid_mapping_zero;
+		data->mapping_fn = fileid_mapping_fsname;
 	} else if (strcmp("fsname_nodirs", algorithm) == 0) {
-		data->device_mapping_fn = fileid_device_mapping_fsname_nodirs;
-		data->extid_mapping_fn = fileid_extid_mapping_zero;
+		data->mapping_fn = fileid_mapping_fsname;
+		data->nolock.force_all_dirs = true;
 	} else if (strcmp("fsid", algorithm) == 0) {
-		data->device_mapping_fn	= fileid_device_mapping_fsid;
-		data->extid_mapping_fn = fileid_extid_mapping_zero;
+		data->mapping_fn = fileid_mapping_fsid;
 	} else if (strcmp("hostname", algorithm) == 0) {
-		data->device_mapping_fn = fileid_device_mapping_hostname;
-		data->extid_mapping_fn = fileid_extid_mapping_zero;
+		data->mapping_fn = fileid_mapping_hostname;
+		data->nolock.force_all_inodes = true;
 	} else if (strcmp("fsname_norootdir", algorithm) == 0) {
-		data->device_mapping_fn	= fileid_device_mapping_fsname;
-		data->extid_mapping_fn = fileid_extid_mapping_zero;
-
-		ret = get_connectpath_ino(handle, &data->nolockinode);
-		if (ret != 0) {
-			saved_errno = errno;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list