summaryrefslogtreecommitdiff
path: root/source3/smbd/reply.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-07-17 21:09:02 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:38:11 -0500
commite1da1fcf12164f50f3462c90f0bb785d18c59b0b (patch)
tree8df81a6c947a609249d67188c3a5dbebbdee0984 /source3/smbd/reply.c
parent4c713703d046f756989e7eb901e884829825593c (diff)
downloadsamba-e1da1fcf12164f50f3462c90f0bb785d18c59b0b.tar.gz
samba-e1da1fcf12164f50f3462c90f0bb785d18c59b0b.tar.bz2
samba-e1da1fcf12164f50f3462c90f0bb785d18c59b0b.zip
r17098: Samba3 now cleanly passes Samba4 RAW-LOCK torture
test. Phew - that was painful :-). But what it means is that we now implement lock cancels and I can add lock cancels into POSIX lock handling which will fix the fast/slow system call issue with cifsfs ! Jeremy. (This used to be commit f1a9cf075b87c76c032d19da0168424c90f6cb3c)
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r--source3/smbd/reply.c123
1 files changed, 76 insertions, 47 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index ff3c6832e4..ec618db3f8 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2371,7 +2371,6 @@ 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);
@@ -2396,13 +2395,13 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
* Note that the requested lock size is unaffected by max_recv.
*/
- status = do_lock_spin(fsp,
- (uint32)SVAL(inbuf,smb_pid),
- (SMB_BIG_UINT)numtoread,
- (SMB_BIG_UINT)startpos,
- WRITE_LOCK,
- WINDOWS_LOCK,
- &my_lock_ctx);
+ status = do_lock(fsp,
+ (uint32)SVAL(inbuf,smb_pid),
+ (SMB_BIG_UINT)numtoread,
+ (SMB_BIG_UINT)startpos,
+ WRITE_LOCK,
+ WINDOWS_LOCK,
+ 0 /* zero timeout. */);
if (NT_STATUS_V(status)) {
#if 0
@@ -2412,7 +2411,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
* tester. JRA.
*/
- if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
+ if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
/*
* A blocking lock was requested. Package up
* this smb into a queued request and push it
@@ -3418,7 +3417,6 @@ 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);
@@ -3432,17 +3430,18 @@ int reply_lock(connection_struct *conn,
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
- status = do_lock_spin(fsp,
- (uint32)SVAL(inbuf,smb_pid),
- count,
- offset,
- WRITE_LOCK,
- WINDOWS_LOCK,
- &my_lock_ctx);
+ status = do_lock(fsp,
+ (uint32)SVAL(inbuf,smb_pid),
+ count,
+ offset,
+ WRITE_LOCK,
+ WINDOWS_LOCK,
+ 0 /* zero timeout. */);
+
if (NT_STATUS_V(status)) {
#if 0
/* Tests using Samba4 against W2K show this call never creates a blocking lock. */
- if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
+ if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
/*
* A blocking lock was requested. Package up
* this smb into a queued request and push it
@@ -5228,7 +5227,6 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
BOOL large_file_format =
(locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
BOOL err;
- BOOL my_lock_ctx = False;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
START_PROFILE(SMBlockingX);
@@ -5244,11 +5242,6 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
}
- 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.
*/
@@ -5360,7 +5353,11 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
/* Setup the timeout in seconds. */
- lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
+ if (lp_blocking_locks(SNUM(conn))) {
+ lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
+ } else {
+ lock_timeout = 0;
+ }
/* Now do any requested locks */
data += ((large_file_format ? 20 : 10)*num_ulocks);
@@ -5369,7 +5366,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
of smb_lkrng structs */
for(i = 0; i < (int)num_locks; i++) {
- enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK);
+ enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
+ READ_LOCK:WRITE_LOCK);
lock_pid = get_lock_pid( data, i, large_file_format);
count = get_lock_count( data, i, large_file_format);
offset = get_lock_offset( data, i, large_file_format, &err);
@@ -5387,31 +5385,54 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
(double)count, (unsigned int)lock_pid,
fsp->fsp_name, (int)lock_timeout ));
- status = do_lock_spin(fsp,
+ if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
+ if (lp_blocking_locks(SNUM(conn))) {
+
+ /* Schedule a message to ourselves to
+ remove the blocking lock record and
+ return the right error. */
+
+ if (!blocking_lock_cancel(fsp,
+ lock_pid,
+ offset,
+ count,
+ WINDOWS_LOCK,
+ locktype,
+ NT_STATUS_FILE_LOCK_CONFLICT)) {
+ END_PROFILE(SMBlockingX);
+ return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
+ }
+ }
+ /* Remove a matching pending lock. */
+ status = do_lock_cancel(fsp,
+ lock_pid,
+ count,
+ offset,
+ WINDOWS_LOCK);
+ } else {
+ status = do_lock(fsp,
lock_pid,
count,
offset,
lock_type,
WINDOWS_LOCK,
- &my_lock_ctx);
+ lock_timeout);
- if (NT_STATUS_V(status)) {
- /*
- * Interesting fact found by IFSTEST /t
- * LockOverlappedTest... Even if it's our own lock
- * context, we need to wait here as there may be an
- * unlock on the way. So I removed a "&&
- * !my_lock_ctx" from the following if statement. JRA.
- */
- if ((lock_timeout != 0) &&
- lp_blocking_locks(SNUM(conn)) &&
- ERROR_WAS_LOCK_DENIED(status)) {
+ if (NT_STATUS_V(status)) {
/*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
+ * Interesting fact found by IFSTEST /t
+ * LockOverlappedTest... Even if it's our own lock
+ * context, we need to wait here as there may be an
+ * unlock on the way. JRA.
*/
- if(push_blocking_lock_request(inbuf, length,
+ if ((lock_timeout != 0) &&
+ ERROR_WAS_LOCK_DENIED(status)) {
+ /*
+ * A blocking lock was requested. Package up
+ * this smb into a queued request and push it
+ * onto the blocking lock queue.
+ */
+ if(push_blocking_lock_request(inbuf, length,
fsp,
lock_timeout,
i,
@@ -5420,17 +5441,25 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
WINDOWS_LOCK,
offset,
count)) {
- END_PROFILE(SMBlockingX);
- return -1;
+ END_PROFILE(SMBlockingX);
+ return -1;
+ }
}
}
- break;
+ }
+
+ if (NT_STATUS_V(status)) {
+ END_PROFILE(SMBlockingX);
+ return ERROR_NT(status);
}
}
/* If any of the above locks failed, then we must unlock
all of the previous locks (X/Open spec). */
- if (i != num_locks && num_locks != 0) {
+
+ if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
+ (i != num_locks) &&
+ (num_locks != 0)) {
/*
* Ensure we don't do a remove on the lock that just failed,
* as under POSIX rules, if we have a lock already there, we