]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: avoid calling vfs_file_id_from_sbuf() if statinfo is not valid
authorRalph Boehme <slow@samba.org>
Fri, 17 Jan 2020 09:56:00 +0000 (10:56 +0100)
committerJeremy Allison <jra@samba.org>
Fri, 17 Jan 2020 22:38:14 +0000 (22:38 +0000)
When we're about to create a file, the stat info will be all zero, so
vfs_file_id_from_sbuf() would return a bogus file_id. This is normally not a
problem, as open_file() itself also calls vfs_file_id_from_sbuf() after having
created the file.

This is however a problem when using the VFS module fileid, as that is doing
caching of /etc/mtab and failing to find smb_fname->st.st_ex_dev (all zero in
this case when creating a new file) in the mtab cache will trigger a mtab reload
which can be *very* expensive.

Copying many small files to a Samba server in this situation will result in
abysimal performance.

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

Pair-Programmed-With: Jeremy Allison <jra@samba.org>
Signed-off-by: Ralph Boehme <slow@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Fri Jan 17 22:38:14 UTC 2020 on sn-devel-184

source3/smbd/open.c

index a012e33316fe9bcf99aa4aff89b5c0b922bef3fa..e64e22581e0060ee5e512ab8740ed2fa4a88d5a1 100644 (file)
@@ -3596,7 +3596,15 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+       if (VALID_STAT(smb_fname->st)) {
+               /*
+                * Only try and create a file id before open
+                * for an existing file. For a file being created
+                * this won't do anything useful until the file
+                * exists and has a valid stat struct.
+                */
+               fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+       }
        fsp->fh->private_options = private_flags;
        fsp->access_mask = open_access_mask; /* We change this to the
                                              * requested access_mask after