From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lon Hohberger Date: Mon, 10 Nov 2008 09:09:03 -0500 Subject: [Cluster-devel] [PATCH] Clean up some rgmanager cruft Message-ID: <1226326143.16686.4.camel@ayanami> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit * Rename clurgmgrd -> rgmanager * Remove clurmtabd and references since it's not used. diff --git a/rgmanager/init.d/rgmanager.in b/rgmanager/init.d/rgmanager.in index a827aa9..2a3a30c 100644 --- a/rgmanager/init.d/rgmanager.in +++ b/rgmanager/init.d/rgmanager.in @@ -39,7 +39,7 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin export PATH ID="Cluster Service Manager" -RGMGRD="clurgmgrd" +RGMGRD="rgmanager" LOG_ERR=3 LOG_WARNING=4 diff --git a/rgmanager/src/daemons/Makefile b/rgmanager/src/daemons/Makefile index 97819f2..0691677 100644 --- a/rgmanager/src/daemons/Makefile +++ b/rgmanager/src/daemons/Makefile @@ -1,7 +1,6 @@ -TARGET1= clurgmgrd -#TARGET2= clurmtabd # Not needed on 2.6 kernels -TARGET3= rg_test -TARGET4= dtest +TARGET1= rgmanager +TARGET2= rg_test +TARGET3= dtest SBINDIRT=$(TARGET1) $(TARGET3) @@ -32,13 +31,10 @@ OBJS1= depends.o \ event_config.o \ watchdog.o -OBJS2= clurmtabd.o \ - clurmtabd_lib.o - -OBJS3= test-noccs.o \ +OBJS2= test-noccs.o \ restart_counter.o -OBJS4= dtest-noccs.o +OBJS3= dtest-noccs.o SHAREDOBJS= depends-noccs.o \ fo_domain-noccs.o \ @@ -80,9 +76,6 @@ ${TARGET1}: ${OBJS1} ${LDDEPS} $(SLANG_LDFLAGS) $(EXTRA_LDFLAGS) \ $(LOGSYS_LDFLAGS) $(LD_FLAGS) -#${TARGET2}: ${OBJS2} ${LDDEPS} -# $(CC) -o $@ $^ $(LDFLAGS) - # # Our test program links against the local allocator so that # we can see if our program is leaking memory during XML parsing, tree @@ -97,11 +90,11 @@ ${TARGET1}: ${OBJS1} ${LDDEPS} # This is NOT meant to be an installed binary. Rather, RPMs and/or other # packages should run 'make check' as part of the build process. # -${TARGET3}: ${SHAREDOBJS} ${OBJS3} ${LDDEPS} ${LOCAL_LDDEPS} +${TARGET2}: ${SHAREDOBJS} ${OBJS3} ${LDDEPS} ${LOCAL_LDDEPS} $(CC) -o $@ $^ $(CMAN_LDFLAGS) $(LOCAL_LDFLAGS) $(EXTRA_LDFLAGS) \ $(XML2_LDFLAGS) $(LOGSYS_LDFLAGS) $(LDFLAGS) -${TARGET4}: ${SHAREDOBJS} ${OBJS4} ${LDDEPS} ${LOCAL_LDDEPS} +${TARGET3}: ${SHAREDOBJS} ${OBJS4} ${LDDEPS} ${LOCAL_LDDEPS} $(CC) -o $@ $^ $(CCS_LDFLAGS) $(CMAN_LDFLAGS) \ $(LOCAL_LDFLAGS) $(EXTRA_LDFLAGS) $(XML2_LDFLAGS) \ $(READLINE_LDFLAGS) $(LDFLAGS) diff --git a/rgmanager/src/daemons/clurmtabd.c b/rgmanager/src/daemons/clurmtabd.c deleted file mode 100644 index 9dbb045..0000000 --- a/rgmanager/src/daemons/clurmtabd.c +++ /dev/null @@ -1,616 +0,0 @@ -/** @file - * Keeps /var/lib/nfs/rmtab in sync across the cluster. - * - * Author: Lon H. Hohberger - * - * Synchronizes entries in a mount point with /var/lib/nfs/rmtab. - */ - -#define CM_NFS_DIR ".clumanager" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define POLLINT_DEFAULT 2 - -/* FIXME DAEMON_STR is equivalent to the one in quorumd.c: CLURMTABD_DAEMON */ -/* Would be nice to have stuff like this defined in one place */ -#define DAEMON_STR "clurmtabd" -#define LOGLEVEL_STR DAEMON_STR "%logLevel" -#define POLLINT_STR DAEMON_STR "%pollInterval" - -/* - * Globals - */ - -static int exiting = 0; -static int poll_interval = POLLINT_DEFAULT; - -/* - * Function Prototypes - */ -static int rmtab_modified(void); -static int rmtab_copy_bypath(rmtab_node ** dest, rmtab_node ** src, - const char *path); -static int rmtab_get_update(rmtab_node ** rmtab, rmtab_node ** pruned_rmtab, - rmtab_node ** diff, char *path); - -/* Signal Handlers */ -static void sh_sync(int sig); -static void sh_exit(int sig); -static void sh_reconfigure(int sig); -static inline void register_sighandlers(void); - -/* Configuration */ -#if 0 -static inline int __get_int_param(char *str, int *val, int dflt); -#endif -static int get_rmtabd_loglevel(void); -static int get_rmtabd_pollinterval(int *interval); -static void rmtabd_reconfigure(void); - -/* Initialization */ -static int rmtabd_config_init(void); -int main(int argc, char **argv); - - -/** - * stat _PATH_RMTAB and see if it's changed. - * - * @returns 1 if it's been modified; 0 if not. - */ -static int -rmtab_modified(void) -{ - /* Preserved data */ - static struct stat prev_stat; - static int __prev_stat = 0; - - struct stat curr_stat; - int rv = 1; - - /* Initialize */ - if (!__prev_stat) { - memset(&prev_stat, 0, sizeof (prev_stat)); - stat(_PATH_RMTAB, &prev_stat); - __prev_stat = 1; - return 1; - } - - memset(&curr_stat, 0, sizeof (curr_stat)); - while (stat(_PATH_RMTAB, &curr_stat) == -1) { - if (errno != ENOENT) { - log_printf(LOG_ERR, "#15: %s: stat: %s\n", __FUNCTION__, - strerror(errno)); - return -1; - } - - /* Create the file. */ - log_printf(LOG_WARNING, "#62: " _PATH_RMTAB - " does not exist - creating"); - close(open(_PATH_RMTAB, O_CREAT | O_SYNC, 0600)); - } - - if ((rv = memcmp(&prev_stat.st_mtime, &curr_stat.st_mtime, - sizeof (curr_stat.st_mtime)))) { - log_printf(LOG_DEBUG, "Detected modified " _PATH_RMTAB "\n"); - memcpy(&prev_stat, &curr_stat, sizeof (prev_stat)); - } - - return !!rv; -} - - -/** - * Insert (copy) entries in **src with the same rn_path as *path to - * destination list **dest. - * - * @param dest Destination list pointer. - * @param src Source list pointer. - * @param path Path to prune (only copy entries in the specified - * path). - * Returns -1 if rmtab_insert fails; 0 on success - */ -static int -rmtab_copy_bypath(rmtab_node ** dest, rmtab_node ** src, const char *path) -{ - rmtab_node *curr, *last = NULL; - - for (curr = *src; curr; curr = curr->rn_next) - if (!strcmp(path, curr->rn_path)) - if ((last = rmtab_insert(dest, last, - curr->rn_hostname, - curr->rn_path, - curr->rn_count)) == NULL) - return -1; - return 0; -} - - -/** - * Update the rmtab from /var/lib/nfs/rmtab. We need to maintain two separate - * lists (rmtab and pruned_rmtab). This is because we don't want to sync - * non-cluster exports. Non-cluster exports will not show up in pruned_rmtab, - * however, when we receive an update from our peer, we'd lose non-cluster - * entries if we didn't preserve them when we merge in changes from our peer. - * - * The current (full) rmtab is passed in as **rmtab. The current cluster-only - * (pruned) rmtab is passed in as **pruned_rmtab. The differences between - * the current and new cluster-only rmtabs are passed out in **diff, and the - * new versions (if any) of the full rmtab and pruned rmtab are moved into - * - * @return -1 on error, 0 on success, 1 if no differences exist. - */ -static int -rmtab_get_update(rmtab_node ** rmtab, rmtab_node ** pruned_rmtab, - rmtab_node ** diff, char *path) -{ - int rv = -1; - rmtab_node *old_rmtab = NULL, *old_pruned = NULL; - - if (!rmtab_modified()) - return 1; - - /* Save the current full list */ - rmtab_move(&old_rmtab, rmtab); - - if (rmtab_read(rmtab, _PATH_RMTAB) == -1) { - log_printf(LOG_ERR, "#16: Failed to reread rmtab: %s\n", - strerror(errno)); - - /* Don't kill the list if we fail to reread. */ - rmtab_move(rmtab, &old_rmtab); - goto out; - } - - /* Save the current cluster-specific list */ - rmtab_move(&old_pruned, pruned_rmtab); - - if (rmtab_copy_bypath(pruned_rmtab, rmtab, path) == -1) { - log_printf(LOG_ERR, "#17: Failed to prune rmtab: %s\n", - strerror(errno)); - - /* - * Since we couldn't build a new list, restore the old - * one. Otherwise, next time, we'd send a weird diff to - * our peer with all entries as "added". - */ - rmtab_move(pruned_rmtab, &old_pruned); - goto out; - } - - if (!diff) { - rv = 1; - goto out; - } - - /* find the differences */ - if (rmtab_diff(old_pruned, *pruned_rmtab, diff)) { - log_printf(LOG_ERR, "Failed to diff rmtab: %s\n", strerror(errno)); - goto out; - } - - if (!*diff) { - /* No differences */ - rv = 1; - goto out; - } - - rv = 0; - out: - /* stick a finger in the memory dike */ - rmtab_kill(&old_rmtab); /* these will be NOPs if NULL */ - rmtab_kill(&old_pruned); - - return rv; -} - - - - -/* **************** * - * SIGNAL HANDLERS! - * **************** */ - -/** - * INT, USR1, USR2 handler. - * - * What these signals actually do is interrupt the select(2) we enter when we - * call sleep(). Effectively, this causes sleep() to short out, and makes - * us drop down into rmtab_get_update() - causing us to re-check and sync - * changes if there are any. The service script, svclib_nfs, sends us a - * TERM whenever it receives the request to stop a service (which happens - * when the service manager relocates as well), thus, when a service is - * disabled or relocates to the other node, clurmtabd syncs immediately its - * current state to the other node, preventing a timing window between - * "service relocate" and "rmtabd update" during which a client could - * receive ESTALE. - */ -static void -sh_sync(int sig) -{ - log_printf(LOG_DEBUG, "Signal %d received; syncing ASAP\n", sig); -} - - -/** - * QUIT, TERM - * - * In this case, we go down ASAP. But first, we sync. These will, like the - * above, short-out msg_accept_timeout() and drop down for that one last - * sync. - */ -static void -sh_exit(int sig) -{ - log_printf(LOG_DEBUG, "Signal %d received; exiting\n", sig); - exiting = 1; -} - - -/** - * HUP - * - * Traditional behavior. Reconfigure on SIGHUP. - */ -static void -sh_reconfigure(int __attribute__ ((unused)) sig) -{ - log_printf(LOG_DEBUG, "Re-reading the cluster database\n"); - rmtabd_reconfigure(); -} - - -/** - * Set up signal handlers. - */ -static inline void -register_sighandlers(void) -{ - sigset_t set; - struct sigaction act; - - sigemptyset(&set); - sigaddset(&set, SIGINT); - sigaddset(&set, SIGUSR1); - sigaddset(&set, SIGUSR2); - - sigaddset(&set, SIGHUP); - - sigaddset(&set, SIGTERM); - sigaddset(&set, SIGQUIT); - - sigaddset(&set, SIGILL); - sigaddset(&set, SIGIO); - sigaddset(&set, SIGSEGV); - sigaddset(&set, SIGBUS); - - sigprocmask(SIG_UNBLOCK, &set, NULL); - - memset(&act, 0, sizeof (act)); - sigemptyset(&act.sa_mask); - - /* In some cases, just continue */ - act.sa_handler = sh_sync; - - sigaction(SIGINT, &act, NULL); - sigaction(SIGUSR1, &act, NULL); - sigaction(SIGUSR2, &act, NULL); - - /* Ok, reconfigure here */ - act.sa_handler = sh_reconfigure; - sigaction(SIGHUP, &act, NULL); - - /* Exit signals */ - act.sa_handler = sh_exit; - sigaction(SIGTERM, &act, NULL); - sigaction(SIGQUIT, &act, NULL); -} - -/* ******************************* * - * Configuration Utility Functions - * ******************************* */ - -/** - * Retrieve an integer parameter from the config file. - * - * @param str config token - * @param val return value - * @param dflt Default integer value. - * @return 0 s - */ -#if 0 -static inline int -__get_int_param(char *str, int *val, int dflt) -{ - char *value; - int ret; - - ret = CFG_Get(str, NULL, &value); - - switch (ret) { - case CFG_DEFAULT: - *val = dflt; - break; - case CFG_OK: - *val = atoi(value); - break; - default: - log_printf(LOG_ERR, "#19: Cannot get \"%s\" from database; " - "CFG_Get() failed, err=%d\n", ret); - return 0; - } - - return 0; -} -#endif - - -/** - * Gets the loglevel of rmtabd - */ -static int -get_rmtabd_loglevel(void) -{ -#if 0 - return __get_int_param(LOGLEVEL_STR, level, LOG_DEFAULT); -#endif - return LOG_INFO; -} - - -/** - * Retrieves the polling interval, in seconds, of _RMTAB_PATH from the cluster - * configuration database. - */ -static int -get_rmtabd_pollinterval(int __attribute__((unused)) *interval) -{ -#if 0 - return __get_int_param(POLLINT_STR, interval, POLLINT_DEFAULT); -#endif - return POLLINT_DEFAULT; -} - - -/** - * This is called at init and by sh_reconfigure and sets up daemon-specific - * configuration params. - */ -static void -rmtabd_reconfigure(void) -{ - int level, old_level, old_interval; - - /* loglevel */ - old_level = clu_get_loglevel(); - level = get_rmtabd_loglevel(); - - if (old_level != level) { - if (clu_set_loglevel(level) == -1) - log_printf(LOG_ERR, "#20: Failed set log level\n"); - else - log_printf(LOG_DEBUG, "Log level is now %d\n", level); - } - - /* rmtabd polling interval (tw33k4bl3) */ - old_interval = poll_interval; - get_rmtabd_pollinterval(&poll_interval); - - /* bounds-check */ - if (poll_interval < 1) - poll_interval = 1; - else if (poll_interval > 10) - poll_interval = 10; - - if (old_interval != poll_interval) { - log_printf_and_print(LOG_DEBUG, - "Polling interval is now %d seconds\n", - poll_interval); - } -} - - -/** - * Set up local parameters & signal handlers. - */ -static int -rmtabd_config_init(void) -{ - /* Yes, it does this twice */ -#if 0 - if (CFG_ReadFile(CLU_CONFIG_FILE) != CFG_OK) - return -1; -#endif - - rmtabd_reconfigure(); - register_sighandlers(); - return 0; -} - - -/** - * Initializes and synchronizes /var/lib/nfs/rmtab with - * [path]/.clumanager/rmtab. - * - * @param path Path to mount point we're monitoring. - * @param rmtab Will contain full rmtab upon exit. - * @param pruned_rmtab Will contain rmtab entries we care about on exit. - */ -int -rmtab_init(char *path, rmtab_node **rmtab, rmtab_node **pruned_rmtab) -{ - char buf[PATH_MAX]; - - snprintf(buf, sizeof(buf), "%s/%s", path, CM_NFS_DIR); - - if ((mkdir(buf, 0700) == -1) && (errno != EEXIST)) { - log_printf_and_print(LOG_ERR, "#21: Couldn't read/create %s: %s\n", - buf, strerror(errno)); - return -1; - } - - snprintf(buf, sizeof(buf), "%s/%s/rmtab", path, CM_NFS_DIR); - - if (rmtab_read(rmtab, buf) == -1) { - log_printf_and_print(LOG_ERR, "#22: Failed to read %s: %s\n", buf, - strerror(errno)); - return -1; - } - - /* - * Read into the same pointer -> inserting each node will - * cause the nodes with the greater count to be kept. - */ - if (rmtab_read(rmtab, _PATH_RMTAB) == -1) { - log_printf_and_print(LOG_ERR, "#23: Failed to read %s: %s\n", - _PATH_RMTAB, strerror(errno)); - return -1; - } - - /* - * Prune by our path - */ - if (rmtab_copy_bypath(pruned_rmtab, rmtab, path) == -1) { - log_printf_and_print(LOG_ERR, "#24: Failed to prune rmtab: %s\n", - strerror(errno)); - return -1; - } - - /* - * XXX could lose a mount if rpc.mountd writes a file before - * we rewrite the file. - */ - if (rmtab_write_atomic(*rmtab, _PATH_RMTAB) == -1) { - log_printf_and_print(LOG_ERR, "#25: Failed to write %s: %s\n", - _PATH_RMTAB, strerror(errno)); - return -1; - } - /* - * Write new contents. - */ - if (rmtab_write_atomic(*pruned_rmtab, buf) == -1) { - log_printf_and_print(LOG_ERR, "#26: Failed to write %s: %s\n", buf, - strerror(errno)); - return -1; - } - - return 0; -} - - -/** - * Fork off into the background and store our pid file in - * [path]/.clumanager/pid - * - * @param path Mount point we're monitoring. - * @return -1 on failure, 0 on success. - */ -static int -daemonize(char *path) -{ - FILE *fp=NULL; - char filename[PATH_MAX]; - - if (daemon(0,0) == -1) - return -1; - - memset(filename,0,PATH_MAX); - snprintf(filename, sizeof(filename), "%s/%s/pid", path, CM_NFS_DIR); - - fp = fopen(filename, "w"); - if (fp == NULL) { - log_printf(LOG_WARNING, "#63: Couldn't write PID!\n"); - } - - fprintf(fp, "%d", getpid()); - fclose(fp); - - return 0; -} - - -/** - * main - * - * Main. Main. Main. Main. Main. Main. Main. Main. Main. Main. - */ -int -main(int argc, char **argv) -{ - char path[PATH_MAX]; - char rmtab_priv[PATH_MAX]; - - rmtab_node *rmtab = NULL, *pruned_rmtab = NULL, *diff = NULL; - - if (argc < 2) { - fprintf(stderr, "usage: clurmtabd \n"); - return -1; - } - - /* Set up configuration parameters */ - if (rmtabd_config_init() == -1) { - log_printf_and_print(LOG_ERR, - "#27: Couldn't initialize - exiting\n"); - return -1; - } - - /* Set up our internal variables */ - snprintf(path, sizeof(path), "%s", argv[1]); - snprintf(rmtab_priv, sizeof(rmtab_priv), "%s/%s/rmtab", path, - CM_NFS_DIR); - - /* - * Synchronize the rmtab files - * - * We do this before we call daemonize() to ensure that when - * the service script calls exportfs, /var/lib/nfs/rmtab has - * all the necessary entries. - */ - if (rmtab_init(path, &rmtab, &pruned_rmtab) == -1) { - log_printf_and_print(LOG_WARNING, - "#64: Could not validate %s\n", path); - log_printf_and_print(LOG_WARNING, - "#65: NFS Failover of %s will malfunction\n", - path); - return -1; - } - - /* Jump off into the background */ - if (daemonize(path) == -1) { - log_printf_and_print(LOG_ERR, "#28: daemonize: %s\n", - strerror(errno)); - return -1; - } - - /* Main loop */ - while (!exiting) { - - /* Snooze a bit */ - sleep(poll_interval); - - /* Check for updates */ - if (rmtab_get_update(&rmtab, &pruned_rmtab, &diff, path) - == 0) { - /* Handle updates */ - rmtab_merge(&pruned_rmtab, diff); - rmtab_kill(&diff); - if (rmtab_write_atomic(pruned_rmtab, rmtab_priv) == -1) - log_printf(LOG_ERR, - "#29: rmtab_write_atomic: %s\n", - strerror(errno)); - } - } - - return 0; -} diff --git a/rgmanager/src/daemons/clurmtabd_lib.c b/rgmanager/src/daemons/clurmtabd_lib.c deleted file mode 100644 index aa216a2..0000000 --- a/rgmanager/src/daemons/clurmtabd_lib.c +++ /dev/null @@ -1,820 +0,0 @@ -/** @file - * Implements rmtab read/write/list handling functions utilized by - * clurmtabd. - * - * Author: Lon H. Hohberger - * - * This was written for two reasons: - * (1) The nfs-utils code was difficult to adapt to the requirements, and - * (2) to prevent cross-breeding of nfs-utils with clumanager. - * - * So, in a sense, this is a re-invention of the wheel, but it keeps the - * pacakges separate, thus easing maintenance by lessening the number of - * patches and code forks required for Enterprise Linux. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Function Prototypes - */ -static int fp_lock(FILE *fp, int type); -static int fp_unlock(FILE *fp); -static inline void un_diffize(rmtab_node *dest, rmtab_node *src); - - -/* - * free an rmtab node - */ -void -rmtab_free(rmtab_node *ptr) -{ - if(ptr->rn_hostname) - free(ptr->rn_hostname); - if(ptr->rn_path) - free(ptr->rn_path); - free(ptr); -} - - -/* - * take advisory lock. Retry until we're blue in the face. - */ -static int -fp_lock(FILE *fp, int type) -{ - int fd; - struct flock flock; - - fd = fileno(fp); - memset(&flock,0,sizeof(flock)); - - /* Lock. */ - flock.l_type = type; - while (fcntl(fd, F_SETLK, &flock) == -1) { - if ((errno != EAGAIN) && (errno != EACCES)) - return -1; - - usleep(10000); - } - - return 0; -} - - -/* - * unlock... - */ -static int -fp_unlock(FILE *fp) -{ - int fd = fileno(fp); - struct flock flock; - - memset(&flock,0,sizeof(flock)); - flock.l_type = F_UNLCK; - return fcntl(fd, F_SETLK, &flock); -} - - -/* - * Inserts a node into the list in ASCII-sorted order; rnew must have been - * a user-allocated chunk of memory. (static = big nono) - */ -int -__rmtab_insert(rmtab_node **head, rmtab_node *rnew) -{ - rmtab_node *back, *curr; - int rv = 1; - - /* insert as first entry */ - if (!(*head) || (rv = rmtab_cmp_min(rnew, *head)) < 0) { - rnew->rn_next = *head; - *head = rnew; - return 0; - } - - /* Duplicate match? */ - if (!rv) { - if ((*head)->rn_count < rnew->rn_count) - (*head)->rn_count = rnew->rn_count; - return 1; - } - - /* Standard insert - not beginning, not end. */ - back = NULL; - curr = *head; - while (curr) { - /* Insert before current */ - if ((rv = rmtab_cmp_min(rnew, curr)) < 0) { - back->rn_next = rnew; - rnew->rn_next = curr; - return 0; - } - - /* Duplicate match? Snag the greater count. */ - if (!rv) { - if (curr->rn_count < rnew->rn_count) - curr->rn_count = rnew->rn_count; - return 0; - } - - /* Loopy loopy */ - back = curr; - curr = curr->rn_next; - } - - /* Tack on at end of list */ - back->rn_next = rnew; - - return 0; -} - - -/* - * Inserts a node into the list in ASCII-sorted order; rnew must have been - * a user-allocated chunk of memory. (static = big nono) - */ -int -__rmtab_insert_after(rmtab_node *pre, rmtab_node *rnew) -{ - rmtab_node *back, *curr; - int rv = 1; - - /* insert as first entry */ - if ((rv = rmtab_cmp_min(rnew, pre)) < 0) { - return -1; - } - - /* Duplicate match? */ - if (!rv) { - if (pre->rn_count < rnew->rn_count) - pre->rn_count = rnew->rn_count; - return 1; - } - - /* Standard insert - not beginning, not end. */ - back = NULL; - curr = pre; - while (curr) { - /* Insert before current */ - if ((rv = rmtab_cmp_min(rnew, curr)) < 0) { - back->rn_next = rnew; - rnew->rn_next = curr; - return 0; - } - - /* Duplicate match? Snag the greater count. */ - if (!rv) { - if (curr->rn_count < rnew->rn_count) - curr->rn_count = rnew->rn_count; - return 0; - } - - /* Loopy loopy */ - back = curr; - curr = curr->rn_next; - } - - /* Tack on at end of list */ - back->rn_next = rnew; - - return 0; -} - - -/* - * Inserts (host,path) rmtab into a list pointed to by **head - */ -rmtab_node * -rmtab_insert(rmtab_node **head, rmtab_node *pre, char *host, - char *path, int count) -{ - rmtab_node *rnew; - - /* simple bounds-checking */ - if (!head || !host || !path || !strlen(host) || !strlen(path)) - return NULL; - - /* Copy in info */ - rnew = malloc(sizeof(*rnew)); - // FIXME: handle failed malloc - memset(rnew, 0, sizeof(*rnew)); - rnew->rn_hostname = strdup(host); - rnew->rn_path = strdup(path); - rnew->rn_count = count; - - if (pre) { - /* We got a preceding node... try to insert */ - switch(__rmtab_insert_after(pre, rnew)) { - case -1: - /* Failed insert after... try before? */ - break; - case 0: - goto out; - case 1: - rmtab_free(rnew); - rnew = NULL; - goto out; - } - } - - - /* Insert into our list officially */ - if (__rmtab_insert(head, rnew) == 1) { - /* Duplicate match */ - rmtab_free(rnew); - rnew = NULL; - } - -out: - return rnew; -} - - -/* - * removes a node based on contents of *entry - * user must free memory, if applicable. - */ -rmtab_node * -__rmtab_remove(rmtab_node **head, rmtab_node *entry) -{ - int rv = -1; - rmtab_node *curr, *back; - - back = NULL; curr = *head; - - for (curr = *head, back = NULL; - (rv = rmtab_cmp_min(curr, entry)) < 0; - back = curr, curr = curr->rn_next); - - /* overshot => no match */ - if (rv != 0) - return NULL; - - if (back) { - back->rn_next = curr->rn_next; - curr->rn_next = NULL; - return curr; - } - - /* no back pointer = first node in list. */ - back = curr; - *head = curr->rn_next; - back->rn_next = NULL; - return back; -} - - -/* - * removes an entry in the list; user must free. - */ -rmtab_node * -rmtab_remove(rmtab_node **head, char *host, char *path) -{ - rmtab_node tmp; - rmtab_node *ret; - - /* Wrappers, wrappers */ - memset(&tmp, 0, sizeof(tmp)); - if (host) - tmp.rn_hostname = strdup(host); - if (path) - tmp.rn_path = strdup(path); - - ret = __rmtab_remove(head, &tmp); - if (tmp.rn_hostname) - free(tmp.rn_hostname); - if (tmp.rn_path) - free(tmp.rn_path); - - return ret; -} - - -/* - * Frees an entire rmtab list. - */ -void -rmtab_kill(rmtab_node **head) -{ - rmtab_node *curr, *back; - - if (!head || !*head) - return; - - curr = *head; back = NULL; - - while (curr) { - if (back) - rmtab_free(back); - back = curr; - curr = curr->rn_next; - } - - if (back) - rmtab_free(back); - - *head = NULL; -} - - -/* - * Finds the differences between two rmtabs. This is generally called when - * we read our file locally. The diff outputs in **diff are collapsed - * noted as '<' and '>' before the hostname, eg - * - * dragracer /tmp2 1 - */ -int -rmtab_diff(rmtab_node *old, rmtab_node *new, rmtab_node **diff) -{ - rmtab_node *old_curr, *new_curr, *last = NULL; - int rv; - char buf[MAXHOSTNAMELEN]; - - if (!diff) - return -1; - - old_curr = old; - new_curr = new; - - /* This loop will exit when the first list is exhausted. */ - while (old_curr && new_curr) { - - /* Entries the same. */ - if (!(rv = rmtab_cmp(old_curr, new_curr))) { - old_curr = old_curr->rn_next; - new_curr = new_curr->rn_next; - continue; - } - - /* Old < new = deleted entry */ - if (rv < 0) { - snprintf(buf, sizeof(buf), "<%s", - old_curr->rn_hostname); - last = rmtab_insert(diff, last, buf, old_curr->rn_path, - old_curr->rn_count); - old_curr = old_curr->rn_next; - continue; - } - - /* old > new = new entry */ - snprintf(buf, sizeof(buf), ">%s", new_curr->rn_hostname); - last = rmtab_insert(diff, last, buf, new_curr->rn_path, - new_curr->rn_count); - new_curr = new_curr->rn_next; - } - - /* Meaning only one of the two following loops actually is executed:*/ - - /* Add remaining stuff in 'old' to 'deleted' list */ - for (;old_curr; old_curr = old_curr->rn_next) { - snprintf(buf, sizeof(buf), "<%s", old_curr->rn_hostname); - last = rmtab_insert(diff, last, buf, old_curr->rn_path, - old_curr->rn_count); - } - - /* Add remaining stuff in 'new' to 'added' list. */ - for (;new_curr; new_curr = new_curr->rn_next) { - snprintf(buf, sizeof(buf), ">%s", new_curr->rn_hostname); - last = rmtab_insert(diff, last, buf, new_curr->rn_path, - new_curr->rn_count); - } - - return 0; -} - - -/* - * strips the "diff" character ('>' || '<') from the beginning of the hostname - * in *src and stores the resulting stuff in *dest. - */ -static inline void -un_diffize(rmtab_node *dest, rmtab_node *src) -{ - dest->rn_hostname = strdup(&src->rn_hostname[1]); - dest->rn_path = strdup(src->rn_path); - dest->rn_count = src->rn_count; - dest->rn_next = NULL; -} - - -/* - * Merges 'patch' list with **head. - * Modifies list in **head; leaves *patch unchanged. This is generally - * called when we receive an update from a peer. - */ -int -rmtab_merge(rmtab_node **head, rmtab_node *patch) -{ - rmtab_node *curr, *oldp = NULL, *last = NULL; - rmtab_node tmpnode; - int rv = -1; - - /* Delete all matching entries */ - for (curr = patch; curr; curr = curr->rn_next) { - - un_diffize(&tmpnode, curr); - - if (curr->rn_hostname[0] == '<') { - if ((oldp = __rmtab_remove(head, &tmpnode))) { - rmtab_free(oldp); - oldp = NULL; - } - } else if (curr->rn_hostname[0] == '>') { - if ((last = rmtab_insert(head, last, - tmpnode.rn_hostname, - tmpnode.rn_path, - tmpnode.rn_count)) == NULL) { - rv = -1; - break; - } - } else { - /* EEEEEKKKK */ - rv = -1; - break; - } - - /* - * Free anything we allocated - */ - if (tmpnode.rn_hostname) { - free(tmpnode.rn_hostname); - tmpnode.rn_hostname = NULL; - } - if (tmpnode.rn_path) { - free(tmpnode.rn_path); - tmpnode.rn_path = NULL; - } - } - - if (tmpnode.rn_hostname) - free(tmpnode.rn_hostname); - if (tmpnode.rn_path) - free(tmpnode.rn_path); - - return 0; -} - - -/* - * Builds a list by parsing an rmtab in *fp... pretty simple - */ -int -rmtab_import(rmtab_node **head, FILE *fp) -{ - int n = 0; - char line[MAXPATHLEN]; - char *hostname, *path, *cnt; - int count = 0; - rmtab_node *last = NULL; - - if (!fp || !head) - return 0; - - if (fp_lock(fp, F_RDLCK) == -1) { - perror("fplock"); - return -1; - } - - while (fgets(line,sizeof(line),fp) != NULL) { - hostname = strtok(line, ":"); - path = strtok(NULL, ":"); - - /* mount count corresponding to the entry */ - cnt = strtok(NULL, ":"); - if (cnt) - count = strtol(cnt, NULL, 0); - - if (!hostname || !path || !count) - /* End - malformed last line */ - break; - - if ((last = rmtab_insert(head, last, hostname, path, - count)) != NULL) - n++; - } - - fp_unlock(fp); - return n; -} - - -/* - * Writes rmtab to export file *fp - */ -int -rmtab_export(rmtab_node *head, FILE *fp) -{ - rmtab_node *curr; - - /* - * lhh - fix - we removed the check for !head, because we _CAN_ have - * an empty /var/lib/nfs/rmtab!! - */ - if (!fp) - return -1; - - if (fp_lock(fp, F_WRLCK) == -1) - return -1; - - for (curr = head; curr; curr = curr->rn_next) - fprintf(fp,"%s:%s:0x%08x\n",curr->rn_hostname, curr->rn_path, - curr->rn_count); - - fp_unlock(fp); - return 0; -} - - -/* - * - */ -int -rmtab_read(rmtab_node **head, char *filename) -{ - FILE *fp; - int rv = 0; - int esave = 0; - - if (!filename || !strlen(filename)) - return -1; - - fp = fopen(filename, "r"); - if (!fp) { - /* It's ok if it's not there. */ - if (errno == ENOENT) { - close(open(filename, O_WRONLY|O_SYNC|O_CREAT, S_IRUSR | S_IWUSR)); - return 0; - } - perror("fopen"); - return -1; - } - - rv = rmtab_import(head, fp); - esave = errno; - - fclose(fp); - errno = esave; - return rv; -} - - -/* - * Writes rmtab list in *head to *filename; in an atomic fashion - */ -int -rmtab_write_atomic(rmtab_node *head, char *filename) -{ - char tmpfn[MAXPATHLEN], - oldfn[MAXPATHLEN], - realfn[MAXPATHLEN]; - FILE *fp; - int len, tfd, ofd; - int rv = -1; - - memset(realfn, 0, sizeof(realfn)); - memset(oldfn, 0, sizeof(oldfn)); - memset(tmpfn, 0, sizeof(tmpfn)); - - len = strlen(filename); - if (len > (MAXPATHLEN - 1)) - len = MAXPATHLEN - 1; - - memcpy(realfn, filename, len); - - /* chop off the end - GLIBC modifies the argument here */ - dirname(realfn); - - snprintf(oldfn, sizeof(oldfn), "%s/tmp.XXXXXX", realfn); - snprintf(tmpfn, sizeof(tmpfn), "%s/tmp.XXXXXX", realfn); - - if ((ofd = mkstemp(oldfn)) == -1) - return -1; - if ((tfd = mkstemp(tmpfn)) == -1) { - close(ofd); - unlink(oldfn); - return -1; - } - - /* Kill the file so we can link it (else it'll not work) */ - close(ofd); - unlink(oldfn); - - /* set up the link */ - if (link(filename, oldfn) == -1) - goto fail; - - /* Export the file. Yes, we have two fd's on it now. That's ok :) */ - if (!(fp = fopen(tmpfn, "w"))) - goto fail; - - if (rmtab_export(head, fp) == -1) - goto fail; - - fsync(fileno(fp)); - fclose(fp); - - /* atomic update */ - if (rename(tmpfn, filename) == -1) - goto fail; - - if (unlink(oldfn) == -1) - goto fail; - - rv = 0; -fail: - close(tfd); - - return rv; -} - - -/* - * Well, 1106 bytes per transaction is a bit much, especially for - * busy nfs clusters... so, we invent 'compact', which simply eliminates - * all dead data. We basically have two strings + their trailing NULLs, - * and one int (the mount count) - */ -size_t -rmtab_pack_size(rmtab_node *head) -{ - rmtab_node *curr; - size_t total = 0; - - for (curr = head; curr; curr = curr->rn_next) { - /* leave space for NULLs */ - total += strlen(curr->rn_hostname) + 1; - total += strlen(curr->rn_path) + 1; - total += sizeof(curr->rn_count); /* uint32_t */ - } - - return total; -} - - -/* - * rmtab_pack - * - * stores the list in *head in *buf - packed as much as possible without - * actually employing compression. - * - * host.domain.com\0/usr/src\0####host2.domain.com\0/usr/src\0#### - */ -int -rmtab_pack(char *buf, rmtab_node *head) -{ - int n = 0; - char *bptr = buf; - rmtab_node *curr; - size_t len; - uint32_t c_tmp; - - /* Pass 2 */ - for (curr = head; curr; curr = curr->rn_next) { - /* Hostname */ - len = strlen(curr->rn_hostname); - memcpy(bptr, curr->rn_hostname, len); - bptr[len] = 0; - bptr += (len + 1); /* space for the NULL */ - - /* path */ - len = strlen(curr->rn_path); - memcpy(bptr, curr->rn_path, len); - bptr[len] = 0; - bptr += (len + 1); - - /* count */ - len = sizeof(curr->rn_count); - - /* Flip-endianness */ - c_tmp = curr->rn_count; /* uint32_t! */ - swab32(c_tmp); - - memcpy(bptr, &c_tmp, len); - bptr += len; - - n++; - } - - return n; -} - - -/* - * rmtab_unpack - * .... reverse of rmtab_pack. - */ -int -rmtab_unpack(rmtab_node **head, char *src, size_t srclen) -{ - int n = 0; - char *hostp, *pathp; - uint32_t *countp; - size_t len; - size_t total = 0; - rmtab_node *last = NULL; - - if (!src[0]) - return 0; - - hostp = src; - - while (total < srclen) { - len = strlen(hostp) + 1; - pathp = hostp + len; - - len += strlen(pathp) + 1; - - /* flip-endianness if require */ - countp = (uint32_t *)(hostp + len); - swab32(*countp); - - len += sizeof(uint32_t); - - if ((last = rmtab_insert(head, NULL, hostp, pathp, - *countp)) == NULL) - return -1; - - hostp += len; - total += len; - - n++; - } - - return n; -} - - -int -rmtab_cmp_min(rmtab_node *left, rmtab_node *right) -{ - int rv = 0; - - if (!left || !right) - return ( !!right - !!left ); - - if ((rv = strcmp(left->rn_hostname, right->rn_hostname))) - return rv; - - return (strcmp(left->rn_path, right->rn_path)); -} - - -/* - * Compares two rmtab_nodes. - */ -int -rmtab_cmp(rmtab_node *left, rmtab_node *right) -{ - int rv; - - if ((rv = rmtab_cmp_min(left,right))) - return rv; - - if (left->rn_count > right->rn_count) - return -1; - - return (left->rn_count < right->rn_count); -} - - -/* - * Kill an old rmtab in dest and overwrite with *src. - */ -int -rmtab_move(rmtab_node **dest, rmtab_node **src) -{ - rmtab_kill(dest); - - *dest = *src; - *src = NULL; - - return 0; -} - - -#ifdef DEBUG -/* - * prints the contents of **head - */ -int -rmtab_dump(rmtab_node *head) -{ - rmtab_node *curr; - - for (curr = head; curr; curr = curr->rn_next) - printf("%s:%s:0x%08x\n",curr->rn_hostname,curr->rn_path, - curr->rn_count); - return 0; -} -#endif -