summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2022-08-28 11:41:46 +0200
committerJeremy Allison <jra@samba.org>2022-09-20 00:34:35 +0000
commit01c629a409860e5cccfc64e78fa63c90303a4b7a (patch)
treef8f04b4045f97fd1ebdf36c93f71e1bcb30c7575 /source3/lib
parent63291ea5c5d32e295b3638afd530e805ec59a190 (diff)
downloadsamba-01c629a409860e5cccfc64e78fa63c90303a4b7a.tar.gz
s3:g_lock: add callback function to g_lock_lock_simple_fn()
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15125 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/g_lock.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
index 7e27f2ea52a..7868a69a337 100644
--- a/source3/lib/g_lock.c
+++ b/source3/lib/g_lock.c
@@ -1127,9 +1127,12 @@ NTSTATUS g_lock_lock_recv(struct tevent_req *req)
}
struct g_lock_lock_simple_state {
+ struct g_lock_ctx *ctx;
struct server_id me;
enum g_lock_type type;
NTSTATUS status;
+ g_lock_lock_cb_fn_t cb_fn;
+ void *cb_private;
};
static void g_lock_lock_simple_fn(
@@ -1140,7 +1143,15 @@ static void g_lock_lock_simple_fn(
struct g_lock_lock_simple_state *state = private_data;
struct server_id_buf buf;
struct g_lock lck = { .exclusive.pid = 0 };
- struct server_id *new_shared = NULL;
+ struct g_lock_lock_cb_state cb_state = {
+ .ctx = state->ctx,
+ .rec = rec,
+ .lck = &lck,
+ .cb_fn = state->cb_fn,
+ .cb_private = state->cb_private,
+ .existed = value.dsize != 0,
+ .update_mem_ctx = talloc_tos(),
+ };
bool ok;
ok = g_lock_parse(value.dptr, value.dsize, &lck);
@@ -1164,7 +1175,7 @@ static void g_lock_lock_simple_fn(
lck.exclusive = state->me;
} else if (state->type == G_LOCK_READ) {
g_lock_cleanup_shared(&lck);
- new_shared = &state->me;
+ cb_state.new_shared = &state->me;
} else {
smb_panic(__location__);
}
@@ -1172,15 +1183,23 @@ static void g_lock_lock_simple_fn(
lck.unique_lock_epoch = generate_unique_u64(lck.unique_lock_epoch);
/*
- * We're storing a lock and if we are
- * successful in doing that, we should not
- * wakeup any other waiters, all they would
- * find is that we're holding a lock they
- * are conflicting with.
+ * We are going to store us as owner,
+ * so we got what we were waiting for.
+ *
+ * So we no longer need to monitor the
+ * record.
*/
dbwrap_watched_watch_skip_alerting(rec);
- state->status = g_lock_store(rec, &lck, new_shared, NULL, 0);
+ state->status = g_lock_lock_cb_run_and_store(&cb_state);
+ if (!NT_STATUS_IS_OK(state->status) &&
+ !NT_STATUS_EQUAL(state->status, NT_STATUS_WAS_UNLOCKED))
+ {
+ DBG_WARNING("g_lock_lock_cb_run_and_store() failed: %s\n",
+ nt_errstr(state->status));
+ return;
+ }
+
return;
not_granted:
@@ -1190,6 +1209,8 @@ not_granted:
NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, TDB_DATA key,
enum g_lock_type type, struct timeval timeout)
{
+ g_lock_lock_cb_fn_t cb_fn = NULL;
+ void *cb_private = NULL;
TALLOC_CTX *frame;
struct tevent_context *ev;
struct tevent_req *req;
@@ -1209,8 +1230,11 @@ NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, TDB_DATA key,
* improvement for lock/unlock.
*/
struct g_lock_lock_simple_state state = {
+ .ctx = ctx,
.me = messaging_server_id(ctx->msg),
.type = type,
+ .cb_fn = cb_fn,
+ .cb_private = cb_private,
};
status = dbwrap_do_locked(
ctx->db, key, g_lock_lock_simple_fn, &state);
@@ -1231,6 +1255,10 @@ NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, TDB_DATA key,
}
return NT_STATUS_OK;
}
+ if (NT_STATUS_EQUAL(state.status, NT_STATUS_WAS_UNLOCKED)) {
+ /* without dbwrap_lock_order_lock() */
+ return NT_STATUS_OK;
+ }
if (!NT_STATUS_EQUAL(
state.status, NT_STATUS_LOCK_NOT_GRANTED)) {
return state.status;