Deleted Added
full compact
hastd.c (210883) hastd.c (210886)
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * All rights reserved.
4 *
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:

--- 12 unchanged lines hidden (view full) ---

23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
4 * All rights reserved.
5 *
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:

--- 12 unchanged lines hidden (view full) ---

24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sbin/hastd/hastd.c 210883 2010-08-05 19:08:54Z pjd $");
32__FBSDID("$FreeBSD: head/sbin/hastd/hastd.c 210886 2010-08-05 19:16:31Z pjd $");
32
33#include <sys/param.h>
34#include <sys/linker.h>
35#include <sys/module.h>
36#include <sys/wait.h>
37
38#include <assert.h>
39#include <err.h>

--- 12 unchanged lines hidden (view full) ---

52
53#include "control.h"
54#include "hast.h"
55#include "hast_proto.h"
56#include "hastd.h"
57#include "subr.h"
58
59/* Path to configuration file. */
33
34#include <sys/param.h>
35#include <sys/linker.h>
36#include <sys/module.h>
37#include <sys/wait.h>
38
39#include <assert.h>
40#include <err.h>

--- 12 unchanged lines hidden (view full) ---

53
54#include "control.h"
55#include "hast.h"
56#include "hast_proto.h"
57#include "hastd.h"
58#include "subr.h"
59
60/* Path to configuration file. */
60static const char *cfgpath = HAST_CONFIG;
61const char *cfgpath = HAST_CONFIG;
61/* Hastd configuration. */
62static struct hastd_config *cfg;
63/* Was SIGCHLD signal received? */
64static bool sigchld_received = false;
65/* Was SIGHUP signal received? */
62/* Hastd configuration. */
63static struct hastd_config *cfg;
64/* Was SIGCHLD signal received? */
65static bool sigchld_received = false;
66/* Was SIGHUP signal received? */
66static bool sighup_received = false;
67bool sighup_received = false;
67/* Was SIGINT or SIGTERM signal received? */
68bool sigexit_received = false;
69/* PID file handle. */
70struct pidfh *pfh;
71
72static void
73usage(void)
74{

--- 89 unchanged lines hidden (view full) ---

164 pjdlog_info("Changing resource role back to %s.",
165 role2str(res->hr_role));
166 }
167 }
168 pjdlog_prefix_set("%s", "");
169 }
170}
171
68/* Was SIGINT or SIGTERM signal received? */
69bool sigexit_received = false;
70/* PID file handle. */
71struct pidfh *pfh;
72
73static void
74usage(void)
75{

--- 89 unchanged lines hidden (view full) ---

165 pjdlog_info("Changing resource role back to %s.",
166 role2str(res->hr_role));
167 }
168 }
169 pjdlog_prefix_set("%s", "");
170 }
171}
172
173static bool
174resource_needs_restart(const struct hast_resource *res0,
175 const struct hast_resource *res1)
176{
177
178 assert(strcmp(res0->hr_name, res1->hr_name) == 0);
179
180 if (strcmp(res0->hr_provname, res1->hr_provname) != 0)
181 return (true);
182 if (strcmp(res0->hr_localpath, res1->hr_localpath) != 0)
183 return (true);
184 if (res0->hr_role == HAST_ROLE_INIT ||
185 res0->hr_role == HAST_ROLE_SECONDARY) {
186 if (strcmp(res0->hr_remoteaddr, res1->hr_remoteaddr) != 0)
187 return (true);
188 if (res0->hr_replication != res1->hr_replication)
189 return (true);
190 if (res0->hr_timeout != res1->hr_timeout)
191 return (true);
192 }
193 return (false);
194}
195
196static bool
197resource_needs_reload(const struct hast_resource *res0,
198 const struct hast_resource *res1)
199{
200
201 assert(strcmp(res0->hr_name, res1->hr_name) == 0);
202 assert(strcmp(res0->hr_provname, res1->hr_provname) == 0);
203 assert(strcmp(res0->hr_localpath, res1->hr_localpath) == 0);
204
205 if (res0->hr_role != HAST_ROLE_PRIMARY)
206 return (false);
207
208 if (strcmp(res0->hr_remoteaddr, res1->hr_remoteaddr) != 0)
209 return (true);
210 if (res0->hr_replication != res1->hr_replication)
211 return (true);
212 if (res0->hr_timeout != res1->hr_timeout)
213 return (true);
214 return (false);
215}
216
172static void
173hastd_reload(void)
174{
217static void
218hastd_reload(void)
219{
220 struct hastd_config *newcfg;
221 struct hast_resource *nres, *cres, *tres;
222 uint8_t role;
175
223
176 /* TODO */
177 pjdlog_warning("Configuration reload is not implemented.");
224 pjdlog_info("Reloading configuration...");
225
226 newcfg = yy_config_parse(cfgpath, false);
227 if (newcfg == NULL)
228 goto failed;
229
230 /*
231 * Check if control address has changed.
232 */
233 if (strcmp(cfg->hc_controladdr, newcfg->hc_controladdr) != 0) {
234 if (proto_server(newcfg->hc_controladdr,
235 &newcfg->hc_controlconn) < 0) {
236 pjdlog_errno(LOG_ERR,
237 "Unable to listen on control address %s",
238 newcfg->hc_controladdr);
239 goto failed;
240 }
241 }
242 /*
243 * Check if listen address has changed.
244 */
245 if (strcmp(cfg->hc_listenaddr, newcfg->hc_listenaddr) != 0) {
246 if (proto_server(newcfg->hc_listenaddr,
247 &newcfg->hc_listenconn) < 0) {
248 pjdlog_errno(LOG_ERR, "Unable to listen on address %s",
249 newcfg->hc_listenaddr);
250 goto failed;
251 }
252 }
253 /*
254 * Only when both control and listen sockets are successfully
255 * initialized switch them to new configuration.
256 */
257 if (newcfg->hc_controlconn != NULL) {
258 pjdlog_info("Control socket changed from %s to %s.",
259 cfg->hc_controladdr, newcfg->hc_controladdr);
260 proto_close(cfg->hc_controlconn);
261 cfg->hc_controlconn = newcfg->hc_controlconn;
262 newcfg->hc_controlconn = NULL;
263 strlcpy(cfg->hc_controladdr, newcfg->hc_controladdr,
264 sizeof(cfg->hc_controladdr));
265 }
266 if (newcfg->hc_listenconn != NULL) {
267 pjdlog_info("Listen socket changed from %s to %s.",
268 cfg->hc_listenaddr, newcfg->hc_listenaddr);
269 proto_close(cfg->hc_listenconn);
270 cfg->hc_listenconn = newcfg->hc_listenconn;
271 newcfg->hc_listenconn = NULL;
272 strlcpy(cfg->hc_listenaddr, newcfg->hc_listenaddr,
273 sizeof(cfg->hc_listenaddr));
274 }
275
276 /*
277 * Stop and remove resources that were removed from the configuration.
278 */
279 TAILQ_FOREACH_SAFE(cres, &cfg->hc_resources, hr_next, tres) {
280 TAILQ_FOREACH(nres, &newcfg->hc_resources, hr_next) {
281 if (strcmp(cres->hr_name, nres->hr_name) == 0)
282 break;
283 }
284 if (nres == NULL) {
285 control_set_role(cres, HAST_ROLE_INIT);
286 TAILQ_REMOVE(&cfg->hc_resources, cres, hr_next);
287 pjdlog_info("Resource %s removed.", cres->hr_name);
288 free(cres);
289 }
290 }
291 /*
292 * Move new resources to the current configuration.
293 */
294 TAILQ_FOREACH_SAFE(nres, &newcfg->hc_resources, hr_next, tres) {
295 TAILQ_FOREACH(cres, &cfg->hc_resources, hr_next) {
296 if (strcmp(cres->hr_name, nres->hr_name) == 0)
297 break;
298 }
299 if (cres == NULL) {
300 TAILQ_REMOVE(&newcfg->hc_resources, nres, hr_next);
301 TAILQ_INSERT_TAIL(&cfg->hc_resources, nres, hr_next);
302 pjdlog_info("Resource %s added.", nres->hr_name);
303 }
304 }
305 /*
306 * Deal with modified resources.
307 * Depending on what has changed exactly we might want to perform
308 * different actions.
309 *
310 * We do full resource restart in the following situations:
311 * Resource role is INIT or SECONDARY.
312 * Resource role is PRIMARY and path to local component or provider
313 * name has changed.
314 * In case of PRIMARY, the worker process will be killed and restarted,
315 * which also means removing /dev/hast/<name> provider and
316 * recreating it.
317 *
318 * We do just reload (send SIGHUP to worker process) if we act as
319 * PRIMARY, but only remote address, replication mode and timeout
320 * has changed. For those, there is no need to restart worker process.
321 * If PRIMARY receives SIGHUP, it will reconnect if remote address or
322 * replication mode has changed or simply set new timeout if only
323 * timeout has changed.
324 */
325 TAILQ_FOREACH_SAFE(nres, &newcfg->hc_resources, hr_next, tres) {
326 TAILQ_FOREACH(cres, &cfg->hc_resources, hr_next) {
327 if (strcmp(cres->hr_name, nres->hr_name) == 0)
328 break;
329 }
330 assert(cres != NULL);
331 if (resource_needs_restart(cres, nres)) {
332 pjdlog_info("Resource %s configuration was modified, restarting it.",
333 cres->hr_name);
334 role = cres->hr_role;
335 control_set_role(cres, HAST_ROLE_INIT);
336 TAILQ_REMOVE(&cfg->hc_resources, cres, hr_next);
337 free(cres);
338 TAILQ_REMOVE(&newcfg->hc_resources, nres, hr_next);
339 TAILQ_INSERT_TAIL(&cfg->hc_resources, nres, hr_next);
340 control_set_role(nres, role);
341 } else if (resource_needs_reload(cres, nres)) {
342 pjdlog_info("Resource %s configuration was modified, reloading it.",
343 cres->hr_name);
344 strlcpy(cres->hr_remoteaddr, nres->hr_remoteaddr,
345 sizeof(cres->hr_remoteaddr));
346 cres->hr_replication = nres->hr_replication;
347 cres->hr_timeout = nres->hr_timeout;
348 if (cres->hr_workerpid != 0) {
349 if (kill(cres->hr_workerpid, SIGHUP) < 0) {
350 pjdlog_errno(LOG_WARNING,
351 "Unable to send SIGHUP to worker process %u",
352 (unsigned int)cres->hr_workerpid);
353 }
354 }
355 }
356 }
357
358 yy_config_free(newcfg);
359 pjdlog_info("Configuration reloaded successfully.");
360 return;
361failed:
362 if (newcfg != NULL) {
363 if (newcfg->hc_controlconn != NULL)
364 proto_close(newcfg->hc_controlconn);
365 if (newcfg->hc_listenconn != NULL)
366 proto_close(newcfg->hc_listenconn);
367 yy_config_free(newcfg);
368 }
369 pjdlog_warning("Configuration not reloaded.");
178}
179
180static void
181listen_accept(void)
182{
183 struct hast_resource *res;
184 struct proto_conn *conn;
185 struct nv *nvin, *nvout, *nverr;

--- 211 unchanged lines hidden (view full) ---

397}
398
399static void
400main_loop(void)
401{
402 fd_set rfds, wfds;
403 int cfd, lfd, maxfd, ret;
404
370}
371
372static void
373listen_accept(void)
374{
375 struct hast_resource *res;
376 struct proto_conn *conn;
377 struct nv *nvin, *nvout, *nverr;

--- 211 unchanged lines hidden (view full) ---

589}
590
591static void
592main_loop(void)
593{
594 fd_set rfds, wfds;
595 int cfd, lfd, maxfd, ret;
596
405 cfd = proto_descriptor(cfg->hc_controlconn);
406 lfd = proto_descriptor(cfg->hc_listenconn);
407 maxfd = cfd > lfd ? cfd : lfd;
408
409 for (;;) {
410 if (sigchld_received) {
411 sigchld_received = false;
412 child_exit();
413 }
414 if (sighup_received) {
415 sighup_received = false;
416 hastd_reload();
417 }
418
597 for (;;) {
598 if (sigchld_received) {
599 sigchld_received = false;
600 child_exit();
601 }
602 if (sighup_received) {
603 sighup_received = false;
604 hastd_reload();
605 }
606
607 cfd = proto_descriptor(cfg->hc_controlconn);
608 lfd = proto_descriptor(cfg->hc_listenconn);
609 maxfd = cfd > lfd ? cfd : lfd;
610
419 /* Setup descriptors for select(2). */
420 FD_ZERO(&rfds);
421 FD_SET(cfd, &rfds);
422 FD_SET(lfd, &rfds);
423 FD_ZERO(&wfds);
424 FD_SET(cfd, &wfds);
425 FD_SET(lfd, &wfds);
426

--- 108 unchanged lines hidden ---
611 /* Setup descriptors for select(2). */
612 FD_ZERO(&rfds);
613 FD_SET(cfd, &rfds);
614 FD_SET(lfd, &rfds);
615 FD_ZERO(&wfds);
616 FD_SET(cfd, &wfds);
617 FD_SET(lfd, &wfds);
618

--- 108 unchanged lines hidden ---