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 <tpro...@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 <tpro...@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

Reply via email to