summaryrefslogtreecommitdiff
path: root/lib/dbwrap
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2019-11-21 13:23:39 +0100
committerJeremy Allison <jra@samba.org>2020-05-15 00:48:32 +0000
commit38a80a300529719934bba135334506346a7a4a6f (patch)
treec97dc4b90d54ff8e9960c777f89ceea3ced2e29f /lib/dbwrap
parent01db877c7766387984ef32914eca0b2e817c4c6a (diff)
downloadsamba-38a80a300529719934bba135334506346a7a4a6f.tar.gz
dbwrap: Simplify dbwrap_lock_order_[un]lock()
Directly pass the database name and lock order to the core functions, avoid passing struct db_context. In the next steps these functions will become public: locking.tdb will be based on g_lock.c to avoid holding a tdb-level locking.tdb mutex while doing complex file system operations like unlink() which can take ages on FAT for example. This means that g_lock.c will participate in the dbwrap lock order protection and needs access to dbwrap_lock_order_[un]lock() without providing a direct db_context. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/dbwrap')
-rw-r--r--lib/dbwrap/dbwrap.c83
1 files changed, 49 insertions, 34 deletions
diff --git a/lib/dbwrap/dbwrap.c b/lib/dbwrap/dbwrap.c
index baab0338088..41be63d3f45 100644
--- a/lib/dbwrap/dbwrap.c
+++ b/lib/dbwrap/dbwrap.c
@@ -123,79 +123,96 @@ NTSTATUS dbwrap_record_delete(struct db_record *rec)
return NT_STATUS_OK;
}
-static void debug_lock_order(int level, struct db_context *dbs[])
+const char *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
+
+static void debug_lock_order(int level)
{
int i;
DEBUG(level, ("lock order: "));
for (i=0; i<DBWRAP_LOCK_ORDER_MAX; i++) {
- DEBUGADD(level, (" %d:%s", i + 1, dbs[i] ? dbs[i]->name : "<none>"));
+ DEBUGADD(level,
+ (" %d:%s",
+ i + 1,
+ locked_dbs[i] ? locked_dbs[i] : "<none>"));
}
DEBUGADD(level, ("\n"));
}
-static void dbwrap_lock_order_lock(struct db_context *db,
- struct db_context ***lockptr)
+static void dbwrap_lock_order_lock(const char *db_name,
+ enum dbwrap_lock_order lock_order)
{
- static struct db_context *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
int idx;
- DBG_INFO("check lock order %d for %s\n", (int)db->lock_order,
- db->name);
+ DBG_INFO("check lock order %d for %s\n",
+ (int)lock_order,
+ db_name);
- if (!DBWRAP_LOCK_ORDER_VALID(db->lock_order)) {
+ if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
DBG_ERR("Invalid lock order %d of %s\n",
- (int)db->lock_order, db->name);
+ lock_order,
+ db_name);
smb_panic("lock order violation");
}
- for (idx=db->lock_order-1; idx<DBWRAP_LOCK_ORDER_MAX; idx++) {
+ for (idx=lock_order-1; idx<DBWRAP_LOCK_ORDER_MAX; idx++) {
if (locked_dbs[idx] != NULL) {
DBG_ERR("Lock order violation: Trying %s at %d while "
"%s at %d is locked\n",
- db->name, (int)db->lock_order,
- locked_dbs[idx]->name, idx + 1);
- debug_lock_order(0, locked_dbs);
+ db_name,
+ (int)lock_order,
+ locked_dbs[idx],
+ idx + 1);
+ debug_lock_order(0);
smb_panic("lock order violation");
}
}
- locked_dbs[db->lock_order-1] = db;
- *lockptr = &locked_dbs[db->lock_order-1];
+ locked_dbs[lock_order-1] = db_name;
- debug_lock_order(10, locked_dbs);
+ debug_lock_order(10);
}
-static void dbwrap_lock_order_unlock(struct db_context *db,
- struct db_context **lockptr)
+static void dbwrap_lock_order_unlock(const char *db_name,
+ enum dbwrap_lock_order lock_order)
{
DBG_INFO("release lock order %d for %s\n",
- (int)db->lock_order, db->name);
+ (int)lock_order,
+ db_name);
+
+ if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
+ DBG_ERR("Invalid lock order %d of %s\n",
+ lock_order,
+ db_name);
+ smb_panic("lock order violation");
+ }
- if (*lockptr == NULL) {
- DBG_ERR("db %s at order %d unlocked\n", db->name,
- (int)db->lock_order);
+ if (locked_dbs[lock_order-1] == NULL) {
+ DBG_ERR("db %s at order %d unlocked\n",
+ db_name,
+ (int)lock_order);
smb_panic("lock order violation");
}
- if (*lockptr != db) {
+ if (locked_dbs[lock_order-1] != db_name) {
DBG_ERR("locked db at lock order %d is %s, expected %s\n",
- (int)(*lockptr)->lock_order, (*lockptr)->name,
- db->name);
+ (int)lock_order,
+ locked_dbs[lock_order-1],
+ db_name);
smb_panic("lock order violation");
}
- *lockptr = NULL;
+ locked_dbs[lock_order-1] = NULL;
}
struct dbwrap_lock_order_state {
struct db_context *db;
- struct db_context **lockptr;
};
static int dbwrap_lock_order_state_destructor(
struct dbwrap_lock_order_state *s)
{
- dbwrap_lock_order_unlock(s->db, s->lockptr);
+ struct db_context *db = s->db;
+ dbwrap_lock_order_unlock(db->name, db->lock_order);
return 0;
}
@@ -211,7 +228,7 @@ static struct dbwrap_lock_order_state *dbwrap_check_lock_order(
}
state->db = db;
- dbwrap_lock_order_lock(db, &state->lockptr);
+ dbwrap_lock_order_lock(db->name, db->lock_order);
talloc_set_destructor(state, dbwrap_lock_order_state_destructor);
return state;
@@ -540,18 +557,16 @@ NTSTATUS dbwrap_do_locked(struct db_context *db, TDB_DATA key,
struct db_record *rec;
if (db->do_locked != NULL) {
- struct db_context **lockptr = NULL;
NTSTATUS status;
if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
- dbwrap_lock_order_lock(db, &lockptr);
+ dbwrap_lock_order_lock(db->name, db->lock_order);
}
status = db->do_locked(db, key, fn, private_data);
- if (db->lock_order != DBWRAP_LOCK_ORDER_NONE &&
- lockptr != NULL) {
- dbwrap_lock_order_unlock(db, lockptr);
+ if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
+ dbwrap_lock_order_unlock(db->name, db->lock_order);
}
return status;