r3050: Steal from Samba4 :-). Make us pass most of the new lock tests (except for
authorJeremy Allison <jra@samba.org>
Mon, 18 Oct 2004 22:01:10 +0000 (22:01 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:52:59 +0000 (10:52 -0500)
the cancel lock which I have to add).
Jeremy.
(This used to be commit cf7f89999e0c6becd4617c812400d1e71b9c0a30)

source3/include/smb.h
source3/locking/brlock.c
source3/smbd/files.c
source3/smbd/reply.c

index 7317fd16b0fb287391e38e53160b1b6a68ddc5e9..bc99a2a6fddf7aa0fd1511c8a2e87ea58b9f2768 100644 (file)
@@ -380,8 +380,7 @@ typedef struct
 
 #include "fake_file.h"
 
-typedef struct files_struct
-{
+typedef struct files_struct {
        struct files_struct *next, *prev;
        int fnum;
        struct connection_struct *conn;
index 4c34bd7dfd9cc1517d11047bf2f010b67b091d1b..61144eb59a9c801fafe516e0354694a598359a04 100644 (file)
@@ -91,6 +91,28 @@ static BOOL brl_same_context(struct lock_context *ctx1,
                (ctx1->tid == ctx2->tid);
 }
 
+/****************************************************************************
+ See if lck1 and lck2 overlap.
+****************************************************************************/
+
+static BOOL brl_overlap(struct lock_struct *lck1,
+                        struct lock_struct *lck2)
+{
+       /* this extra check is not redundent - it copes with locks
+          that go beyond the end of 64 bit file space */
+       if (lck1->size != 0 &&
+           lck1->start == lck2->start &&
+           lck1->size == lck2->size) {
+               return True;
+       }
+
+       if (lck1->start >= (lck2->start+lck2->size) ||
+           lck2->start >= (lck1->start+lck1->size)) {
+               return False;
+       }
+       return True;
+}
+
 /****************************************************************************
  See if lock2 can be added when lock1 is in place.
 ****************************************************************************/
@@ -115,7 +137,7 @@ static BOOL brl_conflict(struct lock_struct *lck1,
                return False;
        }
            
-       return True;
+       return brl_overlap(lck1, lck2);
 } 
 
 #if ZERO_ZERO
@@ -175,9 +197,36 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck
            lck2->start >= (lck1->start + lck1->size))
                return False;
            
-       return True;
+       return brl_overlap(lck1, lck2);
 } 
 
+/****************************************************************************
+ Amazingly enough, w2k3 "remembers" whether the last lock failure
+ is the same as this one and changes its error code. I wonder if any
+ app depends on this ?
+****************************************************************************/
+
+static NTSTATUS brl_lock_failed(struct lock_struct *lock)
+{
+       static struct lock_struct last_lock_failure;
+
+       if (brl_same_context(&lock->context, &last_lock_failure.context) &&
+                       lock->fnum == last_lock_failure.fnum &&
+                       lock->start == last_lock_failure.start &&
+                       lock->size == last_lock_failure.size) {
+               return NT_STATUS_FILE_LOCK_CONFLICT;
+       }
+       last_lock_failure = *lock;
+       if (lock->start >= 0xEF000000 &&
+                       (lock->start >> 63) == 0) {
+               /* amazing the little things you learn with a test
+                  suite. Locks beyond this offset (as a 64 bit
+                  number!) always generate the conflict error code,
+                  unless the top bit is set */
+               return NT_STATUS_FILE_LOCK_CONFLICT;
+       }
+       return NT_STATUS_LOCK_NOT_GRANTED;
+}
 
 #if DONT_DO_THIS
        /* doing this traversal could kill solaris machines under high load (tridge) */
@@ -313,8 +362,6 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
        struct lock_struct lock, *locks;
        char *tp;
        NTSTATUS status = NT_STATUS_OK;
-       static int last_failed = -1;
-       static br_off last_failed_start;
 
        *my_lock_ctx = False;
        kbuf = locking_key(dev,ino);
