Changes to allow Samba3 to pass the Samba4 RAW-READ tests.
authorJeremy Allison <jra@samba.org>
Thu, 9 Oct 2003 01:46:01 +0000 (01:46 +0000)
committerJeremy Allison <jra@samba.org>
Thu, 9 Oct 2003 01:46:01 +0000 (01:46 +0000)
Jeremy.
(This used to be commit e7565dbba696adbb0fd8cca6b86a1a7e5a655f2e)

source3/locking/brlock.c
source3/locking/locking.c
source3/smbd/blocking.c
source3/smbd/reply.c

index 20d76c9c7926eec9079d075fb2f725e67a40d92d..c51a5a2aac9285b43999fe5c3d6b05476ca7e04f 100644 (file)
@@ -172,7 +172,8 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck
        }
 
        if (lck1->start >= (lck2->start + lck2->size) ||
-           lck2->start >= (lck1->start + lck1->size)) return False;
+           lck2->start >= (lck1->start + lck1->size))
+               return False;
            
        return True;
 } 
@@ -305,7 +306,7 @@ static int lock_compare(struct lock_struct *lck1,
 NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
                  uint16 smbpid, pid_t pid, uint16 tid,
                  br_off start, br_off size, 
-                 enum brl_type lock_type)
+                 enum brl_type lock_type, BOOL *my_lock_ctx)
 {
        TDB_DATA kbuf, dbuf;
        int count, i;
@@ -315,6 +316,7 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
        static int last_failed = -1;
        static br_off last_failed_start;
 
+       *my_lock_ctx = False;
        kbuf = locking_key(dev,ino);
 
        dbuf.dptr = NULL;
@@ -343,6 +345,9 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
                for (i=0; i<count; i++) {
                        if (brl_conflict(&locks[i], &lock)) {
                                status = NT_STATUS_LOCK_NOT_GRANTED;
+                               /* Did we block ourselves ? */
+                               if (brl_same_context(&locks[i].context, &lock.context))
+                                       *my_lock_ctx = True;
                                goto fail;
                        }
 #if ZERO_ZERO
index 91bc20af90f1d8db43e9a4c66cabd4a28873048c..c3abd6381825b84e3213b87d5fe085a8eb18455d 100644 (file)
@@ -98,7 +98,7 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn,
 ****************************************************************************/
 
 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)
+                SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx)
 {
        NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
 
@@ -114,7 +114,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p
                status = brl_lock(fsp->dev, fsp->inode, fsp->fnum,
                                  lock_pid, sys_getpid(), conn->cnum, 
                                  offset, count, 
-                                 lock_type);
+                                 lock_type, my_lock_ctx);
 
                if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) {
 
@@ -153,7 +153,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p
 ****************************************************************************/
 
 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)
+                SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx)
 {
        int j, maxj = lp_lock_spin_count();
        int sleeptime = lp_lock_sleep_time();
@@ -165,7 +165,7 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid
        ret = NT_STATUS_OK; /* to keep dumb compilers happy */
 
        for (j = 0; j < maxj; j++) {
-               status = do_lock(fsp, conn, lock_pid, count, offset, lock_type);
+               status = do_lock(fsp, conn, lock_pid, count, offset, lock_type, my_lock_ctx);
                if (!NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED) &&
                    !NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
                        return status;
@@ -173,6 +173,9 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid
                /* if we do fail then return the first error code we got */
                if (j == 0) {
                        ret = status;
+                       /* Don't spin if we blocked ourselves. */
+                       if (*my_lock_ctx)
+                               return ret;
                }
                if (sleeptime)
                        sys_usleep(sleeptime);
index 8fa2a6494e3cd2ce8022be02f77c13822ac10e21..5c6ddbc6b7ef2cfb7f35341b1b9c4aedeaad8566 100644 (file)
@@ -91,6 +91,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
 {
        static BOOL set_lock_msg;
        blocking_lock_record *blr;
+       BOOL my_lock_ctx = False;
        NTSTATUS status;
 
        if(in_chained_smb() ) {
@@ -127,7 +128,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
        /* Add a pending lock record for this. */
        status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
                        lock_pid, sys_getpid(), blr->fsp->conn->cnum,
-                       offset, count, PENDING_LOCK);
+                       offset, count, PENDING_LOCK, &my_lock_ctx);
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
@@ -302,6 +303,7 @@ static BOOL process_lockread(blocking_lock_record *blr)
        NTSTATUS status;
        connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
        files_struct *fsp = blr->fsp;
+       BOOL my_lock_ctx = False;
 
        numtoread = SVAL(inbuf,smb_vwv1);
        startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2);
@@ -309,8 +311,7 @@ static BOOL process_lockread(blocking_lock_record *blr)
        numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
        data = smb_buf(outbuf) + 3;
  
-       status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, 
-                         startpos, READ_LOCK);
+       status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, &my_lock_ctx);
        if (NT_STATUS_V(status)) {
                if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
                        !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
@@ -371,13 +372,13 @@ static BOOL process_lock(blocking_lock_record *blr)
        NTSTATUS status;
        connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
        files_struct *fsp = blr->fsp;
+       BOOL my_lock_ctx = False;
 
        count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
        offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
 
        errno = 0;
-       status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, 
-                        offset, WRITE_LOCK);
+       status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
        if (NT_STATUS_IS_ERR(status)) {
                if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
                        !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
@@ -428,6 +429,7 @@ static BOOL process_lockingX(blocking_lock_record *blr)
        uint16 lock_pid;
        BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
        char *data;
+       BOOL my_lock_ctx = False;
        NTSTATUS status = NT_STATUS_OK;
 
        data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks);
