Deleted Added
full compact
secondary.c (229744) secondary.c (229945)
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
4 * All rights reserved.
5 *
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
8 *

--- 15 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>
1/*-
2 * Copyright (c) 2009-2010 The FreeBSD Foundation
3 * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
4 * All rights reserved.
5 *
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
8 *

--- 15 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>
32__FBSDID("$FreeBSD: head/sbin/hastd/secondary.c 229744 2012-01-06 23:44:26Z pjd $");
32__FBSDID("$FreeBSD: head/sbin/hastd/secondary.c 229945 2012-01-10 22:39:07Z pjd $");
33
34#include <sys/param.h>
35#include <sys/time.h>
36#include <sys/bio.h>
37#include <sys/disk.h>
38#include <sys/stat.h>
39
40#include <err.h>

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

176 TAILQ_INSERT_HEAD(&hio_free_list, hio, hio_next);
177 }
178}
179
180static void
181init_local(struct hast_resource *res)
182{
183
33
34#include <sys/param.h>
35#include <sys/time.h>
36#include <sys/bio.h>
37#include <sys/disk.h>
38#include <sys/stat.h>
39
40#include <err.h>

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

176 TAILQ_INSERT_HEAD(&hio_free_list, hio, hio_next);
177 }
178}
179
180static void
181init_local(struct hast_resource *res)
182{
183
184 if (metadata_read(res, true) < 0)
184 if (metadata_read(res, true) == -1)
185 exit(EX_NOINPUT);
186}
187
188static void
189init_remote(struct hast_resource *res, struct nv *nvin)
190{
191 uint64_t resuid;
192 struct nv *nvout;

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

257 /*
258 * Provider is used for the first time. If primary node done no
259 * writes yet as well (we will find "virgin" argument) then
260 * there is no need to synchronize anything. If primary node
261 * done any writes already we have to synchronize everything.
262 */
263 PJDLOG_ASSERT(res->hr_secondary_localcnt == 0);
264 res->hr_resuid = resuid;
185 exit(EX_NOINPUT);
186}
187
188static void
189init_remote(struct hast_resource *res, struct nv *nvin)
190{
191 uint64_t resuid;
192 struct nv *nvout;

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

257 /*
258 * Provider is used for the first time. If primary node done no
259 * writes yet as well (we will find "virgin" argument) then
260 * there is no need to synchronize anything. If primary node
261 * done any writes already we have to synchronize everything.
262 */
263 PJDLOG_ASSERT(res->hr_secondary_localcnt == 0);
264 res->hr_resuid = resuid;
265 if (metadata_write(res) < 0)
265 if (metadata_write(res) == -1)
266 exit(EX_NOINPUT);
267 if (nv_exists(nvin, "virgin")) {
268 free(map);
269 map = NULL;
270 mapsize = 0;
271 } else {
272 memset(map, 0xff, mapsize);
273 }
274 nv_add_int8(nvout, 1, "virgin");
275 nv_add_uint8(nvout, HAST_SYNCSRC_PRIMARY, "syncsrc");
276 } else if (res->hr_resuid != resuid) {
277 char errmsg[256];
278
279 free(map);
280 (void)snprintf(errmsg, sizeof(errmsg),
281 "Resource unique ID mismatch (primary=%ju, secondary=%ju).",
282 (uintmax_t)resuid, (uintmax_t)res->hr_resuid);
283 pjdlog_error("%s", errmsg);
284 nv_add_string(nvout, errmsg, "errmsg");
266 exit(EX_NOINPUT);
267 if (nv_exists(nvin, "virgin")) {
268 free(map);
269 map = NULL;
270 mapsize = 0;
271 } else {
272 memset(map, 0xff, mapsize);
273 }
274 nv_add_int8(nvout, 1, "virgin");
275 nv_add_uint8(nvout, HAST_SYNCSRC_PRIMARY, "syncsrc");
276 } else if (res->hr_resuid != resuid) {
277 char errmsg[256];
278
279 free(map);
280 (void)snprintf(errmsg, sizeof(errmsg),
281 "Resource unique ID mismatch (primary=%ju, secondary=%ju).",
282 (uintmax_t)resuid, (uintmax_t)res->hr_resuid);
283 pjdlog_error("%s", errmsg);
284 nv_add_string(nvout, errmsg, "errmsg");
285 if (hast_proto_send(res, res->hr_remotein, nvout, NULL, 0) < 0) {
285 if (hast_proto_send(res, res->hr_remotein, nvout, NULL, 0) == -1) {
286 pjdlog_exit(EX_TEMPFAIL, "Unable to send response to %s",
287 res->hr_remoteaddr);
288 }
289 nv_free(nvout);
290 exit(EX_CONFIG);
291 } else if (
292 /* Is primary out-of-date? */
293 (res->hr_secondary_localcnt > res->hr_primary_remotecnt &&

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

322 } else if (res->hr_secondary_localcnt > res->hr_primary_remotecnt &&
323 res->hr_primary_localcnt > res->hr_secondary_remotecnt) {
324 /*
325 * Not good, we have split-brain condition.
326 */
327 free(map);
328 pjdlog_error("Split-brain detected, exiting.");
329 nv_add_string(nvout, "Split-brain condition!", "errmsg");
286 pjdlog_exit(EX_TEMPFAIL, "Unable to send response to %s",
287 res->hr_remoteaddr);
288 }
289 nv_free(nvout);
290 exit(EX_CONFIG);
291 } else if (
292 /* Is primary out-of-date? */
293 (res->hr_secondary_localcnt > res->hr_primary_remotecnt &&

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

322 } else if (res->hr_secondary_localcnt > res->hr_primary_remotecnt &&
323 res->hr_primary_localcnt > res->hr_secondary_remotecnt) {
324 /*
325 * Not good, we have split-brain condition.
326 */
327 free(map);
328 pjdlog_error("Split-brain detected, exiting.");
329 nv_add_string(nvout, "Split-brain condition!", "errmsg");
330 if (hast_proto_send(res, res->hr_remotein, nvout, NULL, 0) < 0) {
330 if (hast_proto_send(res, res->hr_remotein, nvout, NULL, 0) == -1) {
331 pjdlog_exit(EX_TEMPFAIL, "Unable to send response to %s",
332 res->hr_remoteaddr);
333 }
334 nv_free(nvout);
335 /* Exit on split-brain. */
336 event_send(res, EVENT_SPLITBRAIN);
337 exit(EX_CONFIG);
338 } else /* if (res->hr_secondary_localcnt < res->hr_primary_remotecnt ||

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

356 }
357 pjdlog_warning("This should never happen, asking for full synchronization (primary(local=%ju, remote=%ju), secondary(local=%ju, remote=%ju)).",
358 (uintmax_t)res->hr_primary_localcnt,
359 (uintmax_t)res->hr_primary_remotecnt,
360 (uintmax_t)res->hr_secondary_localcnt,
361 (uintmax_t)res->hr_secondary_remotecnt);
362 }
363 nv_add_uint32(nvout, (uint32_t)mapsize, "mapsize");
331 pjdlog_exit(EX_TEMPFAIL, "Unable to send response to %s",
332 res->hr_remoteaddr);
333 }
334 nv_free(nvout);
335 /* Exit on split-brain. */
336 event_send(res, EVENT_SPLITBRAIN);
337 exit(EX_CONFIG);
338 } else /* if (res->hr_secondary_localcnt < res->hr_primary_remotecnt ||

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

356 }
357 pjdlog_warning("This should never happen, asking for full synchronization (primary(local=%ju, remote=%ju), secondary(local=%ju, remote=%ju)).",
358 (uintmax_t)res->hr_primary_localcnt,
359 (uintmax_t)res->hr_primary_remotecnt,
360 (uintmax_t)res->hr_secondary_localcnt,
361 (uintmax_t)res->hr_secondary_remotecnt);
362 }
363 nv_add_uint32(nvout, (uint32_t)mapsize, "mapsize");
364 if (hast_proto_send(res, res->hr_remotein, nvout, map, mapsize) < 0) {
364 if (hast_proto_send(res, res->hr_remotein, nvout, map, mapsize) == -1) {
365 pjdlog_exit(EX_TEMPFAIL, "Unable to send activemap to %s",
366 res->hr_remoteaddr);
367 }
368 if (map != NULL)
369 free(map);
370 nv_free(nvout);
371#ifdef notyet
372 /* Setup direction. */

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

381 sigset_t mask;
382 pthread_t td;
383 pid_t pid;
384 int error, mode, debuglevel;
385
386 /*
387 * Create communication channel between parent and child.
388 */
365 pjdlog_exit(EX_TEMPFAIL, "Unable to send activemap to %s",
366 res->hr_remoteaddr);
367 }
368 if (map != NULL)
369 free(map);
370 nv_free(nvout);
371#ifdef notyet
372 /* Setup direction. */

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

381 sigset_t mask;
382 pthread_t td;
383 pid_t pid;
384 int error, mode, debuglevel;
385
386 /*
387 * Create communication channel between parent and child.
388 */
389 if (proto_client(NULL, "socketpair://", &res->hr_ctrl) < 0) {
389 if (proto_client(NULL, "socketpair://", &res->hr_ctrl) == -1) {
390 KEEP_ERRNO((void)pidfile_remove(pfh));
391 pjdlog_exit(EX_OSERR,
392 "Unable to create control sockets between parent and child");
393 }
394 /*
395 * Create communication channel between child and parent.
396 */
390 KEEP_ERRNO((void)pidfile_remove(pfh));
391 pjdlog_exit(EX_OSERR,
392 "Unable to create control sockets between parent and child");
393 }
394 /*
395 * Create communication channel between child and parent.
396 */
397 if (proto_client(NULL, "socketpair://", &res->hr_event) < 0) {
397 if (proto_client(NULL, "socketpair://", &res->hr_event) == -1) {
398 KEEP_ERRNO((void)pidfile_remove(pfh));
399 pjdlog_exit(EX_OSERR,
400 "Unable to create event sockets between child and parent");
401 }
402
403 pid = fork();
404 if (pid == -1) {
405 KEEP_ERRNO((void)pidfile_remove(pfh));

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

436 pjdlog_debug_set(debuglevel);
437 pjdlog_prefix_set("[%s] (%s) ", res->hr_name, role2str(res->hr_role));
438 setproctitle("%s (%s)", res->hr_name, role2str(res->hr_role));
439
440 PJDLOG_VERIFY(sigemptyset(&mask) == 0);
441 PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
442
443 /* Error in setting timeout is not critical, but why should it fail? */
398 KEEP_ERRNO((void)pidfile_remove(pfh));
399 pjdlog_exit(EX_OSERR,
400 "Unable to create event sockets between child and parent");
401 }
402
403 pid = fork();
404 if (pid == -1) {
405 KEEP_ERRNO((void)pidfile_remove(pfh));

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

436 pjdlog_debug_set(debuglevel);
437 pjdlog_prefix_set("[%s] (%s) ", res->hr_name, role2str(res->hr_role));
438 setproctitle("%s (%s)", res->hr_name, role2str(res->hr_role));
439
440 PJDLOG_VERIFY(sigemptyset(&mask) == 0);
441 PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
442
443 /* Error in setting timeout is not critical, but why should it fail? */
444 if (proto_timeout(res->hr_remotein, 2 * HAST_KEEPALIVE) < 0)
444 if (proto_timeout(res->hr_remotein, 2 * HAST_KEEPALIVE) == -1)
445 pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
445 pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
446 if (proto_timeout(res->hr_remoteout, res->hr_timeout) < 0)
446 if (proto_timeout(res->hr_remoteout, res->hr_timeout) == -1)
447 pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
448
449 init_local(res);
450 init_environment();
451
452 if (drop_privs(res) != 0)
453 exit(EX_CONFIG);
454 pjdlog_info("Privileges successfully dropped.");

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

618 struct hast_resource *res = arg;
619 struct hio *hio;
620 struct nv *nv;
621
622 for (;;) {
623 pjdlog_debug(2, "recv: Taking free request.");
624 QUEUE_TAKE(free, hio);
625 pjdlog_debug(2, "recv: (%p) Got request.", hio);
447 pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
448
449 init_local(res);
450 init_environment();
451
452 if (drop_privs(res) != 0)
453 exit(EX_CONFIG);
454 pjdlog_info("Privileges successfully dropped.");

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

618 struct hast_resource *res = arg;
619 struct hio *hio;
620 struct nv *nv;
621
622 for (;;) {
623 pjdlog_debug(2, "recv: Taking free request.");
624 QUEUE_TAKE(free, hio);
625 pjdlog_debug(2, "recv: (%p) Got request.", hio);
626 if (hast_proto_recv_hdr(res->hr_remotein, &nv) < 0) {
626 if (hast_proto_recv_hdr(res->hr_remotein, &nv) == -1) {
627 secondary_exit(EX_TEMPFAIL,
628 "Unable to receive request header");
629 }
630 if (requnpack(res, hio, nv) != 0) {
631 nv_free(nv);
632 pjdlog_debug(2,
633 "recv: (%p) Moving request to the send queue.",
634 hio);

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

661 pjdlog_debug(2,
662 "recv: (%p) Moving request to the free queue.",
663 hio);
664 hio_clear(hio);
665 QUEUE_INSERT(free, hio);
666 continue;
667 } else if (hio->hio_cmd == HIO_WRITE) {
668 if (hast_proto_recv_data(res, res->hr_remotein, nv,
627 secondary_exit(EX_TEMPFAIL,
628 "Unable to receive request header");
629 }
630 if (requnpack(res, hio, nv) != 0) {
631 nv_free(nv);
632 pjdlog_debug(2,
633 "recv: (%p) Moving request to the send queue.",
634 hio);

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

661 pjdlog_debug(2,
662 "recv: (%p) Moving request to the free queue.",
663 hio);
664 hio_clear(hio);
665 QUEUE_INSERT(free, hio);
666 continue;
667 } else if (hio->hio_cmd == HIO_WRITE) {
668 if (hast_proto_recv_data(res, res->hr_remotein, nv,
669 hio->hio_data, MAXPHYS) < 0) {
669 hio->hio_data, MAXPHYS) == -1) {
670 secondary_exit(EX_TEMPFAIL,
671 "Unable to receive request data");
672 }
673 }
674 nv_free(nv);
675 pjdlog_debug(2, "recv: (%p) Moving request to the disk queue.",
676 hio);
677 QUEUE_INSERT(disk, hio);

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

730 reqlog(LOG_DEBUG, 2, -1, hio, "disk: (%p) Got request: ", hio);
731 logerror = true;
732 /* Handle the actual request. */
733 switch (hio->hio_cmd) {
734 case HIO_READ:
735 ret = pread(res->hr_localfd, hio->hio_data,
736 hio->hio_length,
737 hio->hio_offset + res->hr_localoff);
670 secondary_exit(EX_TEMPFAIL,
671 "Unable to receive request data");
672 }
673 }
674 nv_free(nv);
675 pjdlog_debug(2, "recv: (%p) Moving request to the disk queue.",
676 hio);
677 QUEUE_INSERT(disk, hio);

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

730 reqlog(LOG_DEBUG, 2, -1, hio, "disk: (%p) Got request: ", hio);
731 logerror = true;
732 /* Handle the actual request. */
733 switch (hio->hio_cmd) {
734 case HIO_READ:
735 ret = pread(res->hr_localfd, hio->hio_data,
736 hio->hio_length,
737 hio->hio_offset + res->hr_localoff);
738 if (ret < 0)
738 if (ret == -1)
739 hio->hio_error = errno;
740 else if (ret != (int64_t)hio->hio_length)
741 hio->hio_error = EIO;
742 else
743 hio->hio_error = 0;
744 break;
745 case HIO_WRITE:
746 ret = pwrite(res->hr_localfd, hio->hio_data,
747 hio->hio_length,
748 hio->hio_offset + res->hr_localoff);
739 hio->hio_error = errno;
740 else if (ret != (int64_t)hio->hio_length)
741 hio->hio_error = EIO;
742 else
743 hio->hio_error = 0;
744 break;
745 case HIO_WRITE:
746 ret = pwrite(res->hr_localfd, hio->hio_data,
747 hio->hio_length,
748 hio->hio_offset + res->hr_localoff);
749 if (ret < 0)
749 if (ret == -1)
750 hio->hio_error = errno;
751 else if (ret != (int64_t)hio->hio_length)
752 hio->hio_error = EIO;
753 else
754 hio->hio_error = 0;
755 break;
756 case HIO_DELETE:
757 ret = g_delete(res->hr_localfd,
758 hio->hio_offset + res->hr_localoff,
759 hio->hio_length);
750 hio->hio_error = errno;
751 else if (ret != (int64_t)hio->hio_length)
752 hio->hio_error = EIO;
753 else
754 hio->hio_error = 0;
755 break;
756 case HIO_DELETE:
757 ret = g_delete(res->hr_localfd,
758 hio->hio_offset + res->hr_localoff,
759 hio->hio_length);
760 if (ret < 0)
760 if (ret == -1)
761 hio->hio_error = errno;
762 else
763 hio->hio_error = 0;
764 break;
765 case HIO_FLUSH:
766 if (!res->hr_localflush) {
767 ret = -1;
768 hio->hio_error = EOPNOTSUPP;
769 logerror = false;
770 break;
771 }
772 ret = g_flush(res->hr_localfd);
761 hio->hio_error = errno;
762 else
763 hio->hio_error = 0;
764 break;
765 case HIO_FLUSH:
766 if (!res->hr_localflush) {
767 ret = -1;
768 hio->hio_error = EOPNOTSUPP;
769 logerror = false;
770 break;
771 }
772 ret = g_flush(res->hr_localfd);
773 if (ret < 0) {
773 if (ret == -1) {
774 if (errno == EOPNOTSUPP)
775 res->hr_localflush = false;
776 hio->hio_error = errno;
777 } else {
778 hio->hio_error = 0;
779 }
780 break;
781 default:

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

832 break;
833 default:
834 PJDLOG_ABORT("Unexpected command (cmd=%hhu).",
835 hio->hio_cmd);
836 }
837 if (hio->hio_error != 0)
838 nv_add_int16(nvout, hio->hio_error, "error");
839 if (hast_proto_send(res, res->hr_remoteout, nvout, data,
774 if (errno == EOPNOTSUPP)
775 res->hr_localflush = false;
776 hio->hio_error = errno;
777 } else {
778 hio->hio_error = 0;
779 }
780 break;
781 default:

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

832 break;
833 default:
834 PJDLOG_ABORT("Unexpected command (cmd=%hhu).",
835 hio->hio_cmd);
836 }
837 if (hio->hio_error != 0)
838 nv_add_int16(nvout, hio->hio_error, "error");
839 if (hast_proto_send(res, res->hr_remoteout, nvout, data,
840 length) < 0) {
840 length) == -1) {
841 secondary_exit(EX_TEMPFAIL, "Unable to send reply.");
842 }
843 nv_free(nvout);
844 pjdlog_debug(2, "send: (%p) Moving request to the free queue.",
845 hio);
846 hio_clear(hio);
847 QUEUE_INSERT(free, hio);
848 }
849 /* NOTREACHED */
850 return (NULL);
851}
841 secondary_exit(EX_TEMPFAIL, "Unable to send reply.");
842 }
843 nv_free(nvout);
844 pjdlog_debug(2, "send: (%p) Moving request to the free queue.",
845 hio);
846 hio_clear(hio);
847 QUEUE_INSERT(free, hio);
848 }
849 /* NOTREACHED */
850 return (NULL);
851}