[DRBD-cvs] user by phil; The unpopular user-dialog in the startup...
drbd-user@lists.linbit.com
drbd-user@lists.linbit.com
Mon, 5 Jul 2004 14:24:36 +0200 (CEST)
DRBD CVS committal
Author : phil
Project : drbd
Module : user
Dir : drbd/user
Modified Files:
Tag: rel-0_7-branch
drbdadm.h drbdadm_main.c
Log Message:
The unpopular user-dialog in the startup script is back.
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/Attic/drbdadm.h,v
retrieving revision 1.1.2.22
retrieving revision 1.1.2.23
diff -u -3 -r1.1.2.22 -r1.1.2.23
--- drbdadm.h 26 Apr 2004 08:36:29 -0000 1.1.2.22
+++ drbdadm.h 5 Jul 2004 12:24:30 -0000 1.1.2.23
@@ -3,12 +3,16 @@
#include <linux/drbd_config.h>
#include <sys/utsname.h>
+#include <sys/types.h>
#define E_syntax 2
#define E_usage 3
#define E_config_invalid 10
#define E_exec_error 20
#define E_thinko 42 /* :) */
+
+#define SF_MaySleep 2
+#define SF_ReturnPid 4
/* for check_uniq(): Check for uniqueness of certain values...
* comment out if you want to NOT choke on the first conflict */
===================================================================
RCS file: /var/lib/cvs/drbd/drbd/user/Attic/drbdadm_main.c,v
retrieving revision 1.1.2.56
retrieving revision 1.1.2.57
diff -u -3 -r1.1.2.56 -r1.1.2.57
--- drbdadm_main.c 3 Jul 2004 11:38:11 -0000 1.1.2.56
+++ drbdadm_main.c 5 Jul 2004 12:24:30 -0000 1.1.2.57
@@ -37,6 +37,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#include <sys/poll.h>
#include <unistd.h>
#include <errno.h>
#include <getopt.h>
@@ -78,6 +79,7 @@
extern int adm_adjust(struct d_resource* ,char* );
static int adm_dump(struct d_resource* ,char* );
static int adm_wait_c(struct d_resource* ,char* );
+static int adm_wait_ci(struct d_resource* ,char* );
static int sh_resources(struct d_resource* ,char* );
static int sh_mod_parms(struct d_resource* ,char* );
static int sh_dev(struct d_resource* ,char* );
@@ -124,6 +126,7 @@
{ "wait_connect", adm_wait_c, 0 ,1,1 },
{ "state", adm_generic, "state" ,1,1 },
{ "dump", adm_dump, 0 ,1,1 },
+ { "wait_con_int", adm_wait_ci, 0 ,1,0 },
{ "sh-resources", sh_resources,0 ,0,0 },
{ "sh-mod-parms", sh_mod_parms,0 ,0,0 },
{ "sh-dev", sh_dev, 0 ,0,1 },
@@ -342,10 +345,10 @@
alarm_raised=1;
}
-int m_system(int may_sleep,char** argv)
+pid_t m_system(int flags,char** argv)
{
- int pid,status;
- int rv=-1;
+ pid_t pid;
+ int status,rv=-1;
char **cmdline = argv;
struct sigaction so;
@@ -374,12 +377,16 @@
exit(E_exec_error);
}
- if( !may_sleep ) {
+ if( !(flags&SF_MaySleep) ) {
sigaction(SIGALRM,&sa,&so);
alarm_raised=0;
alarm(25); // Reading the AL & BitMap can take some time.
}
+ if( (flags&SF_ReturnPid) ) {
+ return pid;
+ }
+
while(1) {
if (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR) break;
@@ -398,12 +405,12 @@
}
}
- if( !may_sleep ) {
+ if( !(flags&SF_MaySleep) ) {
alarm(0);
sigaction(SIGALRM,&so,NULL);
}
- if(!may_sleep && rv) {
+ if(!(flags&SF_MaySleep) && rv) {
fprintf(stderr,"Command line was '");
while(*argv) {
fprintf(stderr,"%s",*argv++);
@@ -549,9 +556,148 @@
make_options(opt);
argv[argc++]=0;
- return m_system(1,argv);
+ return m_system(SF_MaySleep,argv);
+}
+
+
+static int childs_running(pid_t* pids,int opts)
+{
+ int i=0,wr,rv=0,status;
+
+ for(i=0;i<nr_resources;i++) {
+ if(pids[i]==0) continue;
+ wr = waitpid(pids[i], &status, opts);
+ if( wr == -1) { // Wait error.
+ if (errno == ECHILD) {
+ pids[i] = 0; // Child exited before ?
+ continue;
+ }
+ perror("waitpid");
+ exit(E_exec_error);
+ }
+ if( wr == 0 ) rv = 1; // Child still running.
+ if( wr > 0 ) pids[i] = 0; // Child exited.
+ }
+ return rv;
}
+static void kill_childs(pid_t* pids)
+{
+ int i;
+
+ for(i=0;i<nr_resources;i++) {
+ if(pids[i]==0) continue;
+ kill(pids[i],SIGINT);
+ }
+}
+
+int gets_timeout(char* s, int size, int timeout)
+{
+ int pr,rr;
+ struct pollfd pfd;
+
+ pfd.fd = fileno(stdin);
+ pfd.events = POLLIN | POLLHUP | POLLERR | POLLNVAL;
+
+ pr = poll(&pfd, 1, timeout);
+
+ if( pr == -1 ) { // Poll error.
+ perror("poll");
+ exit(E_exec_error);
+ }
+
+ if( pr == 1 ) { // Input available.
+ rr = read(fileno(stdin),s,size-1);
+ if(rr == -1) {
+ perror("read");
+ exit(E_exec_error);
+ }
+ s[rr]=0;
+ }
+
+ return pr; // if pr == 0 timeout expired
+}
+
+static char* get_opt_val(struct d_option* base,char* name,char* def)
+{
+ while(base) {
+ if(!strcmp(base->name,name)) {
+ return base->value;
+ }
+ base=base->next;
+ }
+ return def;
+}
+
+static int adm_wait_ci(struct d_resource* ignored ,char* unused)
+{
+ struct d_resource *res,*t;
+ char *argv[20], answer[40];
+ pid_t* pids;
+ struct d_option* opt;
+ int argc,sec,i=0;
+
+ struct sigaction so;
+ struct sigaction sa;
+
+ sa.sa_handler=SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags=SA_NOCLDSTOP;
+
+ sigaction(SIGCHLD,&sa,&so);
+
+ pids = alloca( nr_resources * sizeof(pid_t) );
+
+ for_each_resource(res,t,config) {
+ argc=0;
+ argv[argc++]=drbdsetup;
+ argv[argc++]=res->me->device;
+ argv[argc++]="wait_connect";
+ opt=res->startup_options;
+ make_options(opt);
+ argv[argc++]=0;
+
+ pids[i++]=m_system(SF_MaySleep|SF_ReturnPid, argv);
+ }
+
+ sec = 0;
+ while(sec < 3) {
+ if(!childs_running(pids,WNOHANG)) return 0;
+ sleep(1);
+ sec++;
+ }
+
+ if(childs_running(pids,WNOHANG)) {
+ printf("***************************************************************\n"
+ " DRBD's startup script waits for the peer node(s) to appear.\n"
+ " - In case this node was already a degraded cluster before the\n"
+ " reboot the timeout is %s seconds. [degr-wfc-timeout]\n"
+ " - If the peer was available before the reboot the timeout will\n"
+ " expire after %s seconds. [wfc-timeout]\n"
+ " (These values are for resource '%s'; 0 sec -> wait forever)\n",
+ get_opt_val(config->startup_options,"degr-wfc-timeout","0"),
+ get_opt_val(config->startup_options,"wfc-timeout","0"),
+ config->name);
+
+ printf(" To abort waiting enter 'yes' [%4d]:",sec);
+ do {
+ printf("\e[s\e[31G[%4d]:\e[u",sec); // Redraw sec, preserve cursor pos.
+ fflush(stdout);
+ if(gets_timeout(answer,40,1000)) {
+ if(!strcmp(answer,"yes\n")) {
+ kill_childs(pids);
+ childs_running(pids,0);
+ } else {
+ printf(" To abort waiting enter 'yes' [%4d]:",sec);
+ }
+ }
+ sec++;
+ } while(childs_running(pids,WNOHANG));
+ printf("\n");
+ }
+
+ return 0;
+}
const char* make_optstring(struct option *options)
{
@@ -637,7 +783,7 @@
"fi >/dev/null",
my_ip);
if (ex < 0) { perror("asprintf"); exit(E_thinko); }
- ex = m_system(1,argv);
+ ex = m_system(0,argv);
free(argv[2]); argv[2] = NULL;
if (ex != 0) {
@@ -671,7 +817,7 @@
"fi >/dev/null",
my_ip,his_ip);
if (ex < 0) { perror("asprintf"); exit(E_thinko); }
- ex = m_system(1,argv);
+ ex = m_system(0,argv);
free(argv[2]); argv[2] = NULL;
if (ex != 0) {
ENTRY e, *ep;