@@ -450,7 +452,7 @@ static BOOL process_lockingX(blocking_lock_record *blr)
                 */
                errno = 0;
                status = do_lock_spin(fsp,conn,lock_pid,count,offset, 
-                                ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
+                                ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
                if (NT_STATUS_IS_ERR(status)) break;
        }
 
index 2c8b768d70ffd38ed04d19419b3170d25c751751..5c1d7915c26cc73f92b8f16960a1578dddcd0b0f 100644 (file)
@@ -1567,8 +1567,13 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
 
        if (nread > 0) {
                ret = read_file(fsp,outbuf+4,startpos,nread);
+#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
                if (ret < mincount)
                        ret = 0;
+#else
+               if (ret < nread)
+                       ret = 0;
+#endif
        }
 
        _smb_setlen(outbuf,ret);
@@ -1668,7 +1673,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
 
        /* ensure we don't overrun the packet size */
        maxcount = MIN(65535,maxcount);
-       maxcount = MAX(mincount,maxcount);
 
        if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
                SMB_OFF_T size = fsp->size;
@@ -1688,8 +1692,10 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
                        nread = MIN(maxcount,(size - startpos));          
        }
 
+#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
        if (nread < mincount)
                nread = 0;
+#endif
   
        DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
                                (int)maxcount, (int)mincount, (int)nread ) );
@@ -1714,6 +1720,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
        size_t numtoread;
        NTSTATUS status;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+       BOOL my_lock_ctx = False;
        START_PROFILE(SMBlockread);
 
        CHECK_FSP(fsp,conn);
@@ -1733,13 +1740,21 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
         * protocol request that predates the read/write lock concept. 
         * Thus instead of asking for a read lock here we need to ask
         * for a write lock. JRA.
+        * Note that the requested lock size is unaffected by max_recv.
         */
        
        status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), 
-                        (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
+                        (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
 
        if (NT_STATUS_V(status)) {
-               if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
+#if 0
+               /*
+                * We used to make lockread a blocking lock. It turns out
+                * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
+                * tester. JRA.
+                */
+
+               if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
                        /*
                         * A blocking lock was requested. Package up
                         * this smb into a queued request and push it
@@ -1751,10 +1766,16 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
                                return -1;
                        }
                }
+#endif
                END_PROFILE(SMBlockread);
                return ERROR_NT(status);
        }
 
+       /*
+        * However the requested READ size IS affected by max_recv. Insanity.... JRA.
+        */
+
+       numtoread = MIN(numtoread,max_recv);
        nread = read_file(fsp,data,startpos,numtoread);
 
        if (nread < 0) {
@@ -1796,6 +1817,11 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int
 
        outsize = set_message(outbuf,5,3,True);
        numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
+       /*
+        * The requested read size cannot be greater than max_recv. JRA.
+        */
+       numtoread = MIN(numtoread,max_recv);
+
        data = smb_buf(outbuf) + 3;
   
        if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
@@ -1863,6 +1889,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
                 * correct amount of data).
                 */
 
+               SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
                SSVAL(outbuf,smb_vwv5,smb_maxcnt);
                SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
                SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
@@ -1901,6 +1928,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
                return(UNIXERROR(ERRDOS,ERRnoaccess));
        }
 
+       SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
        SSVAL(outbuf,smb_vwv5,nread);
        SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
        SSVAL(smb_buf(outbuf),-2,nread);
@@ -1993,7 +2021,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        START_PROFILE(SMBwritebraw);
 
        if (srv_is_signing_active()) {
-               exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
+               exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
        }
 
        CHECK_FSP(fsp,conn);
@@ -2626,6 +2654,8 @@ int reply_lock(connection_struct *conn,
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+       BOOL my_lock_ctx = False;
+
        START_PROFILE(SMBlock);
 
        CHECK_FSP(fsp,conn);
@@ -2638,9 +2668,9 @@ 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_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
+       status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
        if (NT_STATUS_V(status)) {
-               if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
+               if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
                        /*
                         * A blocking lock was requested. Package up
                         * this smb into a queued request and push it
@@ -4140,6 +4170,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
        char *data;
        BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
        BOOL err;
+       BOOL my_lock_ctx = False;
        NTSTATUS status;
 
        START_PROFILE(SMBlockingX);
@@ -4260,9 +4291,9 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                        fsp->fsp_name, (int)lock_timeout ));
                
                status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
-                                ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
+                                ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
                if (NT_STATUS_V(status)) {
-                       if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
+                       if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
                                /*
                                 * A blocking lock was requested. Package up
                                 * this smb into a queued request and push it