1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-26 10:04:02 +03:00

ctdb_freeze: Replace locking functions with locking API

Signed-off-by: Amitay Isaacs <amitay@gmail.com>

(This used to be ctdb commit 01ee86d2aafbcda658ef6acc2bba6d6781ae4047)
This commit is contained in:
Amitay Isaacs 2012-05-09 15:09:51 +10:00
parent cbf16856f8
commit 23f83d58a5

View File

@ -26,52 +26,6 @@
#include "db_wrap.h"
#include "../common/rb_tree.h"
static bool later_db(const char *name)
{
return (strstr(name, "notify") || strstr(name, "serverid"));
}
/*
lock all databases
*/
static int ctdb_lock_all_databases(struct ctdb_context *ctdb, uint32_t priority)
{
struct ctdb_db_context *ctdb_db;
/* REMOVE later */
/* This double loop is for backward compatibility and deadlock
avoidance for old samba versions that not yet support
the set prio call.
This code shall be removed later
*/
for (ctdb_db=ctdb->db_list;ctdb_db;ctdb_db=ctdb_db->next) {
if (ctdb_db->priority != priority) {
continue;
}
if (later_db(ctdb_db->db_name)) {
continue;
}
DEBUG(DEBUG_INFO,("locking database 0x%08x priority:%u %s\n", ctdb_db->db_id, ctdb_db->priority, ctdb_db->db_name));
if (tdb_lockall(ctdb_db->ltdb->tdb) != 0) {
DEBUG(DEBUG_ERR,(__location__ " Failed to lock database %s\n", ctdb_db->db_name));
return -1;
}
}
for (ctdb_db=ctdb->db_list;ctdb_db;ctdb_db=ctdb_db->next) {
if (ctdb_db->priority != priority) {
continue;
}
if (!later_db(ctdb_db->db_name)) {
continue;
}
DEBUG(DEBUG_INFO,("locking database 0x%08x priority:%u %s\n", ctdb_db->db_id, ctdb_db->priority, ctdb_db->db_name));
if (tdb_lockall(ctdb_db->ltdb->tdb) != 0) {
DEBUG(DEBUG_ERR,(__location__ " Failed to lock database %s\n", ctdb_db->db_name));
return -1;
}
}
return 0;
}
/*
a list of control requests waiting for a freeze lock child to get
the database locks
@ -88,8 +42,7 @@ struct ctdb_freeze_waiter {
struct ctdb_freeze_handle {
struct ctdb_context *ctdb;
uint32_t priority;
pid_t child;
int fd;
struct lock_request *lreq;
struct ctdb_freeze_waiter *waiters;
};
@ -122,18 +75,17 @@ static int ctdb_freeze_handle_destructor(struct ctdb_freeze_handle *h)
ctdb->freeze_mode[h->priority] = CTDB_FREEZE_NONE;
ctdb->freeze_handles[h->priority] = NULL;
ctdb_kill(h->ctdb, h->child, SIGKILL);
ctdb_lock_free_request_context(h->lreq);
return 0;
}
/*
called when the child writes its status to us
*/
static void ctdb_freeze_lock_handler(struct event_context *ev, struct fd_event *fde,
uint16_t flags, void *private_data)
static void ctdb_freeze_lock_handler(void *private_data, bool locked)
{
struct ctdb_freeze_handle *h = talloc_get_type(private_data, struct ctdb_freeze_handle);
int32_t status;
struct ctdb_freeze_handle *h = talloc_get_type_abort(private_data,
struct ctdb_freeze_handle);
struct ctdb_freeze_waiter *w;
if (h->ctdb->freeze_mode[h->priority] == CTDB_FREEZE_FROZEN) {
@ -142,12 +94,7 @@ static void ctdb_freeze_lock_handler(struct event_context *ev, struct fd_event *
return;
}
if (read(h->fd, &status, sizeof(status)) != sizeof(status)) {
DEBUG(DEBUG_ERR,("read error from freeze lock child\n"));
status = -1;
}
if (status == -1) {
if (!locked) {
DEBUG(DEBUG_ERR,("Failed to get locks in ctdb_freeze_child\n"));
/* we didn't get the locks - destroy the handle */
talloc_free(h);
@ -161,90 +108,12 @@ static void ctdb_freeze_lock_handler(struct event_context *ev, struct fd_event *
DEBUG(DEBUG_ERR,("lockwait finished but h is not linked\n"));
}
while ((w = h->waiters)) {
w->status = status;
w->status = 0;
DLIST_REMOVE(h->waiters, w);
talloc_free(w);
}
}
/*
create a child which gets locks on all the open databases, then calls the callback telling the parent
that it is done
*/
static struct ctdb_freeze_handle *ctdb_freeze_lock(struct ctdb_context *ctdb, uint32_t priority)
{
struct ctdb_freeze_handle *h;
int fd[2];
struct fd_event *fde;
h = talloc_zero(ctdb, struct ctdb_freeze_handle);
CTDB_NO_MEMORY_NULL(ctdb, h);
h->ctdb = ctdb;
h->priority = priority;
if (pipe(fd) == -1) {
DEBUG(DEBUG_ERR,("Failed to create pipe for ctdb_freeze_lock\n"));
talloc_free(h);
return NULL;
}
h->child = ctdb_fork(ctdb);
if (h->child == -1) {
DEBUG(DEBUG_ERR,("Failed to fork child for ctdb_freeze_lock\n"));
talloc_free(h);
return NULL;
}
if (h->child == 0) {
int ret;
/* in the child */
close(fd[0]);
debug_extra = talloc_asprintf(NULL, "freeze_lock-%u:", priority);
ret = ctdb_lock_all_databases(ctdb, priority);
if (ret != 0) {
_exit(0);
}
ret = write(fd[1], &ret, sizeof(ret));
if (ret != sizeof(ret)) {
DEBUG(DEBUG_ERR, (__location__ " Failed to write to socket from freeze child. ret:%d errno:%u\n", ret, errno));
_exit(1);
}
while (1) {
sleep(1);
if (ctdb_kill(ctdb, ctdb->ctdbd_pid, 0) != 0) {
DEBUG(DEBUG_ERR,("Parent died. Exiting lock wait child\n"));
_exit(0);
}
}
}
talloc_set_destructor(h, ctdb_freeze_handle_destructor);
close(fd[1]);
set_close_on_exec(fd[0]);
h->fd = fd[0];
fde = event_add_fd(ctdb->ev, h, h->fd, EVENT_FD_READ,
ctdb_freeze_lock_handler, h);
if (fde == NULL) {
DEBUG(DEBUG_ERR,("Failed to setup fd event for ctdb_freeze_lock\n"));
close(fd[0]);
talloc_free(h);
return NULL;
}
tevent_fd_set_auto_close(fde);
return h;
}
/*
destroy a waiter for a freeze mode change
*/
@ -259,6 +128,8 @@ static int ctdb_freeze_waiter_destructor(struct ctdb_freeze_waiter *w)
*/
int ctdb_start_freeze(struct ctdb_context *ctdb, uint32_t priority)
{
struct ctdb_freeze_handle *h;
if (priority == 0) {
DEBUG(DEBUG_ERR,("Freeze priority 0 requested, remapping to priority 1\n"));
priority = 1;
@ -279,8 +150,15 @@ int ctdb_start_freeze(struct ctdb_context *ctdb, uint32_t priority)
/* if there isn't a freeze lock child then create one */
if (ctdb->freeze_handles[priority] == NULL) {
ctdb->freeze_handles[priority] = ctdb_freeze_lock(ctdb, priority);
CTDB_NO_MEMORY(ctdb, ctdb->freeze_handles[priority]);
h = talloc_zero(ctdb, struct ctdb_freeze_handle);
CTDB_NO_MEMORY(ctdb, h);
h->ctdb = ctdb;
h->priority = priority;
talloc_set_destructor(h, ctdb_freeze_handle_destructor);
h->lreq = ctdb_lock_alldb_prio(ctdb, priority, false, ctdb_freeze_lock_handler, h);
CTDB_NO_MEMORY(ctdb, h->lreq);
ctdb->freeze_handles[priority] = h;
ctdb->freeze_mode[priority] = CTDB_FREEZE_PENDING;
}