4 Copyright (C) Ronnie Sahlberg 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/time.h"
22 #include "system/network.h"
23 #include "system/filesys.h"
24 #include "system/wait.h"
25 #include "../include/ctdb_client.h"
26 #include "../include/ctdb_private.h"
30 ctdb_ban_node_event(struct event_context
*ev
, struct timed_event
*te
,
31 struct timeval t
, void *private_data
)
33 struct ctdb_context
*ctdb
= talloc_get_type(private_data
, struct ctdb_context
);
34 bool freeze_failed
= false;
37 /* Make sure we were able to freeze databases during banning */
38 for (i
=1; i
<=NUM_DB_PRIORITIES
; i
++) {
39 if (ctdb
->freeze_mode
[i
] != CTDB_FREEZE_FROZEN
) {
45 DEBUG(DEBUG_ERR
, ("Banning timedout, but still unable to freeze databases\n"));
50 DEBUG(DEBUG_ERR
,("Banning timedout\n"));
51 ctdb
->nodes
[ctdb
->pnn
]->flags
&= ~NODE_FLAGS_BANNED
;
53 if (ctdb
->banning_ctx
!= NULL
) {
54 talloc_free(ctdb
->banning_ctx
);
55 ctdb
->banning_ctx
= NULL
;
59 void ctdb_local_node_got_banned(struct ctdb_context
*ctdb
)
63 /* make sure we are frozen */
64 DEBUG(DEBUG_NOTICE
,("This node has been banned - forcing freeze and recovery\n"));
66 /* Reset the generation id to 1 to make us ignore any
67 REQ/REPLY CALL/DMASTER someone sends to us.
68 We are now banned so we shouldnt service database calls
71 ctdb
->vnn_map
->generation
= INVALID_GENERATION
;
73 ctdb
->recovery_mode
= CTDB_RECOVERY_ACTIVE
;
74 for (i
=1; i
<=NUM_DB_PRIORITIES
; i
++) {
75 ctdb_start_freeze(ctdb
, i
);
77 ctdb_release_all_ips(ctdb
);
80 int32_t ctdb_control_set_ban_state(struct ctdb_context
*ctdb
, TDB_DATA indata
)
82 struct ctdb_ban_time
*bantime
= (struct ctdb_ban_time
*)indata
.dptr
;
84 DEBUG(DEBUG_INFO
,("SET BAN STATE\n"));
86 if (bantime
->pnn
!= ctdb
->pnn
) {
87 if (bantime
->pnn
>= ctdb
->num_nodes
) {
88 DEBUG(DEBUG_ERR
,(__location__
" ERROR: Invalid ban request. PNN:%d is invalid. Max nodes %d\n", bantime
->pnn
, ctdb
->num_nodes
));
91 if (bantime
->time
== 0) {
92 DEBUG(DEBUG_NOTICE
,("unbanning node %d\n", bantime
->pnn
));
93 ctdb
->nodes
[bantime
->pnn
]->flags
&= ~NODE_FLAGS_BANNED
;
95 DEBUG(DEBUG_NOTICE
,("banning node %d\n", bantime
->pnn
));
96 if (ctdb
->tunable
.enable_bans
== 0) {
97 /* FIXME: This is bogus. We really should be
98 * taking decision based on the tunables on
99 * the banned node and not local node.
101 DEBUG(DEBUG_WARNING
,("Bans are disabled - ignoring ban of node %u\n", bantime
->pnn
));
105 ctdb
->nodes
[bantime
->pnn
]->flags
|= NODE_FLAGS_BANNED
;
110 if (ctdb
->banning_ctx
!= NULL
) {
111 talloc_free(ctdb
->banning_ctx
);
112 ctdb
->banning_ctx
= NULL
;
115 if (bantime
->time
== 0) {
116 DEBUG(DEBUG_ERR
,("Unbanning this node\n"));
117 ctdb
->nodes
[bantime
->pnn
]->flags
&= ~NODE_FLAGS_BANNED
;
121 if (ctdb
->tunable
.enable_bans
== 0) {
122 DEBUG(DEBUG_ERR
,("Bans are disabled - ignoring ban of node %u\n", bantime
->pnn
));
126 ctdb
->banning_ctx
= talloc(ctdb
, struct ctdb_ban_time
);
127 if (ctdb
->banning_ctx
== NULL
) {
128 DEBUG(DEBUG_CRIT
,(__location__
" ERROR Failed to allocate new banning state\n"));
131 *((struct ctdb_ban_time
*)(ctdb
->banning_ctx
)) = *bantime
;
134 DEBUG(DEBUG_ERR
,("Banning this node for %d seconds\n", bantime
->time
));
135 ctdb
->nodes
[bantime
->pnn
]->flags
|= NODE_FLAGS_BANNED
;
137 event_add_timed(ctdb
->ev
, ctdb
->banning_ctx
, timeval_current_ofs(bantime
->time
,0), ctdb_ban_node_event
, ctdb
);
139 ctdb_local_node_got_banned(ctdb
);
143 int32_t ctdb_control_get_ban_state(struct ctdb_context
*ctdb
, TDB_DATA
*outdata
)
145 struct ctdb_ban_time
*bantime
;
147 bantime
= talloc(outdata
, struct ctdb_ban_time
);
148 CTDB_NO_MEMORY(ctdb
, bantime
);
150 if (ctdb
->banning_ctx
!= NULL
) {
151 *bantime
= *(struct ctdb_ban_time
*)(ctdb
->banning_ctx
);
153 bantime
->pnn
= ctdb
->pnn
;
157 outdata
->dptr
= (uint8_t *)bantime
;
158 outdata
->dsize
= sizeof(struct ctdb_ban_time
);
163 /* Routine to ban ourselves for a while when trouble strikes. */
164 void ctdb_ban_self(struct ctdb_context
*ctdb
)
167 struct ctdb_ban_time bantime
;
169 bantime
.pnn
= ctdb
->pnn
;
170 bantime
.time
= ctdb
->tunable
.recovery_ban_period
;
172 data
.dsize
= sizeof(bantime
);
173 data
.dptr
= (uint8_t *)&bantime
;
175 ctdb_control_set_ban_state(ctdb
, data
);