/* * Disable the device from the kernel configuration. * * RETURN: * 0 on success * non-zero on failure. * * Failures are reported to the user. */ static int disable_dev(const caddr_t path) { struct stat stb; sv_conf_t svc; int fd; sv_check_cluster(path); if (stat(path, &stb) < 0) { svc.svc_major = (major_t)-1; svc.svc_minor = (minor_t)-1; } else { svc.svc_major = major(stb.st_rdev); svc.svc_minor = minor(stb.st_rdev); } if ((fd = open(sv_rpath, O_RDONLY)) < 0) { warn(NULL, gettext("unable to open %s: %s"), sv_rpath, strerror(errno)); return (-1); } (void) strcpy(svc.svc_path, path); svc.svc_error = spcs_s_ucreate(); /* * Issue the ioctl to attempt to disable this device. Note that all * the libdscfg details are handled elsewhere. */ if (ioctl(fd, SVIOC_DISABLE, &svc) < 0) { if (errno != SV_EDISABLED) { spcs_log("sv", &svc.svc_error, gettext("%s: unable to disable %s"), program, path); warn(&svc.svc_error, gettext("unable to disable %s"), path); (void) close(fd); return (-1); } } spcs_log("sv", NULL, gettext("%s: disabled %s"), program, path); spcs_s_ufree(&svc.svc_error); (void) close(fd); return (0); }
static void lock_stat() { char *lt = "Unknown"; struct lockdaemon *ldp; int i; switch (the_lock.type) { case LOCK_NOTLOCKED: lt = "not locked"; break; case LOCK_READ: lt = "read locked"; break; case LOCK_WRITE: lt = "write locked"; break; } spcs_log("cfglockd", NULL, "Lock is %s (%d)", lt, the_lock.type); spcs_log("cfglockd", NULL, "There are %d holders of the lock", the_lock.nholders); if (the_lock.nholders > 0) { for (i = 0; i < the_lock.nholders; i++) spcs_log("cfglockd", NULL, "holding_pid[%d] = %6d", i, the_lock.holding_pid[i]); } spcs_log("cfglockd", NULL, "holder daemon was %s port %hu, remote %x", dp_addr(&the_lock.holder), the_lock.holder.sin_port, the_lock.remote_daemon); spcs_log("cfglockd", NULL, "Lock queue, %d requests", next_req); for (i = 0; i < next_req; i++) { spcs_log("cfglockd", NULL, "request %d type %d order %d", i, lock_queue[i].type, lock_queue[i].order); spcs_log("cfglockd", NULL, " client %s port %hu, pid %d", dp_addr(&lock_queue[i].remote), lock_queue[i].remote.sin_port, lock_queue[i].pid); } spcs_log("cfglockd", NULL, "Daemon list"); for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { if (ldp->inuse == 0) break; spcs_log("cfglockd", NULL, "daemon %d, %s port %hu", i, dp_addr(&ldp->host), ldp->host.sin_port); spcs_log("cfglockd", NULL, " up %d timeout %ld missed %d state %d\n", ldp->up, ldp->timeout, ticker - ldp->timeout, ldp->state); } }
static int is_duplicate(cfglockd_t type, pid_t pid, uint8_t seq) { struct unlock_s *bufp; int i; if (!pid) { return (0); } for (i = 0, bufp = unlock_buf; bufp->pid && i < MAX_UNLOCK; i++, bufp++) { if (bufp->pid == pid && bufp->seq == seq) { /* throw message away */ #ifdef DEBUG spcs_log("cfglockd", NULL, "duplicate '%d' request received from %d", type, pid); #endif return (1); } } /* add it to the list */ bcopy(unlock_buf, &unlock_buf[ 1 ], sizeof (unlock_buf) - sizeof (struct unlock_s)); (*unlock_buf).pid = pid; (*unlock_buf).seq = seq; return (0); }
static void term(int sig) { (void) unlink(CFG_PIDFILE); spcs_log("cfglockd", NULL, "pid %d terminate on signal %d", getpid(), sig); exit(0); }
void init_host_list(void) { host_list = calloc(1, sizeof (host_list_t)); if (host_list == NULL) { spcs_log("sndr", NULL, gettext("host list not initialized, cannot run")); rdc_err(NULL, gettext("host list not initialized, cannot run")); } (void) mutex_init(&host_list->hosts_mutex, USYNC_THREAD, NULL); }
static void daemon_alive(daemonaddr_t *daemon, int32_t order) { struct lockdaemon *ldp; int i; for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) { if (ldp->inuse == 0) break; if (cmp_addr(&(ldp->host), daemon) == 0) { ldp->order = order; ldp->timeout = ticker; if (ldp->up == 0) { spcs_log("cfglockd", NULL, "daemon restarted on %s\n", dp_addr(daemon)); DPF((stderr, "daemon restarted on %s\n", dp_addr(daemon))); ldp->up = 1; goto come_up; } return; } } /* new daemon has announced itself */ if (i < MAX_DAEMONS) { DPF((stderr, "new daemon on %s\n", dp_addr(daemon))); spcs_log("cfglockd", NULL, "new daemon on %s\n", dp_addr(daemon)); ldp->host = *daemon; ldp->inuse = 1; ldp->timeout = ticker; ldp->order = order; } else { /* problem, more daemons than expected */ i++; } come_up: if (the_lock.type == LOCK_WRITE && the_lock.remote_daemon == NULL) send_lockmsg(WRITE_LOCK, (pid_t)0, daemon, 0); }
int get_cfg_setid(CFGFILE *cfg, char *ctag, char *tohost, char *tofile) { int setnum = 0; int close_cfg = 0; char key[CFG_MAX_KEY]; char setid[64]; if (cfg == NULL) { close_cfg = 1; if ((cfg = cfg_open(NULL)) == NULL) { return (-1); /* message printed by caller */ } if (!cfg_lock(cfg, CFG_RDLOCK)) { cfg_close(cfg); return (-1); } } setnum = find_setnumber_in_libcfg(cfg, ctag, tohost, tofile); if (setnum < 0) return (setnum); (void) snprintf(key, CFG_MAX_KEY, "sndr.set%d.options", setnum); if (cfg_get_single_option(cfg, CFG_SEC_CONF, key, "setid", setid, sizeof (setid)) < 0) { if (close_cfg) cfg_close(cfg); spcs_log("sndr", NULL, gettext("%s unable to get unique setid " "for %s:%s"), program, tohost, tofile); return (-1); } if (close_cfg) cfg_close(cfg); return (atoi(setid)); }
static void send_lockmsg(int cmd, pid_t pid, daemonaddr_t *dp, uint8_t seq) { struct lock_msg message_buf; int rc; if (msgtrace && debugfile) { time_t t = time(0); (void) fprintf(debugfile, "%19.19s send %-9.9s to %s\n", ctime(&t), lockd_msg(cmd), dp_addr(dp)); } DPF((stderr, "send %d to %s port %hu\n", cmd, dp_addr(dp), dp->sin_port)); message_buf.message = cmd; message_buf.pid = pid; message_buf.order = order; message_buf.seq = seq; do { rc = sendto(lock_soc, &message_buf, sizeof (message_buf), 0, (struct sockaddr *)dp, sizeof (struct sockaddr)); } while (rc == -1 && errno == EINTR); if (rc == -1) spcs_log("cfglockd", NULL, "sendto rc -1 errno %d", errno); }
static void init(int argc, char *argv[]) { #if defined(_SunOS_5_6) || defined(_SunOS_5_7) || defined(_SunOS_5_8) struct rlimit rl; #endif int c, i, x; int rc; char *cp = NULL; struct itimerval tv; struct timeval tp; socklen_t len = sizeof (thishost); int exe = 0; pid_t pid; FILE *fp; lstate = (getenv("LOCKD_STATE") != NULL); msgtrace = (getenv("LOCKD_MSG") != NULL); /* * Fork off a child that becomes the daemon. */ #ifndef TTY_MESSAGES if ((rc = fork()) > 0) exit(0); else if (rc < 0) { spcs_log("cfglockd", NULL, "can't fork %d", errno); (void) fprintf(stderr, gettext("dscfglockd: cannot fork: %s\n"), strerror(errno)); exit(1); } #endif /* * In child - become daemon. */ #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8) /* use closefrom(3C) from PSARC/2000/193 when possible */ closefrom(CLOSE_FD); #else (void) getrlimit(RLIMIT_NOFILE, &rl); for (i = CLOSE_FD; i < rl.rlim_max; i++) (void) close(i); #endif #ifdef DEBUG #ifndef TTY_MESSAGES (void) open("/dev/console", O_WRONLY|O_APPEND); (void) dup(0); (void) dup(0); #endif #endif (void) close(0); if (msgtrace || lstate) { debugfile = fopen("/var/tmp/dscfglockd.out", "a"); if (debugfile) { time_t t = time(0); setbuf(debugfile, (char *)0); (void) fprintf(debugfile, "%19.19s dscfglockd start\n", ctime(&t)); } } (void) setpgrp(); spcs_log("cfglockd", NULL, "new lock daemon, pid %d", getpid()); /* * Catch as unexpected all signals apart from SIGTERM. */ for (i = 1; i < _sys_nsig; i++) (void) sigset(i, unexpected); (void) sigset(SIGTERM, term); for (i = 0; (c = getopt(argc, argv, "df:e:")) != EOF; i++) { switch (c) { case 'd': debug = 1; break; case 'e': exe = 1; if (cp) { usage(); } cp = optarg; break; case 'f': if (cp) { usage(); } cp = optarg; break; default: usage(); break; } } ifc = (struct ifconf *)malloc(sizeof (struct ifconf)); if (ifc == NULL) { perror(CFG_PIDFILE); DPF((stderr, "Can't open pid file\n")); exit(1); } (void) memset((char *)ifc, 0, sizeof (struct ifconf)); getmyaddrs(ifc); /* * if (lockdaemonalive()) { * (void) fprintf(stderr, "%s: %s\n", program, * gettext("There is already a live lockdaemon")); * exit(1); * } */ if ((fp = fopen(CFG_PIDFILE, "w")) == NULL) { perror(CFG_PIDFILE); DPF((stderr, "Can't open pid file\n")); exit(1); } (void) fprintf(fp, "%ld\n", getpid()); (void) fclose(fp); /* order should be set to node number within cluster */ order = cfg_iscluster(); cfg_lfinit(); if (!order) { (void) gettimeofday(&tp, NULL); srand48(tp.tv_usec); order = lrand48(); if (debugfile) { (void) fprintf(debugfile, "WARNING: order number " "is 0 -- changing randomly to %d\n", order); } } c = 0; for (i = 0; (x = cfg_filelock(i, 0)) != CFG_LF_EOF; i++) { if (x == CFG_LF_AGAIN) { cfg_readpid(i, &pid); if (c++ == 0) spcs_log("cfglockd", NULL, "init .dscfg.lck slot %d pid %d locked", i, pid); DPF((stderr, "client process %ld still alive\n", pid)); continue; /* can't take lock, must be still alive */ } cfg_writepid(i, 0); (void) cfg_fileunlock(i); } tv.it_interval.tv_sec = TIMEOUT_SECS; tv.it_interval.tv_usec = 0; tv.it_value = tv.it_interval; bzero(unlock_buf, sizeof (unlock_buf)); next_q = 0; build_daemon_list(cp, exe); if ((lock_soc = socket(pf_inet, SOCK_DGRAM, 0)) < 0) { (void) fprintf(stderr, "%s: %s\n", program, gettext("failed to create socket")); perror("socket"); spcs_log("cfglockd", NULL, "couldn't create socket"); exit(1); } thishost.sin_family = AF_INET; thishost.sin_addr.s_addr = INADDR_ANY; thishost.sin_port = htons(lock_port); rc = bind(lock_soc, (struct sockaddr *)&thishost, sizeof (thishost)); if (rc < 0) { perror("bind"); spcs_log("cfglockd", NULL, "couldn't bind"); exit(1); } if (getsockname(lock_soc, (struct sockaddr *)&thishost, &len) < 0) perror("getsockname"); send_aliveall(); (void) sigset(SIGALRM, keepalive); (void) setitimer(ITIMER_REAL, &tv, NULL); /* * wait 2 time outs before allowing a lock to find if someone else * currently has the lock. */ }
static void unexpected(int sig) { spcs_log("cfglockd", NULL, "pid %d unexpected signal %d, ignoring", getpid(), sig); }
static void build_daemon_list(char *cf_file, int exe) { FILE *fp; char host[1024]; int port; int i; struct hostent *hp; struct lockdaemon *ldp; if ((hp = gethostbyname("localhost")) == NULL) { (void) fprintf(stderr, "%s: Can't find hostent for %s\n", program, "localhost"); spcs_log("cfglockd", NULL, "couldn't find localhost"); exit(1); } (void) memcpy(&(localhost.sin_addr.s_addr), *(hp->h_addr_list), sizeof (localhost.sin_addr)); if (cf_file == NULL) { (void) endhostent(); return; } if (exe) { if ((fp = popen(cf_file, "r")) == NULL) { perror(cf_file); (void) fprintf(stderr, "%s: Can't open config program\n", program); spcs_log("cfglockd", NULL, "couldn't read config"); exit(1); } } else { if ((fp = fopen(cf_file, "r")) == NULL) { perror(cf_file); (void) fprintf(stderr, "%s: Can't open config file\n", program); spcs_log("cfglockd", NULL, "couldn't read config"); exit(1); } } ldp = daemon_list; while ((i = fscanf(fp, "%s %d\n", host, &port)) != EOF) { if (host[0] == '#') /* line starting with # are comments */ continue; if (i == 1) { port = lock_port; } else { if (strcmp(host, "localhost") == 0) { lock_port = port; continue; } } if ((hp = gethostbyname(host)) == NULL) { (void) fprintf(stderr, "%s: Can't find hostent for %s\n", program, host); continue; } (void) memcpy(&(ldp->host.sin_addr.s_addr), *(hp->h_addr_list), sizeof (ldp->host.sin_addr)); DPF((stderr, "daemon: %s\t%s\n", inet_ntoa(ldp->host.sin_addr), hp->h_name)); if (islocalhost(&(ldp->host))) { DPF((stderr, "is an alias for this host, skipping\n")); continue; } ldp->host.sin_port = htons((short)port); ldp->host.sin_family = hp->h_addrtype; ldp->inuse = 1; ldp->up = 1; ldp++; } if (exe) (void) pclose(fp); else (void) fclose(fp); (void) endhostent(); }
static int enable_dev(sv_name_t *svn) { char buf[CFG_MAX_BUF]; struct stat stb; sv_conf_t svc; int fd; int sev; int rc; char *lcltag; char *altname; sv_check_cluster(svn->svn_path); sv_cfg_open(CFG_WRLOCK); bzero(&svc, sizeof (svc)); if (stat(svn->svn_path, &stb) != 0) { warn(NULL, gettext("unable to access %s: %s"), svn->svn_path, strerror(errno)); return (1); } if (!S_ISCHR(stb.st_mode)) { warn(NULL, gettext("%s is not a character device - ignored"), svn->svn_path); return (1); } svc.svc_major = major(stb.st_rdev); svc.svc_minor = minor(stb.st_rdev); (void) strncpy(svc.svc_path, svn->svn_path, sizeof (svc.svc_path)); fd = open(sv_rpath, O_RDONLY); if (fd < 0) { warn(NULL, gettext("unable to open %s: %s"), svn->svn_path, strerror(errno)); return (1); } svc.svc_flag = svn->svn_mode; svc.svc_error = spcs_s_ucreate(); /* first, check for duplicates */ rc = cfg_get_canonical_name(cfg, svn->svn_path, &altname); if (rc < 0) { spcs_log("sv", NULL, gettext("Unable to parse config file")); warn(NULL, gettext("Unable to parse config file")); (void) close(fd); return (1); } if (rc) { error(NULL, gettext("'%s' has already been configured as " "'%s'. Re-enter command with the latter name."), svn->svn_path, altname); } /* secondly, try to insert it into the dsvol config */ if (implicit_tag && *implicit_tag) { lcltag = implicit_tag; } else if (cfg_cluster_tag && *cfg_cluster_tag) { lcltag = cfg_cluster_tag; } else { lcltag = "-"; } rc = cfg_add_user(cfg, svn->svn_path, lcltag, "sv"); if (CFG_USER_ERR == rc) { spcs_log("sv", NULL, gettext("%s: unable to put %s into dsvol cfg"), program, svn->svn_path); warn(NULL, gettext("unable to put %s into dsvol cfg"), svn->svn_path); (void) close(fd); return (1); } cfg_changed = 1; if (CFG_USER_OK == rc) { /* success */ (void) close(fd); return (0); } if (ioctl(fd, SVIOC_ENABLE, &svc) < 0) { if ((CFG_USER_REPEAT == rc) && (SV_EENABLED == errno)) { /* it's ok -- we were just double-checking */ (void) close(fd); return (0); } spcs_log("sv", &svc.svc_error, gettext("%s: unable to enable %s"), program, svn->svn_path); warn(&svc.svc_error, gettext("unable to enable %s"), svn->svn_path); /* remove it from dsvol, if we're the ones who put it in */ if (CFG_USER_FIRST == rc) { (void) cfg_rem_user(cfg, svn->svn_path, lcltag, "sv"); } (void) close(fd); return (1); } spcs_log("sv", NULL, gettext("%s: enabled %s"), program, svn->svn_path); if (implicit_tag != NULL) { #ifdef DEBUG if (cfg_cluster_tag != NULL) { error(NULL, gettext("enable_dev: -C %s AND implicit_tag %s!"), cfg_cluster_tag, implicit_tag); } #endif (void) snprintf(buf, sizeof (buf), "%s - %s", svc.svc_path, implicit_tag); } else { (void) strcpy(buf, svc.svc_path); } rc = 0; if (cfg_put_cstring(cfg, "sv", buf, sizeof (buf)) < 0) { warn(NULL, gettext("unable to add %s to configuration storage: %s"), svc.svc_path, cfg_error(&sev)); rc = 1; } cfg_changed = 1; spcs_s_ufree(&svc.svc_error); (void) close(fd); return (rc); }
static void compare_tag(char *path) { char buf[CFG_MAX_BUF], vol[CFG_MAX_BUF], cnode[CFG_MAX_BUF]; char key[CFG_MAX_KEY]; int found, setnumber, i; char *tag; sv_check_cluster(path); cfg_resource(cfg, (char *)NULL); /* reset */ cfg_rewind(cfg, CFG_SEC_CONF); #ifdef DEBUG if (cfg_cluster_tag != NULL && implicit_tag != NULL) { error(NULL, gettext("compare_tag: -C %s AND implicit_tag %s!"), cfg_cluster_tag, implicit_tag); } #endif if (cfg_cluster_tag != NULL) tag = cfg_cluster_tag; else if (implicit_tag != NULL) tag = implicit_tag; else tag = "-"; found = 0; for (i = 0; i < sv_max_devices; i++) { setnumber = i + 1; (void) snprintf(key, sizeof (key), "sv.set%d", setnumber); if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0) { break; } if (sscanf(buf, "%s - %s", vol, cnode) != 2) { continue; } if (strcmp(path, vol) == 0) { found = 1; break; } } if (!found) { warn(NULL, gettext("unable to find %s in the configuration"), path); return; } /* have name match, compare cnode to new tag */ if (strcmp(tag, cnode) == 0) { /* cluster tags match */ return; } /* need to change the cluster tag */ (void) snprintf(key, sizeof (key), "sv.set%d.cnode", setnumber); if (cfg_put_cstring(cfg, key, tag, strlen(tag)) < 0) { warn(NULL, gettext("unable to change cluster tag for %s"), path); return; } cfg_changed = 1; /* change "-" tags to "" for display purposes */ if (strcmp(tag, "-") == 0) tag = ""; if (strcmp(cnode, "-") == 0) (void) strcpy(cnode, ""); (void) printf( gettext("%s: changed cluster tag for %s from \"%s\" to \"%s\"\n"), program, path, cnode, tag); spcs_log("sv", NULL, gettext("%s: changed cluster tag for %s from \"%s\" to \"%s\""), program, path, cnode, tag); }
int main(int argc, char *argv[]) #endif { char fromhost[MAX_RDC_HOST_SIZE]; char tohost[MAX_RDC_HOST_SIZE]; char fromfile[NSC_MAXPATH]; char tofile[NSC_MAXPATH]; char frombitmap[NSC_MAXPATH]; char tobitmap[NSC_MAXPATH]; char directfile[NSC_MAXPATH]; char diskqueue[NSC_MAXPATH]; char group[NSC_MAXPATH]; char lhost[MAX_RDC_HOST_SIZE]; int pairs; int pid; int flag = 0; int doasync; int rc; char *required; int setid; (void) setlocale(LC_ALL, ""); (void) textdomain("rdc"); program = basename(argv[0]); rc = rdc_check_release(&required); if (rc < 0) { rdc_err(NULL, gettext("unable to determine the current " "Solaris release: %s\n"), strerror(errno)); } else if (rc == FALSE) { rdc_err(NULL, gettext("incorrect Solaris release (requires %s)\n"), required); } rdc_maxsets = rdc_get_maxsets(); if (rdc_maxsets == -1) { spcs_log("sndr", NULL, gettext("%s unable to get maxsets value from kernel"), program); rdc_err(NULL, gettext("unable to get maxsets value from kernel")); } pair_list = calloc(rdc_maxsets, sizeof (*pair_list)); if (pair_list == NULL) { rdc_err(NULL, gettext( "unable to allocate pair_list" " array for %d sets"), rdc_maxsets); } if (parseopts(argc, argv, &flag)) return (1); pairs = read_libcfg(flag); if (flag == RDC_CMD_FIXSETIDS) { if (pairs) { spcs_log("sndr", NULL, gettext("Fixed %d Remote Mirror" " set IDs"), pairs); #ifdef DEBUG rdc_warn(NULL, gettext("Fixed %d Remote Mirror set " "IDs"), pairs); #endif } return (0); } if (pairs == 0) { #ifdef DEBUG rdc_err(NULL, gettext("Config contains no dual copy sets")); #else return (0); #endif } while (pairs--) { pid = fork(); if (pid == -1) { /* error forking */ perror("fork"); continue; } if (pid > 0) /* this is parent process */ continue; /* * At this point, this is the child process. Do the operation */ strncpy(fromfile, pair_list[pairs].ffile, NSC_MAXPATH); strncpy(tofile, pair_list[pairs].tfile, NSC_MAXPATH); strncpy(frombitmap, pair_list[pairs].fbitmap, NSC_MAXPATH); strncpy(fromhost, pair_list[pairs].fhost, MAX_RDC_HOST_SIZE); strncpy(tohost, pair_list[pairs].thost, MAX_RDC_HOST_SIZE); strncpy(tobitmap, pair_list[pairs].tbitmap, NSC_MAXPATH); strncpy(directfile, pair_list[pairs].directfile, NSC_MAXPATH); strncpy(diskqueue, pair_list[pairs].diskqueue, NSC_MAXPATH); strncpy(group, pair_list[pairs].group, NSC_MAXPATH); strncpy(lhost, pair_list[pairs].lhost, MAX_RDC_HOST_SIZE); doasync = pair_list[pairs].doasync; setid = pair_list[pairs].setid; if (rdc_operation(fromhost, fromfile, frombitmap, tohost, tofile, tobitmap, flag, directfile, group, diskqueue, doasync, lhost, setid) < 0) { exit(255); } exit(0); } while ((wait((int *)0) > 0)) ; return (0); }