[SCM] Samba Shared Repository - branch v3-4-test updated - release-4-0-0alpha7-881-ge4628c6

Tim Prouty tprouty at samba.org
Tue May 5 23:50:14 GMT 2009


The branch, v3-4-test has been updated
       via  e4628c6fc7348f56666adc69722809ea539c4fe7 (commit)
       via  92558a875ebf842e652614a5519ae101dd62ffd1 (commit)
      from  f4e2f7bc23da5f73311bb7adeab2838af14bdeaf (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-4-test


- Log -----------------------------------------------------------------
commit e4628c6fc7348f56666adc69722809ea539c4fe7
Author: tprouty <tprouty at b72e2a10-2d34-0410-9a71-d3beadf02b57>
Date:   Tue May 5 01:17:04 2009 +0000

    s3 onefs: Turn up the debug level for non-error cases

commit 92558a875ebf842e652614a5519ae101dd62ffd1
Author: tprouty <tprouty at b72e2a10-2d34-0410-9a71-d3beadf02b57>
Date:   Sat May 2 00:28:38 2009 +0000

    s3: Fix trans2 path to use case-insensitive stat optimization
    
    Often times before creating a file, a client will first query to see
    if it already exists.  Since some systems have a case-insensitive stat
    that is called from unix_convert, we can definitively return
    STATUS_NO_SUCH_FILE to the client without scanning the whole
    directory.
    
    This code path is taken from trans2querypathinfo, but trans2findfirst
    still does a full directory scan even though the get_real_filename
    (the case-insensitive stat vfs call) can prevent this.
    
    This patch adds the get_real_filename call to the trans2find* path,
    and also changes the vfs_default behavior for
    SMB_VFS_GET_REAL_FILENAME.  Previously, in the absence of a
    get_real_filename implementation, we would fallback to the full
    directory scan.  The default behavior now returns -1 and sets errno to
    EOPNOTSUPP.  This allows SMB_VFS_GET_REALFILENAME to be called from
    trans2* and unix_convert.

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

Summary of changes:
 source3/modules/onefs_system.c |    6 +++---
 source3/modules/vfs_default.c  |    8 ++++++--
 source3/smbd/dir.c             |   17 +++++++++++++++++
 source3/smbd/filename.c        |   40 ++++++++++++++++++++++++++++++++++------
 4 files changed, 60 insertions(+), 11 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/modules/onefs_system.c b/source3/modules/onefs_system.c
index bc2ed46..cf99a27 100644
--- a/source3/modules/onefs_system.c
+++ b/source3/modules/onefs_system.c
@@ -580,7 +580,7 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
 
 	/* Log if recvfile didn't write everything it read. */
 	if (total_rbytes != total_wbytes) {
-		DEBUG(0, ("partial recvfile: total_rbytes=%llu but "
+		DEBUG(3, ("partial recvfile: total_rbytes=%llu but "
 			  "total_wbytes=%llu, diff = %llu\n", total_rbytes,
 			  total_wbytes, total_rbytes - total_wbytes));
 		SMB_ASSERT(total_rbytes > total_wbytes);
@@ -591,7 +591,7 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
 	 */
 	while (total_rbytes < count) {
 
-		DEBUG(0, ("shallow recvfile (%s), reading %llu\n",
+		DEBUG(3, ("shallow recvfile (%s), reading %llu\n",
 			  strerror(errno), count - total_rbytes));
 
 		/*
@@ -628,7 +628,7 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
 	 */
 	while (total_wbytes < count) {
 
-		DEBUG(0, ("partial recvfile, writing %llu\n", count - total_wbytes));
+		DEBUG(3, ("partial recvfile, writing %llu\n", count - total_wbytes));
 
 		ret = sys_pwrite(tofd, spill_buffer, count - total_wbytes,
 				 offset + total_wbytes);
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index bb01f98..6c1946a 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1120,8 +1120,12 @@ static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
 				     TALLOC_CTX *mem_ctx,
 				     char **found_name)
 {
-	return get_real_filename(handle->conn, path, name, mem_ctx,
-				 found_name);
+	/*
+	 * Don't fall back to get_real_filename so callers can differentiate
+	 * between a full directory scan and an actual case-insensitive stat.
+	 */
+	errno = EOPNOTSUPP;
+	return -1;
 }
 
 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index b4a8f94..e790287 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -576,6 +576,9 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx,
 {
 	char *name = NULL;
 	char *pathreal = NULL;
+	char *found_name = NULL;
+	int ret;
+
 	SET_STAT_INVALID(*pst);
 
 	if (dptr->has_wild || dptr->did_stat) {
@@ -640,6 +643,20 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx,
 		goto clean;
 	}
 
+	/*
+	 * Try case-insensitive stat if the fs has the ability. This avoids
+	 * scanning the whole directory.
+	 */
+	ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
+					ctx, &found_name);
+	if (ret == 0) {
+		name = found_name;
+		goto clean;
+	} else if (errno == ENOENT) {
+		/* The case-insensitive lookup was authoritative. */
+		goto clean;
+	}
+
 	TALLOC_FREE(pathreal);
 
 	return dptr_normal_ReadDirName(dptr, poffset, pst);
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 80722a7..774ab27 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -447,9 +447,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
 			 */
 
 			if (name_has_wildcard ||
-			    (SMB_VFS_GET_REAL_FILENAME(
-				     conn, dirpath, start,
-				     talloc_tos(), &found_name) == -1)) {
+			    (get_real_filename(conn, dirpath, start,
+					       talloc_tos(),
+					       &found_name) == -1)) {
 				char *unmangled;
 
 				if (end) {
@@ -789,9 +789,9 @@ static bool fname_equal(const char *name1, const char *name2,
  If the name looks like a mangled name then try via the mangling functions
 ****************************************************************************/
 
-int get_real_filename(connection_struct *conn, const char *path,
-		      const char *name, TALLOC_CTX *mem_ctx,
-		      char **found_name)
+static int get_real_filename_full_scan(connection_struct *conn,
+				       const char *path, const char *name,
+				       TALLOC_CTX *mem_ctx, char **found_name)
 {
 	struct smb_Dir *cur_dir;
 	const char *dname;
@@ -887,6 +887,34 @@ int get_real_filename(connection_struct *conn, const char *path,
 	return -1;
 }
 
+/****************************************************************************
+ Wrapper around the vfs get_real_filename and the full directory scan
+ fallback.
+****************************************************************************/
+
+int get_real_filename(connection_struct *conn, const char *path,
+		      const char *name, TALLOC_CTX *mem_ctx,
+		      char **found_name)
+{
+	int ret;
+
+	/* Try the vfs first to take advantage of case-insensitive stat. */
+	ret = SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name);
+
+	/*
+	 * If the case-insensitive stat was successful, or returned an error
+	 * other than EOPNOTSUPP then there is no need to fall back on the
+	 * full directory scan.
+	 */
+	if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
+		return ret;
+	}
+
+	ret = get_real_filename_full_scan(conn, path, name, mem_ctx,
+					  found_name);
+	return ret;
+}
+
 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
 				  connection_struct *conn,
 				  const char *orig_path,


-- 
Samba Shared Repository


More information about the samba-cvs mailing list