summaryrefslogtreecommitdiff
path: root/source3/locking
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/locking
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/locking')
-rw-r--r--source3/locking/brlock.c57
-rw-r--r--source3/locking/locking.c102
2 files changed, 70 insertions, 89 deletions
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index 9edac7203b..f251ff57ec 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -211,30 +211,34 @@ static BOOL brl_conflict_other(const struct lock_struct *lck1, const struct lock
}
/****************************************************************************
- 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;
}
@@ -293,8 +297,7 @@ static int lock_compare(const struct lock_struct *lck1,
****************************************************************************/
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;
@@ -303,12 +306,7 @@ static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
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 &&
@@ -571,8 +569,7 @@ OR
****************************************************************************/
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;
@@ -604,10 +601,6 @@ static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
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;
@@ -683,13 +676,11 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck,
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"));
@@ -706,9 +697,9 @@ NTSTATUS brl_lock(struct byte_range_lock *br_lck,
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
@@ -1165,7 +1156,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
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,
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index ac50c9b648..cd1d9547f3 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -185,7 +185,7 @@ NTSTATUS do_lock(files_struct *fsp,
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;
@@ -216,76 +216,63 @@ NTSTATUS do_lock(files_struct *fsp,
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,
@@ -295,14 +282,15 @@ NTSTATUS do_unlock(files_struct *fsp,
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);
@@ -310,7 +298,7 @@ NTSTATUS do_unlock(files_struct *fsp,
return NT_STATUS_NO_MEMORY;
}
- ok = brl_unlock(br_lck,
+ ok = brl_lock_cancel(br_lck,
lock_pid,
procid_self(),
offset,
@@ -320,8 +308,8 @@ NTSTATUS do_unlock(files_struct *fsp,
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;
@@ -340,7 +328,9 @@ void locking_close_file(files_struct *fsp)
}
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);
}