diff options
author | Jeremy Allison <jra@samba.org> | 2006-07-17 21:09:02 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:38:11 -0500 |
commit | e1da1fcf12164f50f3462c90f0bb785d18c59b0b (patch) | |
tree | 8df81a6c947a609249d67188c3a5dbebbdee0984 /source3/locking | |
parent | 4c713703d046f756989e7eb901e884829825593c (diff) | |
download | samba-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.c | 57 | ||||
-rw-r--r-- | source3/locking/locking.c | 102 |
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); } |