}
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;
}
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;
static int last_failed = -1;
static br_off last_failed_start;
+ *my_lock_ctx = False;
kbuf = locking_key(dev,ino);
dbuf.dptr = NULL;
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
****************************************************************************/
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;
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))) {
****************************************************************************/
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();
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;
/* 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);
{
static BOOL set_lock_msg;
blocking_lock_record *blr;
+ BOOL my_lock_ctx = False;
NTSTATUS status;
if(in_chained_smb() ) {
/* 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"));
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);
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)) {
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)) {
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);
*/
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;
}
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);
/* 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;
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 ) );
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);
* 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
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) {
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)) {
* 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);
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);
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);
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);
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
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);
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