The branch, v4-0-test has been updated
       via  661f8af s3:dir - We now pass the previously spinning directory 
tests on ext4.
       via  4527bd6 s3:dir - Introduce a 64-bit directory offset <-> 32 bit 
wire offset map using memcache.
       via  75cc7c7 s3:dir - Add a new memcache type (non-talloc) - 
SMB1_SEARCH_OFFSET_MAP.
       via  b884da9 s3:dir - Map wire offsets to native directory cookies.
       via  79e6052 s3:dir - Cope with fixed mapping of 'special' values.
       via  334f7d4 s3: dir - Introduce 32-bit wire versions of the 'special' 
values.
       via  8874f5d s3:dir - Introduce a function to map a directory cookie to 
a 32-bit wire cookie.
       via  32fffa3 s3:dir - In the old SMB1 search code, rename offset to 
wire_offset to distinguish between wire and native offsets.
      from  0ce1612 shadow_copy2: add a comment explaining why we don't 
talloc_zero_array().

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


- Log -----------------------------------------------------------------
commit 661f8af3355229c8950665ca403c99265b9fc08a
Author: Jeremy Allison <j...@samba.org>
Date:   Mon Jan 13 10:20:25 2014 -0800

    s3:dir - We now pass the previously spinning directory tests on ext4.
    
    https://bugzilla.samba.org/show_bug.cgi?id=2662
    
    Signed-off-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    
    Autobuild-User(master): Andreas Schneider <a...@cryptomilk.org>
    Autobuild-Date(master): Wed Jan 15 11:39:12 CET 2014 on sn-devel-104
    
    (cherry picked from commit 0f9a189e36d8e30dfd40e42130329a0984938ddd)
    
    Autobuild-User(v4-0-test): Karolin Seeger <ksee...@samba.org>
    Autobuild-Date(v4-0-test): Wed Jan 29 21:39:55 CET 2014 on sn-devel-104

commit 4527bd6bca977943906c1247ce44107055350362
Author: Jeremy Allison <j...@samba.org>
Date:   Sat Jan 11 15:45:48 2014 -0800

    s3:dir - Introduce a 64-bit directory offset <-> 32 bit wire offset map 
using memcache.
    
    Should fix the DOS clients against 64-bit smbd's bug.
    
    https://bugzilla.samba.org/show_bug.cgi?id=2662
    
    Signed-off-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    (cherry picked from commit 97cd9c6729a3821faa2dbc1588a40c5e03b9fd4f)

commit 75cc7c7e22adc56e9d993747db9ee67e8d660b0e
Author: Jeremy Allison <j...@samba.org>
Date:   Sat Jan 11 13:58:46 2014 -0800

    s3:dir - Add a new memcache type (non-talloc) - SMB1_SEARCH_OFFSET_MAP.
    
    We will use this in mapping 64-bit directory offset
    cookies to a 32-bit counter.
    
    https://bugzilla.samba.org/show_bug.cgi?id=2662
    
    Signed-off-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    (cherry picked from commit 4e0c41a321b2683610748c8c176fc46aaa8d114d)

commit b884da932b1e1d95709d17c1803f73aefff9916b
Author: Jeremy Allison <j...@samba.org>
Date:   Sat Jan 11 15:04:38 2014 -0800

    s3:dir - Map wire offsets to native directory cookies.
    
    Take care of the special offsets.
    
    https://bugzilla.samba.org/show_bug.cgi?id=2662
    
    Signed-off-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    (cherry picked from commit 42c80358c83dca65cdde78f442056ec0f55ecbb1)

commit 79e60528274e6382b42b8408627304259e2ecf4a
Author: Jeremy Allison <j...@samba.org>
Date:   Sat Jan 11 14:59:00 2014 -0800

    s3:dir - Cope with fixed mapping of 'special' values.
    
    https://bugzilla.samba.org/show_bug.cgi?id=2662
    
    Signed-off-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    (cherry picked from commit 81df4123ca6fae6e9d901c59a12407f3f89dc335)

