primary.c (211981) | primary.c (211982) |
---|---|
1/*- 2 * Copyright (c) 2009 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 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/primary.c 211981 2010-08-29 22:55:21Z pjd $"); | 32__FBSDID("$FreeBSD: head/sbin/hastd/primary.c 211982 2010-08-30 00:06:05Z pjd $"); |
33 34#include <sys/types.h> 35#include <sys/time.h> 36#include <sys/bio.h> 37#include <sys/disk.h> 38#include <sys/refcount.h> 39#include <sys/stat.h> 40 41#include <geom/gate/g_gate.h> 42 43#include <assert.h> 44#include <err.h> 45#include <errno.h> 46#include <fcntl.h> 47#include <libgeom.h> 48#include <pthread.h> | 33 34#include <sys/types.h> 35#include <sys/time.h> 36#include <sys/bio.h> 37#include <sys/disk.h> 38#include <sys/refcount.h> 39#include <sys/stat.h> 40 41#include <geom/gate/g_gate.h> 42 43#include <assert.h> 44#include <err.h> 45#include <errno.h> 46#include <fcntl.h> 47#include <libgeom.h> 48#include <pthread.h> |
49#include <signal.h> |
|
49#include <stdint.h> 50#include <stdio.h> 51#include <string.h> 52#include <sysexits.h> 53#include <unistd.h> 54 55#include <activemap.h> 56#include <nv.h> --- 70 unchanged lines hidden (view full) --- 127 */ 128static bool sync_inprogress; 129static pthread_mutex_t sync_lock; 130static pthread_cond_t sync_cond; 131/* 132 * The lock below allows to synchornize access to remote connections. 133 */ 134static pthread_rwlock_t *hio_remote_lock; | 50#include <stdint.h> 51#include <stdio.h> 52#include <string.h> 53#include <sysexits.h> 54#include <unistd.h> 55 56#include <activemap.h> 57#include <nv.h> --- 70 unchanged lines hidden (view full) --- 128 */ 129static bool sync_inprogress; 130static pthread_mutex_t sync_lock; 131static pthread_cond_t sync_cond; 132/* 133 * The lock below allows to synchornize access to remote connections. 134 */ 135static pthread_rwlock_t *hio_remote_lock; |
135static pthread_mutex_t hio_guard_lock; 136static pthread_cond_t hio_guard_cond; | |
137 138/* 139 * Lock to synchronize metadata updates. Also synchronize access to 140 * hr_primary_localcnt and hr_primary_remotecnt fields. 141 */ 142static pthread_mutex_t metadata_lock; 143 144/* 145 * Maximum number of outstanding I/O requests. 146 */ 147#define HAST_HIO_MAX 256 148/* 149 * Number of components. At this point there are only two components: local 150 * and remote, but in the future it might be possible to use multiple local 151 * and remote components. 152 */ 153#define HAST_NCOMPONENTS 2 154/* | 136 137/* 138 * Lock to synchronize metadata updates. Also synchronize access to 139 * hr_primary_localcnt and hr_primary_remotecnt fields. 140 */ 141static pthread_mutex_t metadata_lock; 142 143/* 144 * Maximum number of outstanding I/O requests. 145 */ 146#define HAST_HIO_MAX 256 147/* 148 * Number of components. At this point there are only two components: local 149 * and remote, but in the future it might be possible to use multiple local 150 * and remote components. 151 */ 152#define HAST_NCOMPONENTS 2 153/* |
155 * Number of seconds to sleep between keepalive packets. | 154 * Number of seconds to sleep between reconnect retries or keepalive packets. |
156 */ | 155 */ |
157#define KEEPALIVE_SLEEP 10 158/* 159 * Number of seconds to sleep between reconnect retries. 160 */ 161#define RECONNECT_SLEEP 5 | 156#define RETRY_SLEEP 10 |
162 163#define ISCONNECTED(res, no) \ 164 ((res)->hr_remotein != NULL && (res)->hr_remoteout != NULL) 165 166#define QUEUE_INSERT1(hio, name, ncomp) do { \ 167 bool _wakeup; \ 168 \ 169 mtx_lock(&hio_##name##_list_lock[(ncomp)]); \ --- 55 unchanged lines hidden (view full) --- 225static void *ggate_recv_thread(void *arg); 226static void *local_send_thread(void *arg); 227static void *remote_send_thread(void *arg); 228static void *remote_recv_thread(void *arg); 229static void *ggate_send_thread(void *arg); 230static void *sync_thread(void *arg); 231static void *guard_thread(void *arg); 232 | 157 158#define ISCONNECTED(res, no) \ 159 ((res)->hr_remotein != NULL && (res)->hr_remoteout != NULL) 160 161#define QUEUE_INSERT1(hio, name, ncomp) do { \ 162 bool _wakeup; \ 163 \ 164 mtx_lock(&hio_##name##_list_lock[(ncomp)]); \ --- 55 unchanged lines hidden (view full) --- 220static void *ggate_recv_thread(void *arg); 221static void *local_send_thread(void *arg); 222static void *remote_send_thread(void *arg); 223static void *remote_recv_thread(void *arg); 224static void *ggate_send_thread(void *arg); 225static void *sync_thread(void *arg); 226static void *guard_thread(void *arg); 227 |
233static void sighandler(int sig); | 228static void 229dummy_sighandler(int sig __unused) 230{ 231 /* Nothing to do. */ 232} |
234 235static void 236cleanup(struct hast_resource *res) 237{ 238 int rerrno; 239 240 /* Remember errno. */ 241 rerrno = errno; --- 72 unchanged lines hidden (view full) --- 314 return (strcmp(res->hr_remoteaddr, "none") != 0); 315} 316 317static void 318init_environment(struct hast_resource *res __unused) 319{ 320 struct hio *hio; 321 unsigned int ii, ncomps; | 233 234static void 235cleanup(struct hast_resource *res) 236{ 237 int rerrno; 238 239 /* Remember errno. */ 240 rerrno = errno; --- 72 unchanged lines hidden (view full) --- 313 return (strcmp(res->hr_remoteaddr, "none") != 0); 314} 315 316static void 317init_environment(struct hast_resource *res __unused) 318{ 319 struct hio *hio; 320 unsigned int ii, ncomps; |
321 sigset_t mask; |
|
322 323 /* 324 * In the future it might be per-resource value. 325 */ 326 ncomps = HAST_NCOMPONENTS; 327 328 /* 329 * Allocate memory needed by lists. --- 54 unchanged lines hidden (view full) --- 384 TAILQ_INIT(&hio_recv_list[ii]); 385 mtx_init(&hio_recv_list_lock[ii]); 386 cv_init(&hio_recv_list_cond[ii]); 387 rw_init(&hio_remote_lock[ii]); 388 } 389 TAILQ_INIT(&hio_done_list); 390 mtx_init(&hio_done_list_lock); 391 cv_init(&hio_done_list_cond); | 322 323 /* 324 * In the future it might be per-resource value. 325 */ 326 ncomps = HAST_NCOMPONENTS; 327 328 /* 329 * Allocate memory needed by lists. --- 54 unchanged lines hidden (view full) --- 384 TAILQ_INIT(&hio_recv_list[ii]); 385 mtx_init(&hio_recv_list_lock[ii]); 386 cv_init(&hio_recv_list_cond[ii]); 387 rw_init(&hio_remote_lock[ii]); 388 } 389 TAILQ_INIT(&hio_done_list); 390 mtx_init(&hio_done_list_lock); 391 cv_init(&hio_done_list_cond); |
392 mtx_init(&hio_guard_lock); 393 cv_init(&hio_guard_cond); | |
394 mtx_init(&metadata_lock); 395 396 /* 397 * Allocate requests pool and initialize requests. 398 */ 399 for (ii = 0; ii < HAST_HIO_MAX; ii++) { 400 hio = malloc(sizeof(*hio)); 401 if (hio == NULL) { --- 24 unchanged lines hidden (view full) --- 426 hio->hio_ggio.gctl_length = MAXPHYS; 427 hio->hio_ggio.gctl_error = 0; 428 TAILQ_INSERT_HEAD(&hio_free_list, hio, hio_free_next); 429 } 430 431 /* 432 * Turn on signals handling. 433 */ | 392 mtx_init(&metadata_lock); 393 394 /* 395 * Allocate requests pool and initialize requests. 396 */ 397 for (ii = 0; ii < HAST_HIO_MAX; ii++) { 398 hio = malloc(sizeof(*hio)); 399 if (hio == NULL) { --- 24 unchanged lines hidden (view full) --- 424 hio->hio_ggio.gctl_length = MAXPHYS; 425 hio->hio_ggio.gctl_error = 0; 426 TAILQ_INSERT_HEAD(&hio_free_list, hio, hio_free_next); 427 } 428 429 /* 430 * Turn on signals handling. 431 */ |
434 signal(SIGINT, sighandler); 435 signal(SIGTERM, sighandler); 436 signal(SIGHUP, sighandler); 437 signal(SIGCHLD, sighandler); | 432 /* Because SIGCHLD is ignored by default, setup dummy handler for it. */ 433 PJDLOG_VERIFY(signal(SIGCHLD, dummy_sighandler) != SIG_ERR); 434 PJDLOG_VERIFY(sigfillset(&mask) == 0); 435 PJDLOG_VERIFY(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); |
438} 439 440static void 441init_local(struct hast_resource *res) 442{ 443 unsigned char *buf; 444 size_t mapsize; 445 --- 442 unchanged lines hidden (view full) --- 888 rw_unlock(&hio_remote_lock[ncomp]); 889 890 pjdlog_warning("Disconnected from %s.", res->hr_remoteaddr); 891 892 /* 893 * Stop synchronization if in-progress. 894 */ 895 sync_stop(); | 436} 437 438static void 439init_local(struct hast_resource *res) 440{ 441 unsigned char *buf; 442 size_t mapsize; 443 --- 442 unchanged lines hidden (view full) --- 886 rw_unlock(&hio_remote_lock[ncomp]); 887 888 pjdlog_warning("Disconnected from %s.", res->hr_remoteaddr); 889 890 /* 891 * Stop synchronization if in-progress. 892 */ 893 sync_stop(); |
896 897 /* 898 * Wake up guard thread (if we are not called from within guard thread), 899 * so it can immediately start reconnect. 900 */ 901 if (!mtx_owned(&hio_guard_lock)) { 902 mtx_lock(&hio_guard_lock); 903 cv_signal(&hio_guard_cond); 904 mtx_unlock(&hio_guard_lock); 905 } | |
906} 907 908/* 909 * Thread receives ggate I/O requests from the kernel and passes them to 910 * appropriate threads: 911 * WRITE - always goes to both local_send and remote_send threads 912 * READ (when the block is up-to-date on local component) - 913 * only local_send thread --- 815 unchanged lines hidden (view full) --- 1729 hio); 1730 QUEUE_INSERT2(hio, free); 1731 } 1732 /* NOTREACHED */ 1733 return (NULL); 1734} 1735 1736static void | 894} 895 896/* 897 * Thread receives ggate I/O requests from the kernel and passes them to 898 * appropriate threads: 899 * WRITE - always goes to both local_send and remote_send threads 900 * READ (when the block is up-to-date on local component) - 901 * only local_send thread --- 815 unchanged lines hidden (view full) --- 1717 hio); 1718 QUEUE_INSERT2(hio, free); 1719 } 1720 /* NOTREACHED */ 1721 return (NULL); 1722} 1723 1724static void |
1737sighandler(int sig) 1738{ 1739 bool unlock; 1740 1741 switch (sig) { 1742 case SIGINT: 1743 case SIGTERM: 1744 sigexit_received = true; 1745 break; 1746 case SIGHUP: 1747 sighup_received = true; 1748 break; 1749 case SIGCHLD: 1750 sigchld_received = true; 1751 break; 1752 default: 1753 assert(!"invalid condition"); 1754 } 1755 /* 1756 * Racy, but if we cannot obtain hio_guard_lock here, we don't 1757 * want to risk deadlock. 1758 */ 1759 unlock = mtx_trylock(&hio_guard_lock); 1760 cv_signal(&hio_guard_cond); 1761 if (unlock) 1762 mtx_unlock(&hio_guard_lock); 1763} 1764 1765static void | |
1766config_reload(void) 1767{ 1768 struct hastd_config *newcfg; 1769 struct hast_resource *res; 1770 unsigned int ii, ncomps; 1771 int modified; 1772 1773 pjdlog_info("Reloading configuration..."); --- 194 unchanged lines hidden (view full) --- 1968 * Thread guards remote connections and reconnects when needed, handles 1969 * signals, etc. 1970 */ 1971static void * 1972guard_thread(void *arg) 1973{ 1974 struct hast_resource *res = arg; 1975 unsigned int ii, ncomps; | 1725config_reload(void) 1726{ 1727 struct hastd_config *newcfg; 1728 struct hast_resource *res; 1729 unsigned int ii, ncomps; 1730 int modified; 1731 1732 pjdlog_info("Reloading configuration..."); --- 194 unchanged lines hidden (view full) --- 1927 * Thread guards remote connections and reconnects when needed, handles 1928 * signals, etc. 1929 */ 1930static void * 1931guard_thread(void *arg) 1932{ 1933 struct hast_resource *res = arg; 1934 unsigned int ii, ncomps; |
1935 struct timespec timeout; |
|
1976 time_t lastcheck, now; | 1936 time_t lastcheck, now; |
1977 int timeout; | 1937 sigset_t mask; 1938 int signo; |
1978 1979 ncomps = HAST_NCOMPONENTS; 1980 lastcheck = time(NULL); 1981 | 1939 1940 ncomps = HAST_NCOMPONENTS; 1941 lastcheck = time(NULL); 1942 |
1943 PJDLOG_VERIFY(sigemptyset(&mask) == 0); 1944 PJDLOG_VERIFY(sigaddset(&mask, SIGHUP) == 0); 1945 PJDLOG_VERIFY(sigaddset(&mask, SIGINT) == 0); 1946 PJDLOG_VERIFY(sigaddset(&mask, SIGTERM) == 0); 1947 PJDLOG_VERIFY(sigaddset(&mask, SIGCHLD) == 0); 1948 1949 timeout.tv_nsec = 0; 1950 signo = -1; 1951 |
|
1982 for (;;) { | 1952 for (;;) { |
1983 if (sigexit_received) { | 1953 switch (signo) { 1954 case SIGHUP: 1955 config_reload(); 1956 break; 1957 case SIGINT: 1958 case SIGTERM: 1959 sigexit_received = true; |
1984 primary_exitx(EX_OK, 1985 "Termination signal received, exiting."); | 1960 primary_exitx(EX_OK, 1961 "Termination signal received, exiting."); |
1962 break; 1963 default: 1964 break; |
|
1986 } | 1965 } |
1987 if (sighup_received) { 1988 sighup_received = false; 1989 config_reload(); 1990 } 1991 hook_check(sigchld_received); 1992 if (sigchld_received) 1993 sigchld_received = false; | 1966 hook_check(signo == SIGCHLD); |
1994 1995 pjdlog_debug(2, "remote_guard: Checking connections."); | 1967 1968 pjdlog_debug(2, "remote_guard: Checking connections."); |
1996 mtx_lock(&hio_guard_lock); 1997 timeout = KEEPALIVE_SLEEP; 1998 for (ii = 0; ii < ncomps; ii++) { 1999 if (!ISCONNECTED(res, ii)) { 2000 timeout = RECONNECT_SLEEP; 2001 break; 2002 } 2003 } | |
2004 now = time(NULL); | 1969 now = time(NULL); |
2005 if (lastcheck + timeout <= now) { 2006 timeout = KEEPALIVE_SLEEP; 2007 for (ii = 0; ii < ncomps; ii++) { | 1970 if (lastcheck + RETRY_SLEEP <= now) { 1971 for (ii = 0; ii < ncomps; ii++) |
2008 guard_one(res, ii); | 1972 guard_one(res, ii); |
2009 if (!ISCONNECTED(res, ii)) 2010 timeout = RECONNECT_SLEEP; 2011 } | |
2012 lastcheck = now; 2013 } | 1973 lastcheck = now; 1974 } |
2014 /* Sleep only if a signal wasn't delivered in the meantime. */ 2015 if (!sigexit_received && !sighup_received && !sigchld_received) 2016 cv_timedwait(&hio_guard_cond, &hio_guard_lock, timeout); 2017 mtx_unlock(&hio_guard_lock); | 1975 timeout.tv_sec = RETRY_SLEEP; 1976 signo = sigtimedwait(&mask, NULL, &timeout); |
2018 } 2019 /* NOTREACHED */ 2020 return (NULL); 2021} | 1977 } 1978 /* NOTREACHED */ 1979 return (NULL); 1980} |