include/smb_macros.h: Don't round up an allocation if the size is zero.
authorJeremy Allison <jra@samba.org>
Wed, 13 Mar 2002 20:28:19 +0000 (20:28 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 13 Mar 2002 20:28:19 +0000 (20:28 +0000)
"One of these locks is not like the others... One of these locks is not
quite the same" :-). When is a zero timeout lock not zero ? When it's
being processed by Windows 2000 of course.. This code change, ugly though
it is - completely fixes the foxpro/access multi-user file system database
problems that people have been having. I used a *wonderful* test program
donated by "Gerald Drouillard" <gerald@drouillard.ca> which allowed me
to completely reproduce this problem, and to finally determine the correct
fix. This also explains why Windows 2000 is *so slow* when responding to
the smbtorture lock tests. I *love* it when all these things come together
and finally make sense :-).
Jeremy.

source/include/smb_macros.h
source/locking/locking.c
source/param/loadparm.c
source/smbd/blocking.c
source/smbd/reply.c

index 3fdd90f5109eda6c523d3383c071c1f47e4a6971..c19be784a1834455d815ed5ecb2dc8ccabedeb95 100644 (file)
 #define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,__LINE__,__FILE__)
 
 #define SMB_ROUNDUP(x,g) (((x)+((g)-1))&~((g)-1))
-#define SMB_ROUNDUP_ALLOCATION(s) (SMB_ROUNDUP((SMB_OFF_T)((s)+1), ((SMB_OFF_T)SMB_ROUNDUP_ALLOCATION_SIZE)))
+#define SMB_ROUNDUP_ALLOCATION(s) ((s) ? (SMB_ROUNDUP((SMB_OFF_T)((s)+1), ((SMB_OFF_T)SMB_ROUNDUP_ALLOCATION_SIZE))) : 0 )
 
 /* Extra macros added by Ying Chen at IBM - speed increase by inlining. */
 #define smb_buf(buf) (buf + smb_size + CVAL(buf,smb_wct)*2)
index dd6ca62e704ab7e038ec77aa0494caae9795f2f0..8f3e4a278e1712de945971f3b2c9d9644e640318 100644 (file)
@@ -97,7 +97,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn,
  Utility function called by locking requests.
 ****************************************************************************/
 
-NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
+static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
                 SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type)
 {
        NTSTATUS status;
@@ -141,6 +141,30 @@ NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
        return status;
 }
 
+/****************************************************************************
+ Utility function called by locking requests. This is *DISGISTING*. It also
+ appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000
+ is so slow on the locking tests...... ? This is the reason. Much though I hate
+ it, we need this. JRA.
+****************************************************************************/
+
+NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
+                SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type)
+{
+       int j, maxj = lp_lock_spin_count();
+       int sleeptime = lp_lock_sleep_time();
+       NTSTATUS status;
+
+       for (j = 0; j < maxj; j++) {
+               status = do_lock(fsp, conn, lock_pid, count, offset, lock_type);
+               if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) &&
+                               !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT))
+                       break;
+               usleep(sleeptime);
+       }
+       return status;
+}
+
 /****************************************************************************
  Utility function called by unlocking requests.
 ****************************************************************************/
index ec7d76802396a18e06e5e0331d68680a04849595..12dedc7a013529e662a15fea8732fd1c60676cbc 100644 (file)
@@ -198,6 +198,8 @@ typedef struct
        int min_passwd_length;
        int oplock_break_wait_time;
        int winbind_cache_time;
+       int iLockSpinCount;
+       int iLockSpinTime;
 #ifdef WITH_LDAP_SAM
        char *szLdapMachineSuffix;
        char *szLdapUserSuffix;
@@ -965,6 +967,8 @@ static struct parm_struct parm_table[] = {
        {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_SHARE},
        {"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_GLOBAL},
        {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
+       {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_GLOBAL},
+       {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_GLOBAL},
        
        {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
@@ -1319,6 +1323,8 @@ static void init_globals(void)
        Globals.min_passwd_length = MINPASSWDLENGTH;    /* By Default, 5. */
        Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
        Globals.enhanced_browsing = True; 
+       Globals.iLockSpinCount = 3; /* Try 2 times. */
+       Globals.iLockSpinTime = 10; /* usec. */
 #ifdef MMAP_BLACKLIST
        Globals.bUseMmap = False;
 #else
@@ -1659,6 +1665,8 @@ FN_GLOBAL_INTEGER(lp_stat_cache_size, &Globals.stat_cache_size)
 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
 FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length)
 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
+FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
+FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
 FN_LOCAL_STRING(lp_preexec, szPreExec)
 FN_LOCAL_STRING(lp_postexec, szPostExec)
 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
index bc8c54caf7cfafedd9d336ebd2fa43db8456923e..d4a53d9a6d9c7efa1b6fea4a6f84dd6bcea7b596 100644 (file)
@@ -279,7 +279,7 @@ static BOOL process_lockread(blocking_lock_record *blr)
        numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
        data = smb_buf(outbuf) + 3;
  
-       status = do_lock( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, 
+       status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, 
                          (SMB_BIG_UINT)startpos, READ_LOCK);
        if (NT_STATUS_V(status)) {
                if ((errno != EACCES) && (errno != EAGAIN)) {
@@ -345,7 +345,7 @@ static BOOL process_lock(blocking_lock_record *blr)
        offset = IVAL(inbuf,smb_vwv3);
 
        errno = 0;
-       status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, 
+       status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, 
                         (SMB_BIG_UINT)offset, WRITE_LOCK);
        if (NT_STATUS_IS_ERR(status)) {
                if((errno != EACCES) && (errno != EAGAIN)) {
@@ -417,7 +417,7 @@ static BOOL process_lockingX(blocking_lock_record *blr)
                 * request would never have been queued. JRA.
                 */
                errno = 0;
-               status = do_lock(fsp,conn,lock_pid,count,offset, 
+               status = do_lock_spin(fsp,conn,lock_pid,count,offset, 
                                 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
                if (NT_STATUS_IS_ERR(status)) break;
        }
index 9d5d34e410fa2bc04e5def92e08ba1ee0c373963..cbcad435d2cd4a11983eb14663d99079934df456 100644 (file)
@@ -1545,7 +1545,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
         * for a write lock. JRA.
         */
        
-       status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), 
+       status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), 
                         (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
 
        if (NT_STATUS_V(status)) {
@@ -2366,7 +2366,7 @@ int reply_lock(connection_struct *conn,
        DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
                 fsp->fd, fsp->fnum, (double)offset, (double)count));
 
-       status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
+       status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
        if (NT_STATUS_V(status)) {
                if (lp_blocking_locks(SNUM(conn))) {
                        /*
@@ -3808,6 +3808,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
        }
 
        /* Setup the timeout in seconds. */
+
        lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
        
        /* Now do any requested locks */
@@ -3829,10 +3830,11 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                        return ERROR_DOS(ERRDOS,ERRnoaccess);
                }
                
-               DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
-                         (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
+               DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
+                       (double)offset, (double)count, (unsigned int)lock_pid,
+                       (int)lock_timeout, fsp->fsp_name ));
                
-               status = do_lock(fsp,conn,lock_pid, count,offset, 
+               status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
                                 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
                if (NT_STATUS_V(status)) {
                        if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {