mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
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>
This commit is contained in:
parent
01db877c77
commit
38a80a3005
@ -123,79 +123,96 @@ NTSTATUS dbwrap_record_delete(struct db_record *rec)
|
|||||||
return NT_STATUS_OK;
|
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;
|
int i;
|
||||||
DEBUG(level, ("lock order: "));
|
DEBUG(level, ("lock order: "));
|
||||||
for (i=0; i<DBWRAP_LOCK_ORDER_MAX; i++) {
|
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"));
|
DEBUGADD(level, ("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dbwrap_lock_order_lock(struct db_context *db,
|
static void dbwrap_lock_order_lock(const char *db_name,
|
||||||
struct db_context ***lockptr)
|
enum dbwrap_lock_order lock_order)
|
||||||
{
|
{
|
||||||
static struct db_context *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
|
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
DBG_INFO("check lock order %d for %s\n", (int)db->lock_order,
|
DBG_INFO("check lock order %d for %s\n",
|
||||||
db->name);
|
(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",
|
DBG_ERR("Invalid lock order %d of %s\n",
|
||||||
(int)db->lock_order, db->name);
|
lock_order,
|
||||||
|
db_name);
|
||||||
smb_panic("lock order violation");
|
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) {
|
if (locked_dbs[idx] != NULL) {
|
||||||
DBG_ERR("Lock order violation: Trying %s at %d while "
|
DBG_ERR("Lock order violation: Trying %s at %d while "
|
||||||
"%s at %d is locked\n",
|
"%s at %d is locked\n",
|
||||||
db->name, (int)db->lock_order,
|
db_name,
|
||||||
locked_dbs[idx]->name, idx + 1);
|
(int)lock_order,
|
||||||
debug_lock_order(0, locked_dbs);
|
locked_dbs[idx],
|
||||||
|
idx + 1);
|
||||||
|
debug_lock_order(0);
|
||||||
smb_panic("lock order violation");
|
smb_panic("lock order violation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
locked_dbs[db->lock_order-1] = db;
|
locked_dbs[lock_order-1] = db_name;
|
||||||
*lockptr = &locked_dbs[db->lock_order-1];
|
|
||||||
|
|
||||||
debug_lock_order(10, locked_dbs);
|
debug_lock_order(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dbwrap_lock_order_unlock(struct db_context *db,
|
static void dbwrap_lock_order_unlock(const char *db_name,
|
||||||
struct db_context **lockptr)
|
enum dbwrap_lock_order lock_order)
|
||||||
{
|
{
|
||||||
DBG_INFO("release lock order %d for %s\n",
|
DBG_INFO("release lock order %d for %s\n",
|
||||||
(int)db->lock_order, db->name);
|
(int)lock_order,
|
||||||
|
db_name);
|
||||||
|
|
||||||
if (*lockptr == NULL) {
|
if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
|
||||||
DBG_ERR("db %s at order %d unlocked\n", db->name,
|
DBG_ERR("Invalid lock order %d of %s\n",
|
||||||
(int)db->lock_order);
|
lock_order,
|
||||||
|
db_name);
|
||||||
smb_panic("lock order violation");
|
smb_panic("lock order violation");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*lockptr != db) {
|
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 (locked_dbs[lock_order-1] != db_name) {
|
||||||
DBG_ERR("locked db at lock order %d is %s, expected %s\n",
|
DBG_ERR("locked db at lock order %d is %s, expected %s\n",
|
||||||
(int)(*lockptr)->lock_order, (*lockptr)->name,
|
(int)lock_order,
|
||||||
db->name);
|
locked_dbs[lock_order-1],
|
||||||
|
db_name);
|
||||||
smb_panic("lock order violation");
|
smb_panic("lock order violation");
|
||||||
}
|
}
|
||||||
|
|
||||||
*lockptr = NULL;
|
locked_dbs[lock_order-1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dbwrap_lock_order_state {
|
struct dbwrap_lock_order_state {
|
||||||
struct db_context *db;
|
struct db_context *db;
|
||||||
struct db_context **lockptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dbwrap_lock_order_state_destructor(
|
static int dbwrap_lock_order_state_destructor(
|
||||||
struct dbwrap_lock_order_state *s)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +228,7 @@ static struct dbwrap_lock_order_state *dbwrap_check_lock_order(
|
|||||||
}
|
}
|
||||||
state->db = db;
|
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);
|
talloc_set_destructor(state, dbwrap_lock_order_state_destructor);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@ -540,18 +557,16 @@ NTSTATUS dbwrap_do_locked(struct db_context *db, TDB_DATA key,
|
|||||||
struct db_record *rec;
|
struct db_record *rec;
|
||||||
|
|
||||||
if (db->do_locked != NULL) {
|
if (db->do_locked != NULL) {
|
||||||
struct db_context **lockptr = NULL;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
|
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);
|
status = db->do_locked(db, key, fn, private_data);
|
||||||
|
|
||||||
if (db->lock_order != DBWRAP_LOCK_ORDER_NONE &&
|
if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
|
||||||
lockptr != NULL) {
|
dbwrap_lock_order_unlock(db->name, db->lock_order);
|
||||||
dbwrap_lock_order_unlock(db, lockptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
Loading…
Reference in New Issue
Block a user