diff options
Diffstat (limited to 'source3/locking/brlock.c')
-rw-r--r-- | source3/locking/brlock.c | 253 |
1 files changed, 194 insertions, 59 deletions
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index ef72eb0f6c..b7abaa9288 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -5,17 +5,17 @@ Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Jeremy Allison 1992-2000 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -28,7 +28,8 @@ #include "system/filesys.h" #include "locking/proto.h" #include "smbd/globals.h" -#include "dbwrap.h" +#include "dbwrap/dbwrap.h" +#include "dbwrap/dbwrap_open.h" #include "serverid.h" #include "messages.h" @@ -45,18 +46,18 @@ static struct db_context *brlock_db; Debug info at level 10 for lock struct. ****************************************************************************/ -static void print_lock_struct(unsigned int i, struct lock_struct *pls) +static void print_lock_struct(unsigned int i, const struct lock_struct *pls) { DEBUG(10,("[%u]: smblctx = %llu, tid = %u, pid = %s, ", i, (unsigned long long)pls->context.smblctx, (unsigned int)pls->context.tid, - procid_str(talloc_tos(), &pls->context.pid) )); - - DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n", + server_id_str(talloc_tos(), &pls->context.pid) )); + + DEBUG(10,("start = %.0f, size = %.0f, fnum = %llu, %s %s\n", (double)pls->start, (double)pls->size, - pls->fnum, + (unsigned long long)pls->fnum, lock_type_name(pls->lock_type), lock_flav_name(pls->lock_flav) )); } @@ -68,7 +69,7 @@ static void print_lock_struct(unsigned int i, struct lock_struct *pls) bool brl_same_context(const struct lock_context *ctx1, const struct lock_context *ctx2) { - return (procid_equal(&ctx1->pid, &ctx2->pid) && + return (serverid_equal(&ctx1->pid, &ctx2->pid) && (ctx1->smblctx == ctx2->smblctx) && (ctx1->tid == ctx2->tid)); } @@ -180,7 +181,7 @@ static bool brl_conflict1(const struct lock_struct *lck1, lck2->start >= (lck1->start + lck1->size)) { return False; } - + return True; } #endif @@ -251,7 +252,7 @@ NTSTATUS brl_lock_failed(files_struct *fsp, const struct lock_struct *lock, bool return NT_STATUS_FILE_LOCK_CONFLICT; } - if (procid_equal(&lock->context.pid, &fsp->last_lock_failure.context.pid) && + if (serverid_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) { @@ -289,7 +290,8 @@ void brl_init(bool read_only) brlock_db = db_open(NULL, lock_path("brlock.tdb"), lp_open_files_db_hash_size(), tdb_flags, - read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 ); + read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644, + DBWRAP_LOCK_ORDER_2); if (!brlock_db) { DEBUG(0,("Failed to open byte range locking database %s\n", lock_path("brlock.tdb"))); @@ -897,8 +899,8 @@ NTSTATUS smb_vfs_call_brl_lock_windows(struct vfs_handle_struct *handle, struct blocking_lock_record *blr) { VFS_FIND(brl_lock_windows); - return handle->fns->brl_lock_windows(handle, br_lck, plock, - blocking_lock, blr); + return handle->fns->brl_lock_windows_fn(handle, br_lck, plock, + blocking_lock, blr); } /**************************************************************************** @@ -1231,7 +1233,8 @@ bool smb_vfs_call_brl_unlock_windows(struct vfs_handle_struct *handle, const struct lock_struct *plock) { VFS_FIND(brl_unlock_windows); - return handle->fns->brl_unlock_windows(handle, msg_ctx, br_lck, plock); + return handle->fns->brl_unlock_windows_fn(handle, msg_ctx, br_lck, + plock); } /**************************************************************************** @@ -1312,9 +1315,9 @@ bool brl_locktest(struct byte_range_lock *br_lck, if(lp_posix_locking(fsp->conn->params) && (lock_flav == WINDOWS_LOCK)) { ret = is_posix_locked(fsp, &start, &size, &lock_type, WINDOWS_LOCK); - DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for fnum %d file %s\n", + DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for %s file %s\n", (double)start, (double)size, ret ? "locked" : "unlocked", - fsp->fnum, fsp_str_dbg(fsp))); + fsp_fnum_dbg(fsp), fsp_str_dbg(fsp))); /* We need to return the inverse of is_posix_locked. */ ret = !ret; @@ -1378,9 +1381,9 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, if(lp_posix_locking(fsp->conn->params)) { bool ret = is_posix_locked(fsp, pstart, psize, plock_type, POSIX_LOCK); - DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n", + DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for %s file %s\n", (double)*pstart, (double)*psize, ret ? "locked" : "unlocked", - fsp->fnum, fsp_str_dbg(fsp))); + fsp_fnum_dbg(fsp), fsp_str_dbg(fsp))); if (ret) { /* Hmmm. No clue what to set smblctx to - use -1. */ @@ -1399,7 +1402,7 @@ bool smb_vfs_call_brl_cancel_windows(struct vfs_handle_struct *handle, struct blocking_lock_record *blr) { VFS_FIND(brl_cancel_windows); - return handle->fns->brl_cancel_windows(handle, br_lck, plock, blr); + return handle->fns->brl_cancel_windows_fn(handle, br_lck, plock, blr); } /**************************************************************************** @@ -1483,17 +1486,17 @@ void brl_close_fnum(struct messaging_context *msg_ctx, struct byte_range_lock *br_lck) { files_struct *fsp = br_lck->fsp; - uint16 tid = fsp->conn->cnum; - int fnum = fsp->fnum; + uint32_t tid = fsp->conn->cnum; + uint64_t fnum = fsp->fnum; unsigned int i; struct lock_struct *locks = br_lck->lock_data; - struct server_id pid = sconn_server_id(fsp->conn->sconn); + struct server_id pid = messaging_server_id(fsp->conn->sconn->msg_ctx); struct lock_struct *locks_copy; unsigned int num_locks_copy; /* Copy the current lock array. */ if (br_lck->num_locks) { - locks_copy = (struct lock_struct *)TALLOC_MEMDUP(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); + locks_copy = (struct lock_struct *)talloc_memdup(br_lck, locks, br_lck->num_locks * sizeof(struct lock_struct)); if (!locks_copy) { smb_panic("brl_close_fnum: talloc failed"); } @@ -1506,7 +1509,7 @@ void brl_close_fnum(struct messaging_context *msg_ctx, for (i=0; i < num_locks_copy; i++) { struct lock_struct *lock = &locks_copy[i]; - if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid) && + if (lock->context.tid == tid && serverid_equal(&lock->context.pid, &pid) && (lock->fnum == fnum)) { brl_unlock(msg_ctx, br_lck, @@ -1519,6 +1522,131 @@ void brl_close_fnum(struct messaging_context *msg_ctx, } } +bool brl_mark_disconnected(struct files_struct *fsp) +{ + uint32_t tid = fsp->conn->cnum; + uint64_t smblctx = fsp->op->global->open_persistent_id; + uint64_t fnum = fsp->fnum; + unsigned int i; + struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx); + struct byte_range_lock *br_lck = NULL; + + if (!fsp->op->global->durable) { + return false; + } + + if (fsp->current_lock_count == 0) { + return true; + } + + br_lck = brl_get_locks(talloc_tos(), fsp); + if (br_lck == NULL) { + return false; + } + + for (i=0; i < br_lck->num_locks; i++) { + struct lock_struct *lock = &br_lck->lock_data[i]; + + /* + * as this is a durable handle, we only expect locks + * of the current file handle! + */ + + if (lock->context.smblctx != smblctx) { + TALLOC_FREE(br_lck); + return false; + } + + if (lock->context.tid != tid) { + TALLOC_FREE(br_lck); + return false; + } + + if (!serverid_equal(&lock->context.pid, &self)) { + TALLOC_FREE(br_lck); + return false; + } + + if (lock->fnum != fnum) { + TALLOC_FREE(br_lck); + return false; + } + + server_id_set_disconnected(&lock->context.pid); + lock->context.tid = TID_FIELD_INVALID; + lock->fnum = FNUM_FIELD_INVALID; + } + + br_lck->modified = true; + TALLOC_FREE(br_lck); + return true; +} + +bool brl_reconnect_disconnected(struct files_struct *fsp) +{ + uint32_t tid = fsp->conn->cnum; + uint64_t smblctx = fsp->op->global->open_persistent_id; + uint64_t fnum = fsp->fnum; + unsigned int i; + struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx); + struct byte_range_lock *br_lck = NULL; + + if (!fsp->op->global->durable) { + return false; + } + + /* we want to validate ourself */ + fsp->lockdb_clean = true; + + br_lck = brl_get_locks(talloc_tos(), fsp); + if (br_lck == NULL) { + return false; + } + + if (br_lck->num_locks == 0) { + TALLOC_FREE(br_lck); + return true; + } + + for (i=0; i < br_lck->num_locks; i++) { + struct lock_struct *lock = &br_lck->lock_data[i]; + + /* + * as this is a durable handle we only expect locks + * of the current file handle! + */ + + if (lock->context.smblctx != smblctx) { + TALLOC_FREE(br_lck); + return false; + } + + if (lock->context.tid != TID_FIELD_INVALID) { + TALLOC_FREE(br_lck); + return false; + } + + if (!server_id_is_disconnected(&lock->context.pid)) { + TALLOC_FREE(br_lck); + return false; + } + + if (lock->fnum != FNUM_FIELD_INVALID) { + TALLOC_FREE(br_lck); + return false; + } + + lock->context.pid = self; + lock->context.tid = tid; + lock->fnum = fnum; + } + + fsp->current_lock_count = br_lck->num_locks; + br_lck->modified = true; + TALLOC_FREE(br_lck); + return true; +} + /**************************************************************************** Ensure this set of lock entries is valid. ****************************************************************************/ @@ -1584,7 +1712,7 @@ struct brl_forall_cb { on each lock. ****************************************************************************/ -static int traverse_fn(struct db_record *rec, void *state) +static int brl_traverse_fn(struct db_record *rec, void *state) { struct brl_forall_cb *cb = (struct brl_forall_cb *)state; struct lock_struct *locks; @@ -1592,18 +1720,22 @@ static int traverse_fn(struct db_record *rec, void *state) unsigned int i; unsigned int num_locks = 0; unsigned int orig_num_locks = 0; + TDB_DATA dbkey; + TDB_DATA value; + + dbkey = dbwrap_record_get_key(rec); + value = dbwrap_record_get_value(rec); /* In a traverse function we must make a copy of dbuf before modifying it. */ - locks = (struct lock_struct *)memdup(rec->value.dptr, - rec->value.dsize); + locks = (struct lock_struct *)memdup(value.dptr, value.dsize); if (!locks) { return -1; /* Terminate traversal. */ } - key = (struct file_id *)rec->key.dptr; - orig_num_locks = num_locks = rec->value.dsize/sizeof(*locks); + key = (struct file_id *)dbkey.dptr; + orig_num_locks = num_locks = value.dsize/sizeof(*locks); /* Ensure the lock db is clean of entries from invalid processes. */ @@ -1617,9 +1749,9 @@ static int traverse_fn(struct db_record *rec, void *state) TDB_DATA data; data.dptr = (uint8_t *)locks; data.dsize = num_locks*sizeof(struct lock_struct); - rec->store(rec, data, TDB_REPLACE); + dbwrap_record_store(rec, data, TDB_REPLACE); } else { - rec->delete_rec(rec); + dbwrap_record_delete(rec); } } @@ -1651,13 +1783,21 @@ int brl_forall(void (*fn)(struct file_id id, struct server_id pid, void *private_data) { struct brl_forall_cb cb; + NTSTATUS status; + int count = 0; if (!brlock_db) { return 0; } cb.fn = fn; cb.private_data = private_data; - return brlock_db->traverse(brlock_db, traverse_fn, &cb); + status = dbwrap_traverse(brlock_db, brl_traverse_fn, &cb, &count); + + if (!NT_STATUS_IS_OK(status)) { + return -1; + } else { + return count; + } } /******************************************************************* @@ -1678,7 +1818,7 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck) if (br_lck->num_locks == 0) { /* No locks - delete this entry. */ - NTSTATUS status = br_lck->record->delete_rec(br_lck->record); + NTSTATUS status = dbwrap_record_delete(br_lck->record); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("delete_rec returned %s\n", nt_errstr(status))); @@ -1691,8 +1831,7 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck) data.dptr = (uint8 *)br_lck->lock_data; data.dsize = br_lck->num_locks * sizeof(struct lock_struct); - status = br_lck->record->store(br_lck->record, data, - TDB_REPLACE); + status = dbwrap_record_store(br_lck->record, data, TDB_REPLACE); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("store returned %s\n", nt_errstr(status))); smb_panic("Could not store byte range mode entry"); @@ -1724,7 +1863,7 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, files_struct *fsp, bool read_only) { TDB_DATA key, data; - struct byte_range_lock *br_lck = TALLOC_P(mem_ctx, struct byte_range_lock); + struct byte_range_lock *br_lck = talloc(mem_ctx, struct byte_range_lock); bool do_read_only = read_only; if (br_lck == NULL) { @@ -1746,14 +1885,16 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, } if (do_read_only) { - if (brlock_db->fetch(brlock_db, br_lck, key, &data) == -1) { + NTSTATUS status; + status = dbwrap_fetch(brlock_db, br_lck, key, &data); + if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not fetch byte range lock record\n")); TALLOC_FREE(br_lck); return NULL; } br_lck->record = NULL; } else { - br_lck->record = brlock_db->fetch_locked(brlock_db, br_lck, key); + br_lck->record = dbwrap_fetch_locked(brlock_db, br_lck, key); if (br_lck->record == NULL) { DEBUG(3, ("Could not lock byte range lock entry\n")); @@ -1761,7 +1902,7 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, return NULL; } - data = br_lck->record->value; + data = dbwrap_record_get_value(br_lck->record); } br_lck->read_only = do_read_only; @@ -1782,7 +1923,7 @@ static struct byte_range_lock *brl_get_locks_internal(TALLOC_CTX *mem_ctx, memcpy(br_lck->lock_data, data.dptr, data.dsize); } - + if (!fsp->lockdb_clean) { int orig_num_locks = br_lck->num_locks; @@ -1843,7 +1984,7 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp) } if ((fsp->brlock_rec != NULL) - && (brlock_db->get_seqnum(brlock_db) == fsp->brlock_seqnum)) { + && (dbwrap_get_seqnum(brlock_db) == fsp->brlock_seqnum)) { return fsp->brlock_rec; } @@ -1853,7 +1994,7 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp) if (br_lock == NULL) { return NULL; } - fsp->brlock_seqnum = brlock_db->get_seqnum(brlock_db); + fsp->brlock_seqnum = dbwrap_get_seqnum(brlock_db); fsp->brlock_rec = talloc_move(fsp, &br_lock); @@ -1894,8 +2035,8 @@ static void brl_revalidate_collect(struct file_id id, struct server_id pid, static int compare_procids(const void *p1, const void *p2) { - const struct server_id *i1 = (struct server_id *)p1; - const struct server_id *i2 = (struct server_id *)p2; + const struct server_id *i1 = (const struct server_id *)p1; + const struct server_id *i2 = (const struct server_id *)p2; if (i1->pid < i2->pid) return -1; if (i2->pid > i2->pid) return 1; @@ -1911,17 +2052,17 @@ static int compare_procids(const void *p1, const void *p2) * array, then qsort that array and only send to non-dupes. */ -static void brl_revalidate(struct messaging_context *msg_ctx, - void *private_data, - uint32_t msg_type, - struct server_id server_id, - DATA_BLOB *data) +void brl_revalidate(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) { struct brl_revalidate_state *state; uint32 i; struct server_id last_pid; - if (!(state = TALLOC_ZERO_P(NULL, struct brl_revalidate_state))) { + if (!(state = talloc_zero(NULL, struct brl_revalidate_state))) { DEBUG(0, ("talloc failed\n")); return; } @@ -1942,7 +2083,7 @@ static void brl_revalidate(struct messaging_context *msg_ctx, ZERO_STRUCT(last_pid); for (i=0; i<state->num_pids; i++) { - if (procid_equal(&last_pid, &state->pids[i])) { + if (serverid_equal(&last_pid, &state->pids[i])) { /* * We've seen that one already */ @@ -1958,9 +2099,3 @@ static void brl_revalidate(struct messaging_context *msg_ctx, TALLOC_FREE(state); return; } - -void brl_register_msgs(struct messaging_context *msg_ctx) -{ - messaging_register(msg_ctx, NULL, MSG_SMB_BRL_VALIDATE, - brl_revalidate); -} |