commit 334f7d4ad06c3f88c8d0bad96a220e880c69b270
Author: Jeremy Allison <j...@samba.org>
Date:   Sat Jan 11 14:56:57 2014 -0800

    s3: dir - Introduce 32-bit wire versions of the 'special' values.
    
    https://bugzilla.samba.org/show_bug.cgi?id=2662
    
    Signed-off-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    (cherry picked from commit 51a115b62048735b4c8ec79211ce45600cfa5c01)

commit 8874f5d50dfd64712d53554bd67cefe0767ebc1a
Author: Jeremy Allison <j...@samba.org>
Date:   Sat Jan 11 14:48:00 2014 -0800

    s3:dir - Introduce a function to map a directory cookie to a 32-bit wire 
cookie.
    
    Make this an identity for now.
    
    https://bugzilla.samba.org/show_bug.cgi?id=2662
    
    Signed-off-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    (cherry picked from commit 5afc25eceb0c0e031bbe162617309178f3bcc425)

commit 32fffa3fe9b6ed913d6d4d426f9f29fe1a6a0edf
Author: Jeremy Allison <j...@samba.org>
Date:   Sat Jan 11 14:36:17 2014 -0800

    s3:dir - In the old SMB1 search code, rename offset to wire_offset to 
distinguish between wire and native offsets.
    
    Rename uint32 type to correct uint32_t.
    
    https://bugzilla.samba.org/show_bug.cgi?id=2662
    
    Signed-off-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andreas Schneider <a...@samba.org>
    (cherry picked from commit 584de2078d3320ba2e232e5f504191616347d0d7)

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

Summary of changes:
 selftest/skip              |    2 -
 source3/include/memcache.h |    3 +-
 source3/smbd/dir.c         |  140 ++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 131 insertions(+), 14 deletions(-)


Changeset truncated at 500 lines:

diff --git a/selftest/skip b/selftest/skip
index 48d9ba6..f1fc690 100644
--- a/selftest/skip
+++ b/selftest/skip
@@ -106,5 +106,3 @@ bench # don't run benchmarks in our selftest
 ^samba4.drs.delete_object.python # flakey test
 ^samba4.rpc.unixinfo # This contains a server-side getpwuid call which hangs 
the server when nss_winbindd is in use
 ^samba.tests.dcerpc.unix  # This contains a server-side getpwuid call which 
hangs the server when nss_winbindd is in use
-base.dir2 # This test spins on modern ext4, so we have to skip it
-raw.search # This test spins on modern ext4, so we have to skip it
diff --git a/source3/include/memcache.h b/source3/include/memcache.h
index e0ac4af..9362483 100644
--- a/source3/include/memcache.h
+++ b/source3/include/memcache.h
@@ -40,7 +40,8 @@ enum memcache_number {
        MANGLE_HASH2_CACHE,
        PDB_GETPWSID_CACHE,     /* talloc */
        SINGLETON_CACHE_TALLOC, /* talloc */
-       SINGLETON_CACHE
+       SINGLETON_CACHE,
+       SMB1_SEARCH_OFFSET_MAP
 };
 
 /*
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 52bd6a1..c39c624 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -24,6 +24,7 @@
 #include "smbd/globals.h"
 #include "libcli/security/security.h"
 #include "lib/util/bitmap.h"
+#include "memcache.h"
 
 /*
    This module implements directory related functions for Samba.
@@ -34,6 +35,11 @@
 #define START_OF_DIRECTORY_OFFSET ((long)0)
 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
 
+/* "Special" directory offsets in 32-bit wire format. */
+#define WIRE_END_OF_DIRECTORY_OFFSET ((uint32_t)0xFFFFFFFF)
+#define WIRE_START_OF_DIRECTORY_OFFSET ((uint32_t)0)
+#define WIRE_DOT_DOT_DIRECTORY_OFFSET ((uint32_t)0x80000000)
+
 /* Make directory handle internals available. */
 
 struct name_cache_entry {
@@ -67,6 +73,8 @@ struct dptr_struct {
        bool has_wild; /* Set to true if the wcard entry has MS wildcard 
characters in it. */
        bool did_stat; /* Optimisation for non-wcard searches. */
        bool priv;     /* Directory handle opened with privilege. */
+       uint32_t counter;
+       struct memcache *dptr_cache;
 };
 
 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct 
*conn,
@@ -151,6 +159,8 @@ static void dptr_idle(struct dptr_struct *dptr)
        if (dptr->dir_hnd) {
                DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
                TALLOC_FREE(dptr->dir_hnd);
+               TALLOC_FREE(dptr->dptr_cache);
+               dptr->counter = 0;
        }
 }
 
