used. This allows us to provide the same semantics as NT */
#include "includes.h"
+#include "librpc/gen_ndr/messaging.h"
+#include "smbd/globals.h"
+#include "dbwrap.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_LOCKING
static void print_lock_struct(unsigned int i, struct lock_struct *pls)
{
- DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %s, ",
+ DEBUG(10,("[%u]: smblctx = %llu, tid = %u, pid = %s, ",
i,
- (unsigned int)pls->context.smbpid,
+ (unsigned long long)pls->context.smblctx,
(unsigned int)pls->context.tid,
procid_str(talloc_tos(), &pls->context.pid) ));
const struct lock_context *ctx2)
{
return (procid_equal(&ctx1->pid, &ctx2->pid) &&
- (ctx1->smbpid == ctx2->smbpid) &&
+ (ctx1->smblctx == ctx2->smblctx) &&
(ctx1->tid == ctx2->tid));
}
void brl_init(bool read_only)
{
+ int tdb_flags;
+
if (brlock_db) {
return;
}
+
+ tdb_flags = TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH;
+
+ if (!lp_clustering()) {
+ /*
+ * We can't use the SEQNUM trick to cache brlock
+ * entries in the clustering case because ctdb seqnum
+ * propagation has a delay.
+ */
+ tdb_flags |= TDB_SEQNUM;
+ }
+
brlock_db = db_open(NULL, lock_path("brlock.tdb"),
- lp_open_files_db_hash_size(),
- TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST,
+ lp_open_files_db_hash_size(), tdb_flags,
read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );
if (!brlock_db) {
DEBUG(0,("Failed to open byte range locking database %s\n",
SMB_ASSERT(plock->lock_type != UNLOCK_LOCK);
+ if ((plock->start + plock->size - 1 < plock->start) &&
+ plock->size != 0) {
+ return NT_STATUS_INVALID_LOCK_RANGE;
+ }
+
for (i=0; i < br_lck->num_locks; i++) {
/* Do any Windows or POSIX locks conflict ? */
if (brl_conflict(&locks[i], plock)) {
/* Remember who blocked us. */
- plock->context.smbpid = locks[i].context.smbpid;
+ plock->context.smblctx = locks[i].context.smblctx;
return brl_lock_failed(fsp,plock,blocking_lock);
}
#if ZERO_ZERO
&errno_ret)) {
/* We don't know who blocked us. */
- plock->context.smbpid = 0xFFFFFFFF;
+ plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL;
if (errno_ret == EACCES || errno_ret == EAGAIN) {
status = NT_STATUS_FILE_LOCK_CONFLICT;
}
/* Don't allow 64-bit lock wrap. */
- if (plock->start + plock->size < plock->start ||
- plock->start + plock->size < plock->size) {
+ if (plock->start + plock->size - 1 < plock->start) {
return NT_STATUS_INVALID_PARAMETER;
}
/* No games with error messages. */
SAFE_FREE(tp);
/* Remember who blocked us. */
- plock->context.smbpid = curr_lock->context.smbpid;
+ plock->context.smblctx = curr_lock->context.smblctx;
return NT_STATUS_FILE_LOCK_CONFLICT;
}
/* Just copy the Windows lock into the new array. */
/* No games with error messages. */
SAFE_FREE(tp);
/* Remember who blocked us. */
- plock->context.smbpid = curr_lock->context.smbpid;
+ plock->context.smblctx = curr_lock->context.smblctx;
return NT_STATUS_FILE_LOCK_CONFLICT;
}
&errno_ret)) {
/* We don't know who blocked us. */
- plock->context.smbpid = 0xFFFFFFFF;
+ plock->context.smblctx = 0xFFFFFFFFFFFFFFFFLL;
if (errno_ret == EACCES || errno_ret == EAGAIN) {
SAFE_FREE(tp);
NTSTATUS brl_lock(struct messaging_context *msg_ctx,
struct byte_range_lock *br_lck,
- uint32 smbpid,
+ uint64_t smblctx,
struct server_id pid,
br_off start,
br_off size,
enum brl_type lock_type,
enum brl_flavour lock_flav,
bool blocking_lock,
- uint32 *psmbpid,
+ uint64_t *psmblctx,
struct blocking_lock_record *blr)
{
NTSTATUS ret;
memset(&lock, '\0', sizeof(lock));
#endif
- lock.context.smbpid = smbpid;
+ lock.context.smblctx = smblctx;
lock.context.pid = pid;
lock.context.tid = br_lck->fsp->conn->cnum;
lock.start = start;
#if ZERO_ZERO
/* sort the lock list */
- qsort(br_lck->lock_data, (size_t)br_lck->num_locks, sizeof(lock), lock_compare);
+ TYPESAFE_QSORT(br_lck->lock_data, (size_t)br_lck->num_locks, lock_compare);
#endif
/* If we're returning an error, return who blocked us. */
- if (!NT_STATUS_IS_OK(ret) && psmbpid) {
- *psmbpid = lock.context.smbpid;
+ if (!NT_STATUS_IS_OK(ret) && psmblctx) {
+ *psmblctx = lock.context.smblctx;
}
return ret;
}
for (i = 0; i < br_lck->num_locks; i++) {
struct lock_struct *lock = &locks[i];
+ if (IS_PENDING_LOCK(lock->lock_type)) {
+ continue;
+ }
+
/* Only remove our own locks that match in start, size, and flavour. */
if (brl_same_context(&lock->context, &plock->context) &&
lock->fnum == plock->fnum &&
bool brl_unlock(struct messaging_context *msg_ctx,
struct byte_range_lock *br_lck,
- uint32 smbpid,
+ uint64_t smblctx,
struct server_id pid,
br_off start,
br_off size,
{
struct lock_struct lock;
- lock.context.smbpid = smbpid;
+ lock.context.smblctx = smblctx;
lock.context.pid = pid;
lock.context.tid = br_lck->fsp->conn->cnum;
lock.start = start;
****************************************************************************/
bool brl_locktest(struct byte_range_lock *br_lck,
- uint32 smbpid,
+ uint64_t smblctx,
struct server_id pid,
br_off start,
br_off size,
const struct lock_struct *locks = br_lck->lock_data;
files_struct *fsp = br_lck->fsp;
- lock.context.smbpid = smbpid;
+ lock.context.smblctx = smblctx;
lock.context.pid = pid;
lock.context.tid = br_lck->fsp->conn->cnum;
lock.start = start;
****************************************************************************/
NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
- uint32 *psmbpid,
+ uint64_t *psmblctx,
struct server_id pid,
br_off *pstart,
br_off *psize,
const struct lock_struct *locks = br_lck->lock_data;
files_struct *fsp = br_lck->fsp;
- lock.context.smbpid = *psmbpid;
+ lock.context.smblctx = *psmblctx;
lock.context.pid = pid;
lock.context.tid = br_lck->fsp->conn->cnum;
lock.start = *pstart;
}
if (conflict) {
- *psmbpid = exlock->context.smbpid;
+ *psmblctx = exlock->context.smblctx;
*pstart = exlock->start;
*psize = exlock->size;
*plock_type = exlock->lock_type;
fsp->fnum, fsp_str_dbg(fsp)));
if (ret) {
- /* Hmmm. No clue what to set smbpid to - use -1. */
- *psmbpid = 0xFFFF;
+ /* Hmmm. No clue what to set smblctx to - use -1. */
+ *psmblctx = 0xFFFFFFFFFFFFFFFFLL;
return NT_STATUS_LOCK_NOT_GRANTED;
}
}
Remove a particular pending lock.
****************************************************************************/
bool brl_lock_cancel(struct byte_range_lock *br_lck,
- uint32 smbpid,
+ uint64_t smblctx,
struct server_id pid,
br_off start,
br_off size,
bool ret;
struct lock_struct lock;
- lock.context.smbpid = smbpid;
+ lock.context.smblctx = smblctx;
lock.context.pid = pid;
lock.context.tid = br_lck->fsp->conn->cnum;
lock.start = start;
unsigned int i, j, dcount=0;
int num_deleted_windows_locks = 0;
struct lock_struct *locks = br_lck->lock_data;
- struct server_id pid = procid_self();
+ struct server_id pid = sconn_server_id(fsp->conn->sconn);
bool unlock_individually = False;
bool posix_level2_contention_ended = false;
(lock->fnum == fnum)) {
brl_unlock(msg_ctx,
br_lck,
- lock->context.smbpid,
+ lock->context.smblctx,
pid,
lock->start,
lock->size,
for (i = 0; i < *pnum_entries; i++) {
struct lock_struct *lock_data = &locks[i];
- if (!process_exists(lock_data->context.pid)) {
+ if (!serverid_exists(&lock_data->context.pid)) {
/* This process no longer exists - mark this
entry as invalid by zeroing it. */
ZERO_STRUCTP(lock_data);
num_valid_entries = 0;
for (i = 0; i < *pnum_entries; i++) {
struct lock_struct *lock_data = &locks[i];
- if (lock_data->context.smbpid &&
+ if (lock_data->context.smblctx &&
lock_data->context.tid) {
/* Valid (nonzero) entry - copy it. */
memcpy(&new_lock_data[num_valid_entries],
br_lck->fsp = fsp;
br_lck->num_locks = 0;
br_lck->modified = False;
- memset(&br_lck->key, '\0', sizeof(struct file_id));
br_lck->key = fsp->file_id;
key.dptr = (uint8 *)&br_lck->key;
return brl_get_locks_internal(mem_ctx, fsp, False);
}
-struct byte_range_lock *brl_get_locks_readonly(TALLOC_CTX *mem_ctx,
- files_struct *fsp)
+struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
{
- return brl_get_locks_internal(mem_ctx, fsp, True);
+ struct byte_range_lock *br_lock;
+
+ if (lp_clustering()) {
+ return brl_get_locks_internal(talloc_tos(), fsp, true);
+ }
+
+ if ((fsp->brlock_rec != NULL)
+ && (brlock_db->get_seqnum(brlock_db) == fsp->brlock_seqnum)) {
+ return fsp->brlock_rec;
+ }
+
+ TALLOC_FREE(fsp->brlock_rec);
+
+ br_lock = brl_get_locks_internal(talloc_tos(), fsp, false);
+ if (br_lock == NULL) {
+ return NULL;
+ }
+ fsp->brlock_seqnum = brlock_db->get_seqnum(brlock_db);
+
+ fsp->brlock_rec = talloc_zero(fsp, struct byte_range_lock);
+ if (fsp->brlock_rec == NULL) {
+ goto fail;
+ }
+ fsp->brlock_rec->fsp = fsp;
+ fsp->brlock_rec->num_locks = br_lock->num_locks;
+ fsp->brlock_rec->read_only = true;
+ fsp->brlock_rec->key = br_lock->key;
+
+ fsp->brlock_rec->lock_data = (struct lock_struct *)
+ talloc_memdup(fsp->brlock_rec, br_lock->lock_data,
+ sizeof(struct lock_struct) * br_lock->num_locks);
+ if (fsp->brlock_rec->lock_data == NULL) {
+ goto fail;
+ }
+
+ TALLOC_FREE(br_lock);
+ return fsp->brlock_rec;
+fail:
+ TALLOC_FREE(br_lock);
+ TALLOC_FREE(fsp->brlock_rec);
+ return NULL;
}
struct brl_revalidate_state {
goto done;
}
- qsort(state->pids, state->num_pids, sizeof(state->pids[0]),
- compare_procids);
+ TYPESAFE_QSORT(state->pids, state->num_pids, compare_procids);
ZERO_STRUCT(last_pid);