diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/locking/brlock.c | 125 | ||||
-rw-r--r-- | source3/locking/proto.h | 2 |
2 files changed, 127 insertions, 0 deletions
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index c03e4515bf..b7abaa9288 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1522,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. ****************************************************************************/ diff --git a/source3/locking/proto.h b/source3/locking/proto.h index 41c5a85696..c170c73301 100644 --- a/source3/locking/proto.h +++ b/source3/locking/proto.h @@ -79,6 +79,8 @@ bool brl_lock_cancel(struct byte_range_lock *br_lck, struct blocking_lock_record *blr); bool brl_lock_cancel_default(struct byte_range_lock *br_lck, struct lock_struct *plock); +bool brl_mark_disconnected(struct files_struct *fsp); +bool brl_reconnect_disconnected(struct files_struct *fsp); void brl_close_fnum(struct messaging_context *msg_ctx, struct byte_range_lock *br_lck); int brl_forall(void (*fn)(struct file_id id, struct server_id pid, |