@@ -904,6 +914,76 @@ void dptr_init_search_op(struct dptr_struct *dptr)
 }
 
 /****************************************************************************
+ Map a native directory offset to a 32-bit cookie.
+****************************************************************************/
+
+static uint32_t map_dir_offset_to_wire(struct dptr_struct *dptr, long offset)
+{
+       DATA_BLOB key;
+       DATA_BLOB val;
+
+       if (offset == END_OF_DIRECTORY_OFFSET) {
+               return WIRE_END_OF_DIRECTORY_OFFSET;
+       } else if(offset == START_OF_DIRECTORY_OFFSET) {
+               return WIRE_START_OF_DIRECTORY_OFFSET;
+       } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
+               return WIRE_DOT_DOT_DIRECTORY_OFFSET;
+       }
+       if (sizeof(long) == 4) {
+               /* 32-bit machine. We can cheat... */
+               return (uint32_t)offset;
+       }
+       if (dptr->dptr_cache == NULL) {
+               /* Lazy initialize cache. */
+               dptr->dptr_cache = memcache_init(dptr, 0);
+               if (dptr->dptr_cache == NULL) {
+                       return WIRE_END_OF_DIRECTORY_OFFSET;
+               }
+       } else {
+               /* Have we seen this offset before ? */
+               key.data = (void *)&offset;
+               key.length = sizeof(offset);
+               if (memcache_lookup(dptr->dptr_cache,
+                                       SMB1_SEARCH_OFFSET_MAP,
+                                       key,
+                                       &val)) {
+                       uint32_t wire_offset;
+                       SMB_ASSERT(val.length == sizeof(wire_offset));
+                       memcpy(&wire_offset, val.data, sizeof(wire_offset));
+                       DEBUG(10,("found wire %u <-> offset %ld\n",
+                               (unsigned int)wire_offset,
+                               (long)offset));
+                       return wire_offset;
+               }
+       }
+       /* Allocate a new wire cookie. */
+       do {
+               dptr->counter++;
+       } while (dptr->counter == WIRE_START_OF_DIRECTORY_OFFSET ||
+                dptr->counter == WIRE_END_OF_DIRECTORY_OFFSET ||
+                dptr->counter == WIRE_DOT_DOT_DIRECTORY_OFFSET);
+       /* Store it in the cache. */
+       key.data = (void *)&offset;
+       key.length = sizeof(offset);
+       val.data = (void *)&dptr->counter;
+       val.length = sizeof(dptr->counter); /* MUST BE uint32_t ! */
+       memcache_add(dptr->dptr_cache,
+                       SMB1_SEARCH_OFFSET_MAP,
+                       key,
+                       val);
+       /* And the reverse mapping for lookup from
+          map_wire_to_dir_offset(). */
+       memcache_add(dptr->dptr_cache,
+                       SMB1_SEARCH_OFFSET_MAP,
+                       val,
+                       key);
+       DEBUG(10,("stored wire %u <-> offset %ld\n",
+               (unsigned int)dptr->counter,
+               (long)offset));
+       return dptr->counter;
+}
+
+/****************************************************************************
  Fill the 5 byte server reserved dptr field.
 ****************************************************************************/
 
