#include "debugparse.h"
#include "version.h"
#include "privileges.h"
+#include "locking.h"
#include "smb.h"
#include "ads_cldap.h"
#include "nameserv.h"
SMB_INO_T inode;
};
+struct files_struct;
+
struct byte_range_lock {
- files_struct *fsp;
+ struct files_struct *fsp;
unsigned int num_locks;
BOOL modified;
struct lock_key key;
#define MSG_SMB_KERNEL_BREAK 3010
#define MSG_SMB_FILE_RENAME 3011
#define MSG_SMB_INJECT_FAULT 3012
+#define MSG_SMB_BLOCKING_LOCK_CANCEL 3013
/* winbind messages */
#define MSG_WINBIND_FINISHED 4001
int oplock_type;
int sent_oplock_break;
struct timed_event *oplock_timeout;
+ struct lock_struct last_lock_failure;
struct share_mode_entry *pending_break_messages;
int num_pending_break_messages;
#define FLAG_HIDE 0x2000 /* options that should be hidden in SWAT */
#define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */
-#include "locking.h"
-
struct bitmap {
uint32 *b;
unsigned int n;
{
return False;
}
+
+void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck)
+{
+}
}
/****************************************************************************
- Amazingly enough, w2k3 "remembers" whether the last lock failure
+ Amazingly enough, w2k3 "remembers" whether the last lock failure on a fnum
is the same as this one and changes its error code. I wonder if any
app depends on this ?
****************************************************************************/
-static NTSTATUS brl_lock_failed(const struct lock_struct *lock)
+static NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, int32 lock_timeout)
{
- 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) {
+ 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 */
+ if (lock_timeout == 0) {
+ fsp->last_lock_failure = *lock;
+ }
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ }
+
+ if (procid_equal(&lock->context.pid, &fsp->last_lock_failure.context.pid) &&
+ lock->context.tid == fsp->last_lock_failure.context.tid &&
+ lock->fnum == fsp->last_lock_failure.fnum &&
+ lock->start == fsp->last_lock_failure.start) {
return NT_STATUS_FILE_LOCK_CONFLICT;
}
+
+ if (lock_timeout == 0) {
+ fsp->last_lock_failure = *lock;
+ }
return NT_STATUS_LOCK_NOT_GRANTED;
}
****************************************************************************/
static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
- const struct lock_struct *plock,
- BOOL *my_lock_ctx)
+ const struct lock_struct *plock, int32 lock_timeout)
{
unsigned int i;
files_struct *fsp = br_lck->fsp;
for (i=0; i < br_lck->num_locks; i++) {
/* Do any Windows or POSIX locks conflict ? */
if (brl_conflict(&locks[i], plock)) {
- NTSTATUS status = brl_lock_failed(plock);;
- /* Did we block ourselves ? */
- if (brl_same_context(&locks[i].context, &plock->context)) {
- *my_lock_ctx = True;
- }
- return status;
+ return brl_lock_failed(fsp,plock,lock_timeout);
}
#if ZERO_ZERO
if (plock->start == 0 && plock->size == 0 &&
****************************************************************************/
static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
- const struct lock_struct *plock,
- BOOL *my_lock_ctx)
+ const struct lock_struct *plock)
{
unsigned int i, count;
struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
if (locks[i].lock_flav == WINDOWS_LOCK) {
/* Do any Windows flavour locks conflict ? */
if (brl_conflict(&locks[i], plock)) {
- /* Did we block ourselves ? */
- if (brl_same_context(&locks[i].context, &plock->context)) {
- *my_lock_ctx = True;
- }
/* No games with error messages. */
SAFE_FREE(tp);
return NT_STATUS_FILE_LOCK_CONFLICT;
br_off size,
enum brl_type lock_type,
enum brl_flavour lock_flav,
- BOOL *my_lock_ctx)
+ int32 lock_timeout)
{
NTSTATUS ret;
struct lock_struct lock;
- *my_lock_ctx = False;
-
#if !ZERO_ZERO
if (start == 0 && size == 0) {
DEBUG(0,("client sent 0/0 lock - please report this\n"));
lock.lock_flav = lock_flav;
if (lock_flav == WINDOWS_LOCK) {
- ret = brl_lock_windows(br_lck, &lock, my_lock_ctx);
+ ret = brl_lock_windows(br_lck, &lock, lock_timeout);
} else {
- ret = brl_lock_posix(br_lck, &lock, my_lock_ctx);
+ ret = brl_lock_posix(br_lck, &lock);
}
#if ZERO_ZERO
Remove a particular pending lock.
****************************************************************************/
-BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck,
+BOOL brl_lock_cancel(struct byte_range_lock *br_lck,
uint32 smbpid,
struct process_id pid,
br_off start,
SMB_BIG_UINT offset,
enum brl_type lock_type,
enum brl_flavour lock_flav,
- BOOL *my_lock_ctx)
+ int32 lock_timeout)
{
struct byte_range_lock *br_lck = NULL;
NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
count,
lock_type,
lock_flav,
- my_lock_ctx);
+ lock_timeout);
TALLOC_FREE(br_lck);
return status;
}
/****************************************************************************
- Utility function called by locking requests. This is *DISGUSTING*. 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.
+ Utility function called by unlocking requests.
****************************************************************************/
-NTSTATUS do_lock_spin(files_struct *fsp,
+NTSTATUS do_unlock(files_struct *fsp,
uint32 lock_pid,
SMB_BIG_UINT count,
SMB_BIG_UINT offset,
- enum brl_type lock_type,
- enum brl_flavour lock_flav,
- BOOL *my_lock_ctx)
+ enum brl_flavour lock_flav)
{
- int j, maxj = lp_lock_spin_count();
- int sleeptime = lp_lock_sleep_time();
- NTSTATUS status, ret;
-
- if (maxj <= 0) {
- maxj = 1;
+ BOOL ok = False;
+ struct byte_range_lock *br_lck = NULL;
+
+ if (!fsp->can_lock) {
+ return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
}
+
+ if (!lp_locking(SNUM(fsp->conn))) {
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
+ (double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
- ret = NT_STATUS_OK; /* to keep dumb compilers happy */
-
- for (j = 0; j < maxj; j++) {
- status = do_lock(fsp,
- lock_pid,
- count,
- offset,
- lock_type,
- lock_flav,
- 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;
- }
+ br_lck = brl_get_locks(NULL, fsp);
+ if (!br_lck) {
+ return NT_STATUS_NO_MEMORY;
+ }
- /* Only spin for Windows locks. */
- if (lock_flav == POSIX_LOCK) {
- return ret;
- }
- }
+ ok = brl_unlock(br_lck,
+ lock_pid,
+ procid_self(),
+ offset,
+ count,
+ lock_flav);
+
+ TALLOC_FREE(br_lck);
- if (sleeptime) {
- sys_usleep(sleeptime);
- }
+ if (!ok) {
+ DEBUG(10,("do_unlock: returning ERRlock.\n" ));
+ return NT_STATUS_RANGE_NOT_LOCKED;
}
- return ret;
+
+ return NT_STATUS_OK;
}
/****************************************************************************
- Utility function called by unlocking requests.
+ Cancel any pending blocked locks.
****************************************************************************/
-NTSTATUS do_unlock(files_struct *fsp,
+NTSTATUS do_lock_cancel(files_struct *fsp,
uint32 lock_pid,
SMB_BIG_UINT count,
SMB_BIG_UINT offset,
struct byte_range_lock *br_lck = NULL;
if (!fsp->can_lock) {
- return fsp->is_directory ? NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
+ return fsp->is_directory ?
+ NT_STATUS_INVALID_DEVICE_REQUEST : NT_STATUS_INVALID_HANDLE;
}
if (!lp_locking(SNUM(fsp->conn))) {
- return NT_STATUS_OK;
+ return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
-
- DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n",
+
+ DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n",
(double)offset, (double)count, fsp->fnum, fsp->fsp_name ));
br_lck = brl_get_locks(NULL, fsp);
return NT_STATUS_NO_MEMORY;
}
- ok = brl_unlock(br_lck,
+ ok = brl_lock_cancel(br_lck,
lock_pid,
procid_self(),
offset,
TALLOC_FREE(br_lck);
if (!ok) {
- DEBUG(10,("do_unlock: returning ERRlock.\n" ));
- return NT_STATUS_RANGE_NOT_LOCKED;
+ DEBUG(10,("do_lock_cancel: returning ERRcancelviolation.\n" ));
+ return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
}
return NT_STATUS_OK;
}
br_lck = brl_get_locks(NULL,fsp);
+
if (br_lck) {
+ cancel_pending_lock_requests_by_fid(fsp, br_lck);
brl_close_fnum(br_lck);
TALLOC_FREE(br_lck);
}
*/
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
/****************************************************************************
This is the structure to queue to implement blocking locks.
int length;
} blocking_lock_record;
+/* dlink list we store pending lock records on. */
static blocking_lock_record *blocking_lock_queue;
+/* dlink list we move cancelled lock records onto. */
+static blocking_lock_record *blocking_lock_cancelled_queue;
+
/****************************************************************************
Destructor for the above structure.
****************************************************************************/
static void free_blocking_lock_record(blocking_lock_record *blr)
{
- DLIST_REMOVE(blocking_lock_queue, blr);
SAFE_FREE(blr->inbuf);
SAFE_FREE(blr);
}
{
static BOOL set_lock_msg;
blocking_lock_record *blr, *tmp;
- BOOL my_lock_ctx = False;
struct byte_range_lock *br_lck = NULL;
NTSTATUS status;
br_lck = brl_get_locks(NULL, blr->fsp);
if (!br_lck) {
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
return False;
}
count,
PENDING_LOCK,
blr->lock_flav,
- &my_lock_ctx);
+ lock_timeout);
TALLOC_FREE(br_lck);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
return False;
}
status = NT_STATUS_FILE_LOCK_CONFLICT;
}
+ if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
+ /* Store the last lock error. */
+ files_struct *fsp = blr->fsp;
+
+ fsp->last_lock_failure.context.smbpid = blr->lock_pid;
+ fsp->last_lock_failure.context.tid = fsp->conn->cnum;
+ fsp->last_lock_failure.context.pid = procid_self();
+ fsp->last_lock_failure.start = blr->offset;
+ fsp->last_lock_failure.size = blr->count;
+ fsp->last_lock_failure.fnum = fsp->fnum;
+ fsp->last_lock_failure.lock_type = READ_LOCK; /* Don't care. */
+ fsp->last_lock_failure.lock_flav = blr->lock_flav;
+ }
+
ERROR_NT(status);
- if (!send_smb(smbd_server_fd(),outbuf))
+ if (!send_smb(smbd_server_fd(),outbuf)) {
exit_server("generic_blocking_lock_error: send_smb failed.");
+ }
}
/****************************************************************************
size_t numtoread;
NTSTATUS status;
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,
- (uint32)SVAL(inbuf,smb_pid),
- (SMB_BIG_UINT)numtoread,
- startpos,
- READ_LOCK,
- WINDOWS_LOCK,
- &my_lock_ctx);
+ status = do_lock(fsp,
+ (uint32)SVAL(inbuf,smb_pid),
+ (SMB_BIG_UINT)numtoread,
+ startpos,
+ READ_LOCK,
+ WINDOWS_LOCK,
+ (int32)-1);
if (NT_STATUS_V(status)) {
if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
NTSTATUS status;
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,
- (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,
+ (int32)-1);
if (NT_STATUS_IS_ERR(status)) {
if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
uint32 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);
* request would never have been queued. JRA.
*/
errno = 0;
- status = do_lock_spin(fsp,
+ status = do_lock(fsp,
lock_pid,
count,
offset,
- ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
+ ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
+ READ_LOCK : WRITE_LOCK),
WINDOWS_LOCK,
- &my_lock_ctx);
+ (int32)-1);
if (NT_STATUS_IS_ERR(status)) {
break;
extern int max_send;
char *inbuf = blr->inbuf;
char *outbuf;
- BOOL my_lock_ctx = False;
char params[2];
NTSTATUS status;
blr->offset,
blr->lock_type,
blr->lock_flav,
- &my_lock_ctx);
+ (int32)-1);
if (!NT_STATUS_IS_OK(status)) {
if (ERROR_WAS_LOCK_DENIED(status)) {
}
/****************************************************************************
- Delete entries by fnum from the blocking lock pending queue.
+ Cancel entries by fnum from the blocking lock pending queue.
*****************************************************************************/
-void remove_pending_lock_requests_by_fid(files_struct *fsp)
+void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lock *br_lck)
{
blocking_lock_record *blr, *next = NULL;
for(blr = blocking_lock_queue; blr; blr = next) {
next = blr->next;
if(blr->fsp->fnum == fsp->fnum) {
- struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
+ unsigned char locktype = 0;
+
+ if (blr->com_type == SMBlockingX) {
+ locktype = CVAL(blr->inbuf,smb_vwv3);
+ }
if (br_lck) {
DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \
file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
blr->count,
blr->lock_flav);
- TALLOC_FREE(br_lck);
+ blocking_lock_cancel(fsp,
+ blr->lock_pid,
+ blr->offset,
+ blr->count,
+ blr->lock_flav,
+ locktype,
+ NT_STATUS_RANGE_NOT_LOCKED);
}
-
- free_blocking_lock_record(blr);
}
}
}
DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \
file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
}
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
}
}
DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
fsp->fnum, fsp->fsp_name ));
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
}
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
continue;
}
*/
if (br_lck) {
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
vuid ));
blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
continue;
}
*/
if (br_lck) {
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
change_to_root_user();
continue;
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
if (br_lck) {
- brl_remove_pending_lock(br_lck,
+ brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
blr->offset,
TALLOC_FREE(br_lck);
}
+ DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
}
change_to_root_user();
}
}
+
+/****************************************************************************
+ Handle a cancel message. Lock already moved onto the cancel queue.
+*****************************************************************************/
+
+#define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(blocking_lock_record *) + sizeof(NTSTATUS))
+
+static void process_blocking_lock_cancel_message(int msg_type, struct process_id src,
+ void *buf, size_t len)
+{
+ NTSTATUS err;
+ const char *msg = (const char *)buf;
+ blocking_lock_record *blr;
+
+ if (buf == NULL) {
+ smb_panic("process_blocking_lock_cancel_message: null msg\n");
+ }
+
+ if (len != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
+ DEBUG(0, ("process_blocking_lock_cancel_message: "
+ "Got invalid msg len %d\n", (int)len));
+ smb_panic("process_blocking_lock_cancel_message: bad msg\n");
+ }
+
+ memcpy(&blr, msg, sizeof(blr));
+ memcpy(&err, &msg[sizeof(blr)], sizeof(NTSTATUS));
+
+ DEBUG(10,("process_blocking_lock_cancel_message: returning error %s\n",
+ nt_errstr(err) ));
+
+ blocking_lock_reply_error(blr, err);
+ DLIST_REMOVE(blocking_lock_cancelled_queue, blr);
+ free_blocking_lock_record(blr);
+}
+
+/****************************************************************************
+ Send ourselves a blocking lock cancelled message. Handled asynchronously above.
+*****************************************************************************/
+
+BOOL blocking_lock_cancel(files_struct *fsp,
+ uint32 lock_pid,
+ SMB_BIG_UINT offset,
+ SMB_BIG_UINT count,
+ enum brl_flavour lock_flav,
+ unsigned char locktype,
+ NTSTATUS err)
+{
+ static BOOL initialized;
+ char msg[MSG_BLOCKING_LOCK_CANCEL_SIZE];
+ blocking_lock_record *blr;
+
+ if (!initialized) {
+ /* Register our message. */
+ message_register(MSG_SMB_BLOCKING_LOCK_CANCEL,
+ process_blocking_lock_cancel_message);
+
+ initialized = True;
+ }
+
+ for (blr = blocking_lock_queue; blr; blr = blr->next) {
+ if (fsp == blr->fsp &&
+ lock_pid == blr->lock_pid &&
+ offset == blr->offset &&
+ count == blr->count &&
+ lock_flav == blr->lock_flav) {
+ break;
+ }
+ }
+
+ if (!blr) {
+ return False;
+ }
+
+ /* Check the flags are right. */
+ if (blr->com_type == SMBlockingX &&
+ (locktype & LOCKING_ANDX_LARGE_FILES) !=
+ (CVAL(blr->inbuf,smb_vwv3) & LOCKING_ANDX_LARGE_FILES)) {
+ return False;
+ }
+
+ /* Move to cancelled queue. */
+ DLIST_REMOVE(blocking_lock_queue, blr);
+ DLIST_ADD(blocking_lock_cancelled_queue, blr);
+
+ /* Create the message. */
+ memcpy(msg, &blr, sizeof(blr));
+ memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
+
+ /* Don't need to be root here as we're only ever
+ sending to ourselves. */
+
+ message_send_pid(pid_to_procid(sys_getpid()),
+ MSG_SMB_BLOCKING_LOCK_CANCEL,
+ &msg, sizeof(msg), True);
+
+ return True;
+}
int err = 0;
int err1 = 0;
- remove_pending_lock_requests_by_fid(fsp);
-
if (fsp->aio_write_behind) {
/*
* If we're finishing write behind on a close we can get a write
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);
* 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
* 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
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- BOOL my_lock_ctx = False;
START_PROFILE(SMBlock);
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
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);
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.
*/
/* 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);
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);
(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,
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
uint32 lock_pid;
BOOL lock_blocking;
enum brl_type lock_type;
- BOOL my_lock_ctx;
if (fsp == NULL || fsp->fh->fd == -1) {
return ERROR_NT(NT_STATUS_INVALID_HANDLE);
count,
offset,
lock_type,
- POSIX_LOCK,
- &my_lock_ctx);
+ POSIX_LOCK);
if (lock_blocking && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
/*