diff options
author | Volker Lendecke <vl@samba.org> | 2019-11-05 12:01:52 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2020-05-15 00:48:33 +0000 |
commit | 8020f013084e4424e761b405634b03aa6466bd88 (patch) | |
tree | d209ba931f6dfb7ecf12f04c984cfae980051294 /source3 | |
parent | 3bf576bb2a8eaf1ede44b6327e2eb9272b73c5f9 (diff) | |
download | samba-8020f013084e4424e761b405634b03aa6466bd88.tar.gz |
smbd: Base locking.tdb on g_lock.c
This means we don't hold locking.tdb mutexes anymore while we do
filesystem-level operations. This has hurt ctdb quite a bit: A smbd hanging in
an unlink() syscall prevents ctdb from recovering locking.tdb.
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3')
-rw-r--r-- | source3/locking/share_mode_lock.c | 569 |
1 files changed, 315 insertions, 254 deletions
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index ff77f12d1f7..872b77f8d7b 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -42,6 +42,7 @@ #include "smbd/globals.h" #include "dbwrap/dbwrap.h" #include "dbwrap/dbwrap_open.h" +#include "dbwrap/dbwrap_private.h" #include "../libcli/security/security.h" #include "serverid.h" #include "messages.h" @@ -51,6 +52,7 @@ #include "locking/leases_db.h" #include "../lib/util/memcache.h" #include "lib/util/tevent_ntstatus.h" +#include "g_lock.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING @@ -58,7 +60,7 @@ #define NO_LOCKING_COUNT (-1) /* the locking database handle */ -static struct db_context *lock_db; +static struct g_lock_ctx *lock_ctx; static struct db_context *share_entries_db; static bool locking_init_internal(bool read_only) @@ -68,8 +70,9 @@ static bool locking_init_internal(bool read_only) brl_init(read_only); - if (lock_db) + if (lock_ctx != NULL) { return True; + } db_path = lock_path(talloc_tos(), "locking.tdb"); if (db_path == NULL) { @@ -84,22 +87,25 @@ static bool locking_init_internal(bool read_only) TDB_INCOMPATIBLE_HASH| TDB_SEQNUM, read_only?O_RDONLY:O_RDWR|O_CREAT, 0644, - DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE); + DBWRAP_LOCK_ORDER_NONE, + DBWRAP_FLAG_NONE); TALLOC_FREE(db_path); if (!backend) { DEBUG(0,("ERROR: Failed to initialise locking database\n")); return False; } - lock_db = db_open_watched(NULL, &backend, global_messaging_context()); - if (lock_db == NULL) { - DBG_ERR("db_open_watched failed\n"); + lock_ctx = g_lock_ctx_init_backend( + NULL, global_messaging_context(), &backend); + if (lock_ctx == NULL) { TALLOC_FREE(backend); return false; } + g_lock_set_lock_order(lock_ctx, DBWRAP_LOCK_ORDER_1); db_path = lock_path(talloc_tos(), "share_entries.tdb"); if (db_path == NULL) { + TALLOC_FREE(lock_ctx); return false; } @@ -115,13 +121,13 @@ static bool locking_init_internal(bool read_only) TALLOC_FREE(db_path); if (share_entries_db == NULL) { - TALLOC_FREE(lock_db); + TALLOC_FREE(lock_ctx); return false; } if (!posix_locking_init(read_only)) { TALLOC_FREE(share_entries_db); - TALLOC_FREE(lock_db); + TALLOC_FREE(lock_ctx); return False; } @@ -145,7 +151,7 @@ bool locking_init_readonly(void) bool locking_end(void) { brl_shutdown(); - TALLOC_FREE(lock_db); + TALLOC_FREE(lock_ctx); return true; } @@ -243,7 +249,7 @@ static void fsp_update_share_mode_flags_fn( static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp) { struct fsp_update_share_mode_flags_state state = {0}; - int seqnum = dbwrap_get_seqnum(lock_db); + int seqnum = g_lock_seqnum(lock_ctx); NTSTATUS status; if (seqnum == fsp->share_mode_flags_seqnum) { @@ -433,11 +439,10 @@ fail: If modified, store the share_mode_data back into the database. ********************************************************************/ -static NTSTATUS share_mode_data_store( - struct share_mode_data *d, struct db_record *rec) +static NTSTATUS share_mode_data_store(struct share_mode_data *d) { - DATA_BLOB blob; - enum ndr_err_code ndr_err; + TDB_DATA key = locking_key(&d->id); + DATA_BLOB blob = { 0 }; NTSTATUS status; if (!d->modified) { @@ -452,39 +457,29 @@ static NTSTATUS share_mode_data_store( d->sequence_number += 1; - if (!d->have_share_modes) { - TDB_DATA key = dbwrap_record_get_key(rec); + if (d->have_share_modes) { + enum ndr_err_code ndr_err; + + ndr_err = ndr_push_struct_blob( + &blob, + d, + d, + (ndr_push_flags_fn_t)ndr_push_share_mode_data); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DBG_DEBUG("ndr_push_share_mode_data failed: %s\n", + ndr_errstr(ndr_err)); + return ndr_map_error2ntstatus(ndr_err); + } + } else { bool share_entries_exist; share_entries_exist = dbwrap_exists(share_entries_db, key); SMB_ASSERT(!share_entries_exist); - - TALLOC_FREE(d->delete_tokens); - d->num_delete_tokens = 0; - - if (d->fresh) { - DBG_DEBUG("Ignoring fresh empty record\n"); - return NT_STATUS_OK; - } - status = dbwrap_record_delete(rec); - return status; } - ndr_err = ndr_push_struct_blob( - &blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DBG_DEBUG("ndr_push_share_mode_data failed: %s\n", - ndr_errstr(ndr_err)); - return ndr_map_error2ntstatus(ndr_err); - } - - status = dbwrap_record_store( - rec, - (TDB_DATA) { .dptr = blob.data, .dsize = blob.length }, - TDB_REPLACE); + status = g_lock_write_data(lock_ctx, key, blob.data, blob.length); TALLOC_FREE(blob.data); - if (!NT_STATUS_IS_OK(status)) { - DBG_DEBUG("dbwrap_record_store failed: %s\n", + DBG_DEBUG("g_lock_write_data failed: %s\n", nt_errstr(status)); } @@ -543,6 +538,16 @@ fail: } /* + * Key that's locked with g_lock + */ +static uint8_t share_mode_lock_key_data[sizeof(struct file_id)]; +static TDB_DATA share_mode_lock_key = { + .dptr = share_mode_lock_key_data, + .dsize = sizeof(share_mode_lock_key_data), +}; +static size_t share_mode_lock_key_refcount = 0; + +/* * We can only ever have one share mode locked. Use a static * share_mode_data pointer that is shared by multiple nested * share_mode_lock structures, explicitly refcounted. @@ -550,52 +555,90 @@ fail: static struct share_mode_data *static_share_mode_data = NULL; static size_t static_share_mode_data_refcount = 0; -/* - * db_record for the above. With dbwrap_do_locked we can get a - * db_record on the stack, which we can't TALLOC_FREE but which we - * need to share with a nested get_share_mode_lock call. - */ -static struct db_record *static_share_mode_record = NULL; -static TDB_DATA static_share_mode_record_value = {0}; -static bool static_share_mode_record_talloced = false; - /******************************************************************* Either fetch a share mode from the database, or allocate a fresh one if the record doesn't exist. ********************************************************************/ -static NTSTATUS get_static_share_mode_data( - struct db_record *rec, - struct file_id id, - const char *servicepath, - const struct smb_filename *smb_fname, - const struct timespec *old_write_time) -{ - struct share_mode_data *d; - TDB_DATA value = dbwrap_record_get_value(rec); +struct get_static_share_mode_data_state { + TALLOC_CTX *mem_ctx; + struct file_id id; + const char *servicepath; + const struct smb_filename *smb_fname; + const struct timespec *old_write_time; + NTSTATUS status; +}; - SMB_ASSERT(static_share_mode_data == NULL); +static void get_static_share_mode_data_fn( + struct server_id exclusive, + size_t num_shared, + struct server_id *shared, + const uint8_t *data, + size_t datalen, + void *private_data) +{ + struct get_static_share_mode_data_state *state = private_data; + struct share_mode_data *d = NULL; - if (value.dptr == NULL) { + if (datalen == 0) { + if (state->smb_fname == NULL) { + state->status = NT_STATUS_NOT_FOUND; + return; + } d = fresh_share_mode_lock( - lock_db, servicepath, smb_fname, old_write_time); + state->mem_ctx, + state->servicepath, + state->smb_fname, + state->old_write_time); if (d == NULL) { - if (smb_fname == NULL) { - return NT_STATUS_NOT_FOUND; - } - return NT_STATUS_NO_MEMORY; + state->status = NT_STATUS_NO_MEMORY; + return; } } else { - TDB_DATA key = locking_key(&id); - d = parse_share_modes(lock_db, key, value.dptr, value.dsize); + TDB_DATA key = locking_key(&state->id); + d = parse_share_modes(lock_ctx, key, data, datalen); if (d == NULL) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; + state->status = NT_STATUS_INTERNAL_DB_CORRUPTION; + return; } } - d->id = id; - + d->id = state->id; static_share_mode_data = d; +} + +static NTSTATUS get_static_share_mode_data( + struct file_id id, + const char *servicepath, + const struct smb_filename *smb_fname, + const struct timespec *old_write_time) +{ + struct get_static_share_mode_data_state state = { + .mem_ctx = lock_ctx, + .id = id, + .servicepath = servicepath, + .smb_fname = smb_fname, + .old_write_time = old_write_time, + }; + NTSTATUS status; + + SMB_ASSERT(static_share_mode_data == NULL); + + status = g_lock_dump( + lock_ctx, + share_mode_lock_key, + get_static_share_mode_data_fn, + &state); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("g_lock_dump failed: %s\n", + nt_errstr(status)); + return status; + } + if (!NT_STATUS_IS_OK(state.status)) { + DBG_DEBUG("get_static_share_mode_data_fn failed: %s\n", + nt_errstr(state.status)); + return state.status; + } return NT_STATUS_OK; } @@ -616,6 +659,7 @@ struct share_mode_lock *get_share_mode_lock( TDB_DATA key = locking_key(&id); struct share_mode_lock *lck = NULL; NTSTATUS status; + int cmp; lck = talloc(mem_ctx, struct share_mode_lock); if (lck == NULL) { @@ -632,45 +676,42 @@ struct share_mode_lock *get_share_mode_lock( goto done; } - SMB_ASSERT(static_share_mode_data_refcount == 0); - - if (static_share_mode_record == NULL) { - static_share_mode_record = dbwrap_fetch_locked( - lock_db, lock_db, key); - if (static_share_mode_record == NULL) { - DEBUG(3, ("Could not lock share entry\n")); + if (share_mode_lock_key_refcount == 0) { + status = g_lock_lock( + lock_ctx, + key, + G_LOCK_WRITE, + (struct timeval) { .tv_sec = 3600 }); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("g_lock_lock failed: %s\n", + nt_errstr(status)); goto fail; } - static_share_mode_record_talloced = true; - static_share_mode_record_value = dbwrap_record_get_value( - static_share_mode_record); + memcpy(share_mode_lock_key_data, key.dptr, key.dsize); + } - } else { - TDB_DATA static_key; - int cmp; + cmp = tdb_data_cmp(share_mode_lock_key, key); + if (cmp != 0) { + DBG_WARNING("Can not lock two share modes simultaneously\n"); + goto fail; + } - static_key = dbwrap_record_get_key(static_share_mode_record); + SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX); + share_mode_lock_key_refcount += 1; - cmp = tdb_data_cmp(static_key, key); - if (cmp != 0) { - DBG_WARNING("Can not lock two share modes " - "simultaneously\n"); - return NULL; - } - } + SMB_ASSERT(static_share_mode_data_refcount == 0); - status = get_static_share_mode_data(static_share_mode_record, - id, - servicepath, - smb_fname, - old_write_time); + status = get_static_share_mode_data( + id, + servicepath, + smb_fname, + old_write_time); if (!NT_STATUS_IS_OK(status)) { DBG_DEBUG("get_static_share_mode_data failed: %s\n", nt_errstr(status)); - TALLOC_FREE(static_share_mode_record); + share_mode_lock_key_refcount -= 1; goto fail; } - done: static_share_mode_data_refcount += 1; lck->data = static_share_mode_data; @@ -680,6 +721,13 @@ done: return lck; fail: TALLOC_FREE(lck); + if (share_mode_lock_key_refcount == 0) { + status = g_lock_unlock(lock_ctx, share_mode_lock_key); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("g_lock_unlock failed: %s\n", + nt_errstr(status)); + } + } return NULL; } @@ -694,16 +742,23 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) return 0; } - status = share_mode_data_store( - static_share_mode_data, static_share_mode_record); + status = share_mode_data_store(static_share_mode_data); if (!NT_STATUS_IS_OK(status)) { DBG_ERR("share_mode_data_store failed: %s\n", nt_errstr(status)); smb_panic("Could not store share mode data\n"); } - if (static_share_mode_record_talloced) { - TALLOC_FREE(static_share_mode_record); + SMB_ASSERT(share_mode_lock_key_refcount > 0); + share_mode_lock_key_refcount -= 1; + + if (share_mode_lock_key_refcount == 0) { + status = g_lock_unlock(lock_ctx, share_mode_lock_key); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("g_lock_unlock failed: %s\n", + nt_errstr(status)); + smb_panic("Could not unlock share mode\n"); + } } if (static_share_mode_data->have_share_modes) { @@ -729,6 +784,7 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) } struct share_mode_do_locked_state { + TDB_DATA key; void (*fn)(const uint8_t *buf, size_t buflen, bool *modified_dependent, @@ -737,22 +793,18 @@ struct share_mode_do_locked_state { }; static void share_mode_do_locked_fn( - struct db_record *rec, - TDB_DATA value, + struct server_id exclusive, + size_t num_shared, + struct server_id *shared, + const uint8_t *data, + size_t datalen, void *private_data) { struct share_mode_do_locked_state *state = private_data; bool modified_dependent = false; - bool reset_static_share_mode_record = false; - - if (static_share_mode_record == NULL) { - static_share_mode_record = rec; - static_share_mode_record_value = value; - static_share_mode_record_talloced = false; - reset_static_share_mode_record = true; - } else { - SMB_ASSERT(static_share_mode_record == rec); - } + TDB_DATA value = { + .dptr = discard_const_p(uint8_t, data), .dsize = datalen, + }; state->fn(value.dptr, value.dsize, @@ -760,11 +812,7 @@ static void share_mode_do_locked_fn( state->private_data); if (modified_dependent) { - dbwrap_watched_wakeup(rec); - } - - if (reset_static_share_mode_record) { - static_share_mode_record = NULL; + g_lock_wake_watchers(lock_ctx, state->key); } } @@ -777,48 +825,52 @@ NTSTATUS share_mode_do_locked( void *private_data) { TDB_DATA key = locking_key(&id); - size_t refcount = static_share_mode_data_refcount; + size_t data_refcount, key_refcount; + struct share_mode_do_locked_state state = { + .key = key, .fn = fn, .private_data = private_data, + }; + NTSTATUS status; - if (static_share_mode_record != NULL) { - bool modified_dependent = false; - TDB_DATA static_key; - int cmp; + if (share_mode_lock_key_refcount == 0) { + status = g_lock_lock( + lock_ctx, + key, + G_LOCK_WRITE, + (struct timeval) { .tv_sec = 3600 }); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("g_lock_lock failed: %s\n", + nt_errstr(status)); + return status; + } + memcpy(share_mode_lock_key_data, key.dptr, key.dsize); + } - static_key = dbwrap_record_get_key(static_share_mode_record); + SMB_ASSERT(share_mode_lock_key_refcount < SIZE_MAX); + share_mode_lock_key_refcount += 1; - cmp = tdb_data_cmp(static_key, key); - if (cmp != 0) { - DBG_WARNING("Can not lock two share modes " - "simultaneously\n"); - return NT_STATUS_INVALID_LOCK_SEQUENCE; - } + key_refcount = share_mode_lock_key_refcount; + data_refcount = static_share_mode_data_refcount; - fn(static_share_mode_record_value.dptr, - static_share_mode_record_value.dsize, - &modified_dependent, - private_data); + status = g_lock_dump( + lock_ctx, key, share_mode_do_locked_fn, &state); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("g_lock_dump failed: %s\n", + nt_errstr(status)); + } - if (modified_dependent) { - dbwrap_watched_wakeup(static_share_mode_record); - } - } else { - struct share_mode_do_locked_state state = { - .fn = fn, .private_data = private_data, - }; - NTSTATUS status; + SMB_ASSERT(data_refcount == static_share_mode_data_refcount); + SMB_ASSERT(key_refcount == share_mode_lock_key_refcount); + share_mode_lock_key_refcount -= 1; - status = dbwrap_do_locked( - lock_db, key, share_mode_do_locked_fn, &state); + if (share_mode_lock_key_refcount == 0) { + status = g_lock_unlock(lock_ctx, key); if (!NT_STATUS_IS_OK(status)) { - DBG_WARNING("dbwrap_do_locked failed: %s\n", - nt_errstr(status)); - return status; + DBG_DEBUG("g_lock_unlock failed: %s\n", + nt_errstr(status)); } } - SMB_ASSERT(refcount == static_share_mode_data_refcount); - - return NT_STATUS_OK; + return status; } static void share_mode_wakeup_waiters_fn( @@ -841,25 +893,10 @@ bool share_mode_have_entries(struct share_mode_lock *lck) } struct share_mode_watch_state { - struct tevent_context *ev; bool blockerdead; struct server_id blocker; - struct tevent_req *subreq; }; -static void share_mode_watch_fn( - const uint8_t *buf, - size_t buflen, - bool *modified_dependent, - void *private_data) -{ - struct share_mode_watch_state *state = talloc_get_type_abort( - private_data, struct share_mode_watch_state); - - state->subreq = dbwrap_watched_watch_send( - state, state->ev, static_share_mode_record, state->blocker); -} - static void share_mode_watch_done(struct tevent_req *subreq); struct tevent_req *share_mode_watch_send( @@ -868,26 +905,21 @@ struct tevent_req *share_mode_watch_send( struct file_id id, struct server_id blocker) { - struct tevent_req *req = NULL; + TDB_DATA key = locking_key(&id); + struct tevent_req *req = NULL, *subreq = NULL; struct share_mode_watch_state *state = NULL; - NTSTATUS status; req = tevent_req_create( mem_ctx, &state, struct share_mode_watch_state); if (req == NULL) { return NULL; } - state->ev = ev; - state->blocker = blocker; - status = share_mode_do_locked(id, share_mode_watch_fn, state); - if (tevent_req_nterror(req, status)) { - return tevent_req_post(req, ev); - } - if (tevent_req_nomem(state->subreq, req)) { + subreq = g_lock_watch_data_send(state, ev, lock_ctx, key, blocker); + if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(state->subreq, share_mode_watch_done, req); + tevent_req_set_callback(subreq, share_mode_watch_done, req); return req; } @@ -899,7 +931,7 @@ static void share_mode_watch_done(struct tevent_req *subreq) req, struct share_mode_watch_state); NTSTATUS status; - status = dbwrap_watched_watch_recv( + status = g_lock_watch_data_recv( subreq, &state->blockerdead, &state->blocker); if (tevent_req_nterror(req, status)) { return; @@ -928,15 +960,21 @@ NTSTATUS share_mode_watch_recv( struct fetch_share_mode_unlocked_state { TALLOC_CTX *mem_ctx; + TDB_DATA key; struct share_mode_lock *lck; }; static void fetch_share_mode_unlocked_parser( - TDB_DATA key, TDB_DATA data, void *private_data) + struct server_id exclusive, + size_t num_shared, + struct server_id *shared, + const uint8_t *data, + size_t datalen, + void *private_data) { struct fetch_share_mode_unlocked_state *state = private_data; - if (data.dsize == 0) { + if (datalen == 0) { /* Likely a ctdb tombstone record, ignore it */ return; } @@ -948,7 +986,7 @@ static void fetch_share_mode_unlocked_parser( } state->lck->data = parse_share_modes( - state->lck, key, data.dptr, data.dsize); + state->lck, state->key, data, datalen); } /******************************************************************* @@ -959,27 +997,36 @@ static void fetch_share_mode_unlocked_parser( struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, struct file_id id) { - struct fetch_share_mode_unlocked_state state = { .mem_ctx = mem_ctx }; - TDB_DATA key = locking_key(&id); + struct fetch_share_mode_unlocked_state state = { + .mem_ctx = mem_ctx, + .key = locking_key(&id), + }; NTSTATUS status; - status = dbwrap_parse_record( - lock_db, key, fetch_share_mode_unlocked_parser, &state); + status = g_lock_dump( + lock_ctx, state.key, fetch_share_mode_unlocked_parser, &state); if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("g_lock_dump failed: %s\n", nt_errstr(status)); return NULL; } return state.lck; } -static void fetch_share_mode_done(struct tevent_req *subreq); - struct fetch_share_mode_state { struct file_id id; - TDB_DATA key; - struct fetch_share_mode_unlocked_state parser_state; - enum dbwrap_req_state req_state; + struct share_mode_lock *lck; + NTSTATUS status; }; +static void fetch_share_mode_fn( + struct server_id exclusive, + size_t num_shared, + struct server_id *shared, + const uint8_t *data, + size_t datalen, + void *private_data); +static void fetch_share_mode_done(struct tevent_req *subreq); + /** * @brief Get a share_mode_lock without locking or refcounting * @@ -1010,9 +1057,8 @@ struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx, struct file_id id, bool *queued) { - struct tevent_req *req = NULL; + struct tevent_req *req = NULL, *subreq = NULL; struct fetch_share_mode_state *state = NULL; - struct tevent_req *subreq = NULL; *queued = false; @@ -1021,43 +1067,61 @@ struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } - state->id = id; - state->key = locking_key(&state->id); - state->parser_state.mem_ctx = state; - - subreq = dbwrap_parse_record_send(state, - ev, - lock_db, - state->key, - fetch_share_mode_unlocked_parser, - &state->parser_state, - &state->req_state); + + subreq = g_lock_dump_send( + state, + ev, + lock_ctx, + locking_key(&id), + fetch_share_mode_fn, + state); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } tevent_req_set_callback(subreq, fetch_share_mode_done, req); + return req; +} + +static void fetch_share_mode_fn( + struct server_id exclusive, + size_t num_shared, + struct server_id *shared, + const uint8_t *data, + size_t datalen, + void *private_data) +{ + struct fetch_share_mode_state *state = talloc_get_type_abort( + private_data, struct fetch_share_mode_state); - if (state->req_state < DBWRAP_REQ_DISPATCHED) { - *queued = true; + state->lck = talloc(state, struct share_mode_lock); + if (state->lck == NULL) { + DBG_WARNING("talloc failed\n"); + state->status = NT_STATUS_NO_MEMORY; + return; } - return req; + + state->lck->data = parse_share_modes( + state->lck, locking_key(&state->id), data, datalen); } static void fetch_share_mode_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); + struct fetch_share_mode_state *state = tevent_req_data( + req, struct fetch_share_mode_state); NTSTATUS status; - status = dbwrap_parse_record_recv(subreq); + status = g_lock_dump_recv(subreq); TALLOC_FREE(subreq); if (tevent_req_nterror(req, status)) { return; } - + if (tevent_req_nterror(req, state->status)) { + return; + } tevent_req_done(req); - return; } NTSTATUS fetch_share_mode_recv(struct tevent_req *req, @@ -1075,12 +1139,12 @@ NTSTATUS fetch_share_mode_recv(struct tevent_req *req, return status; } - if (state->parser_state.lck->data == NULL) { + if (state->lck->data == NULL) { tevent_req_received(req); return NT_STATUS_NOT_FOUND; } - lck = talloc_move(mem_ctx, &state->parser_state.lck); + lck = talloc_move(mem_ctx, &state->lck); if (DEBUGLEVEL >= 10) { DBG_DEBUG("share_mode_data:\n"); @@ -1093,56 +1157,55 @@ NTSTATUS fetch_share_mode_recv(struct tevent_req *req, } struct share_mode_forall_state { - int (*fn)(struct file_id fid, const struct share_mode_data *data, + TDB_DATA key; + int (*fn)(struct file_id fid, + const struct share_mode_data *data, void *private_data); void *private_data; }; -static int share_mode_traverse_fn(struct db_record *rec, void *_state) +static void share_mode_forall_dump_fn( + struct server_id exclusive, + size_t num_shared, + struct server_id *shared, + const uint8_t *data, + size_t datalen, + void *private_data) { - struct share_mode_forall_state *state = - (struct share_mode_forall_state *)_state; - TDB_DATA key; - TDB_DATA value; - DATA_BLOB blob; - enum ndr_err_code ndr_err; - struct share_mode_data *d; + struct share_mode_forall_state *state = private_data; struct file_id fid; - int ret; - - key = dbwrap_record_get_key(rec); - value = dbwrap_record_get_value(rec); + struct share_mode_data *d; - /* Ensure this is a locking_key record. */ - if (key.dsize != sizeof(fid)) { - return 0; + if (state->key.dsize != sizeof(fid)) { + DBG_DEBUG("Got invalid key length %zu\n", state->key.dsize); + return; } - memcpy(&fid, key.dptr, sizeof(fid)); + memcpy(&fid, state->key.dptr, sizeof(fid)); - d = talloc(talloc_tos(), struct share_mode_data); + d = parse_share_modes(talloc_tos(), state->key, data, datalen); if (d == NULL) { - return 0; + DBG_DEBUG("parse_share_modes() failed\n"); + return; } - blob.data = value.dptr; - blob.length = value.dsize; - - ndr_err = ndr_pull_struct_blob_all( - &blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - DEBUG(1, ("ndr_pull_share_mode_lock failed\n")); - return 0; - } + state->fn(fid, d, state->private_data); + TALLOC_FREE(d); +} - if (DEBUGLEVEL > 10) { - DEBUG(11, ("parse_share_modes:\n")); - NDR_PRINT_DEBUG(share_mode_data, d); - } +static int share_mode_forall_fn(TDB_DATA key, void *private_data) +{ + struct share_mode_forall_state *state = private_data; + NTSTATUS status; - ret = state->fn(fid, d, state->private_data); + state->key = key; - TALLOC_FREE(d); - return ret; + status = g_lock_dump( + lock_ctx, key, share_mode_forall_dump_fn, private_data); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("g_lock_dump failed: %s\n", + nt_errstr(status)); + } + return 0; } int share_mode_forall(int (*fn)(struct file_id fid, @@ -1154,20 +1217,18 @@ int share_mode_forall(int (*fn)(struct file_id fid, .fn = fn, .private_data = private_data }; - NTSTATUS status; - int count; + int ret; - if (lock_db == NULL) { + if (lock_ctx == NULL) { return 0; } - status = dbwrap_traverse_read(lock_db, share_mode_traverse_fn, - &state, &count); - if (!NT_STATUS_IS_OK(status)) { - return -1; + ret = g_lock_locks( + lock_ctx, share_mode_forall_fn, &state); + if (ret < 0) { + DBG_DEBUG("g_lock_locks failed\n"); } - - return count; + return ret; } struct share_entry_forall_state { |