@@ -344,7 +391,7 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
                count = dbuf.dsize / sizeof(*locks);
                for (i=0; i<count; i++) {
                        if (brl_conflict(&locks[i], &lock)) {
-                               status = NT_STATUS_LOCK_NOT_GRANTED;
+                               status = brl_lock_failed(&lock);;
                                /* Did we block ourselves ? */
                                if (brl_same_context(&locks[i].context, &lock.context))
                                        *my_lock_ctx = True;
@@ -375,24 +422,16 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
        qsort(dbuf.dptr, dbuf.dsize/sizeof(lock), sizeof(lock), lock_compare);
 #endif
 
-       tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
+       if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto fail;
+       }
 
        SAFE_FREE(dbuf.dptr);
        tdb_chainunlock(tdb, kbuf);
        return NT_STATUS_OK;
 
  fail:
-       /* this is a nasty hack to try to simulate the lock result cache code in w2k.
-          It isn't completely accurate as I haven't yet worked out the correct
-          semantics (tridge)
-       */
-       if (last_failed == fnum &&
-           last_failed_start == start &&
-           NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
-               status = NT_STATUS_FILE_LOCK_CONFLICT;
-       }
-       last_failed = fnum;
-       last_failed_start = start;
 
        SAFE_FREE(dbuf.dptr);
        tdb_chainunlock(tdb, kbuf);
index 80544c9a3095261b6d8113f98d5b68a8af0ce1bd..580dc545452ad759b100fe604f9c539c4599faa0 100644 (file)
@@ -289,12 +289,12 @@ files_struct *file_find_fsp(files_struct *orig_fsp)
 {
        files_struct *fsp;
 
-    for (fsp=Files;fsp;fsp=fsp->next) {
-        if (fsp == orig_fsp)
-            return fsp;
-    }
+       for (fsp=Files;fsp;fsp=fsp->next) {
+               if (fsp == orig_fsp)
+                       return fsp;
+       }
 
-    return NULL;
+       return NULL;
 }
 
 /****************************************************************************
@@ -303,16 +303,16 @@ files_struct *file_find_fsp(files_struct *orig_fsp)
 
 files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
 {
-    files_struct *fsp;
+       files_struct *fsp;
 
-    for (fsp=Files;fsp;fsp=fsp->next) {
-        if ( fsp->fd != -1 &&
-            fsp->dev == dev &&
-            fsp->inode == inode )
-            return fsp;
-    }
+       for (fsp=Files;fsp;fsp=fsp->next) {
+               if ( fsp->fd != -1 &&
+                               fsp->dev == dev &&
+                               fsp->inode == inode )
+                       return fsp;
+       }
 
-    return NULL;
+       return NULL;
 }
 
 /****************************************************************************
@@ -321,16 +321,16 @@ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
 
 files_struct *file_find_di_next(files_struct *start_fsp)
 {
-    files_struct *fsp;
+       files_struct *fsp;
 
-    for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
-        if ( fsp->fd != -1 &&
-            fsp->dev == start_fsp->dev &&
-            fsp->inode == start_fsp->inode )
-            return fsp;
-    }
+       for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
+               if ( fsp->fd != -1 &&
+                               fsp->dev == start_fsp->dev &&
+                               fsp->inode == start_fsp->inode )
+                       return fsp;
+       }
 
-    return NULL;
+       return NULL;
 }
 
 /****************************************************************************
@@ -388,7 +388,9 @@ void file_free(files_struct *fsp)
           information */
        ZERO_STRUCTP(fsp);
 
-       if (fsp == chain_fsp) chain_fsp = NULL;
+       if (fsp == chain_fsp) {
+               chain_fsp = NULL;
+       }
 
        SAFE_FREE(fsp);
 }
index cdf607e27384d4dbc125dfe4f984afe3a6a2e2ec..845f05886700ba8279138cdb50c30a71228872a7 100644 (file)
@@ -4514,13 +4514,18 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
        
        data = smb_buf(inbuf);
 
-       if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
+       if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
                /* we don't support these - and CANCEL_LOCK makes w2k
                   and XP reboot so I don't really want to be
                   compatible! (tridge) */
                return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
        }
        
+       if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
+               /* Need to make this like a cancel.... JRA. */
+               return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+       }
+       
        /* Check if this is an oplock break on a file
           we have granted an oplock on.
        */