@@ -912,20 +992,62 @@ bool dptr_fill(struct smbd_server_connection *sconn,
 {
        unsigned char *buf = (unsigned char *)buf1;
        struct dptr_struct *dptr = dptr_get(sconn, key, false);
-       uint32 offset;
+       uint32_t wire_offset;
        if (!dptr) {
                DEBUG(1,("filling null dirptr %d\n",key));
                return(False);
        }
-       offset = (uint32)TellDir(dptr->dir_hnd);
+       wire_offset = map_dir_offset_to_wire(dptr,TellDir(dptr->dir_hnd));
        DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
-               (long)dptr->dir_hnd,(int)offset));
+               (long)dptr->dir_hnd,(int)wire_offset));
        buf[0] = key;
-       SIVAL(buf,1,offset);
+       SIVAL(buf,1,wire_offset);
        return(True);
 }
 
 /****************************************************************************
+ Map a 32-bit wire cookie to a native directory offset.
+****************************************************************************/
+
+static long map_wire_to_dir_offset(struct dptr_struct *dptr, uint32_t 
wire_offset)
+{
+       DATA_BLOB key;
+       DATA_BLOB val;
+
+       if (wire_offset == WIRE_END_OF_DIRECTORY_OFFSET) {
+               return END_OF_DIRECTORY_OFFSET;
+       } else if(wire_offset == WIRE_START_OF_DIRECTORY_OFFSET) {
+               return START_OF_DIRECTORY_OFFSET;
+       } else if (wire_offset == WIRE_DOT_DOT_DIRECTORY_OFFSET) {
+               return DOT_DOT_DIRECTORY_OFFSET;
+       }
+       if (sizeof(long) == 4) {
+               /* 32-bit machine. We can cheat... */
+               return (long)wire_offset;
+       }
+       if (dptr->dptr_cache == NULL) {
+               /* Logic error, cache should be initialized. */
+               return END_OF_DIRECTORY_OFFSET;
+       }
+       key.data = (void *)&wire_offset;
+       key.length = sizeof(wire_offset);
+       if (memcache_lookup(dptr->dptr_cache,
+                               SMB1_SEARCH_OFFSET_MAP,
+                               key,
+                               &val)) {
+               /* Found mapping. */
+               long offset;
+               SMB_ASSERT(val.length == sizeof(offset));
+               memcpy(&offset, val.data, sizeof(offset));
+               DEBUG(10,("lookup wire %u <-> offset %ld\n",
+                       (unsigned int)wire_offset,
+                       (long)offset));
+               return offset;
+       }
+       return END_OF_DIRECTORY_OFFSET;
+}
+
+/****************************************************************************
  Fetch the dir ptr and seek it given the 5 byte server field.
 ****************************************************************************/
 
@@ -934,7 +1056,7 @@ struct dptr_struct *dptr_fetch(struct 
smbd_server_connection *sconn,
 {
        unsigned int key = *(unsigned char *)buf;
        struct dptr_struct *dptr = dptr_get(sconn, key, false);
-       uint32 offset;
+       uint32_t wire_offset;
        long seekoff;
 
        if (!dptr) {
@@ -942,12 +1064,8 @@ struct dptr_struct *dptr_fetch(struct 
smbd_server_connection *sconn,
                return(NULL);
        }
        *num = key;
-       offset = IVAL(buf,1);
-       if (offset == (uint32)-1) {
-               seekoff = END_OF_DIRECTORY_OFFSET;
-       } else {
-               seekoff = (long)offset;
-       }
+       wire_offset = IVAL(buf,1);
+       seekoff = map_wire_to_dir_offset(dptr, wire_offset);
        SeekDir(dptr->dir_hnd,seekoff);
        DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
                key, dptr->path, (int)seekoff));


-- 
Samba Shared Repository

Reply via email to