[DRBD-cvs] r1649 - in trunk: drbd scripts user

svn at svn.drbd.org svn at svn.drbd.org
Mon Nov 22 23:35:11 CET 2004


Author: phil
Date: 2004-11-22 23:35:08 +0100 (Mon, 22 Nov 2004)
New Revision: 1649

Modified:
   trunk/drbd/drbd_receiver.c
   trunk/scripts/drbd.conf
   trunk/user/drbdadm.h
   trunk/user/drbdadm_main.c
   trunk/user/drbdadm_parser.y
   trunk/user/drbdadm_scanner.fl
   trunk/user/drbdsetup.c
Log:
Implemented the concept of handlers. These handlers are scripts
that are run on demand of the DRBD kernel module.

Currently the config file knows of the following handlers:
* pri-on-incon-degr
* pri-sees-sec-with-higher-gc
* on-disconnect
[more might come]

Code in drbdadm tested slightly, code on the side of the module
is missing or untested.


Modified: trunk/drbd/drbd_receiver.c
===================================================================
--- trunk/drbd/drbd_receiver.c	2004-11-22 14:31:35 UTC (rev 1648)
+++ trunk/drbd/drbd_receiver.c	2004-11-22 22:35:08 UTC (rev 1649)
@@ -1624,6 +1624,23 @@
 	}
 }
 
+void drbd_khelper(drbd_dev *mdev, char* cmd)
+{
+	int ret;
+	char mb[12];
+	char *argv[] = {"/sbin/drbdadm", cmd, mb, NULL };
+	static char *envp[] = { "HOME=/",
+				"TERM=linux",
+				"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+				NULL };
+	
+	snprintf(mb,12,"minor-%d",(int)(mdev-drbd_conf));
+	ret = call_usermodehelper("/sbin/drbdadm",argv,envp,0);
+	if(ret) {
+		ERR("call_usermodhelper failed with %d",ret);
+	}
+}
+
 STATIC void drbd_disconnect(drbd_dev *mdev)
 {
 	D_ASSERT(mdev->state.s.conn < Connected);
@@ -1736,6 +1753,8 @@
 	}
 	clear_bit(DO_NOT_INC_CONCNT,&mdev->flags);
 
+	drbd_khelper(mdev,"on-disconnect");
+
 	INFO("Connection lost.\n");
 }
 

Modified: trunk/scripts/drbd.conf
===================================================================
--- trunk/scripts/drbd.conf	2004-11-22 14:31:35 UTC (rev 1648)
+++ trunk/scripts/drbd.conf	2004-11-22 22:35:08 UTC (rev 1649)
@@ -118,10 +118,20 @@
   #
   protocol C;
 
-  # what should be done in case the cluster starts up in
-  # degraded mode, but knows it has inconsistent data.
-  incon-degr-cmd "echo '!DRBD! pri on incon-degr' | wall ; sleep 60 ; halt -f";
+  handlers {
+    # what should be done in case the node is primary, degraded
+    # (=no connection) and has inconsistent data.
+    pri-on-incon-degr "halt -f";
 
+    # If suddenly the peer presents a higher generation count
+    # than we have, and we are primary.
+    pri-sees-sec-with-higher-gc "halt -f";
+
+    # Commands to run in case we loose connection. Use this script in 
+    # in conjunction with the on-disconnect=suspend_io configuration.
+    # on-disconnect "/usr/lib/drbd/outdate-peer.sh";
+  }
+
   startup {
     # Wait for connection timeout. 
     # The init script blocks the boot process until the resources
@@ -248,7 +258,6 @@
 #
 resource "r1" {
   protocol C;
-  incon-degr-cmd "echo '!DRBD! pri on incon-degr' | wall ; sleep 60 ; halt -f";
   startup {
     wfc-timeout         0;  ## Infinite!
     degr-wfc-timeout  120;  ## 2 minutes.
@@ -285,7 +294,6 @@
 
 resource r2 {
   protocol C;
-  incon-degr-cmd "echo '!DRBD! pri on incon-degr' | wall ; sleep 60 ; halt -f";
 
   startup { wfc-timeout 0; degr-wfc-timeout 120; }
   disk    { on-io-error detach; }
@@ -304,7 +312,7 @@
 
 resource r3 {
   protocol	C;
-  incon-degr-cmd "echo '!DRBD! pri on incon-degr' | wall ; sleep 60 ; halt -f";
+
   startup { wfc-timeout	0; degr-wfc-timeout	120; }
   disk { on-io-error detach; }
   syncer {

Modified: trunk/user/drbdadm.h
===================================================================
--- trunk/user/drbdadm.h	2004-11-22 14:31:35 UTC (rev 1648)
+++ trunk/user/drbdadm.h	2004-11-22 22:35:08 UTC (rev 1649)
@@ -58,13 +58,13 @@
 {
   char* name;
   char* protocol;
-  char* ind_cmd;
   struct d_host_info* me;
   struct d_host_info* peer;
   struct d_option* net_options;
   struct d_option* disk_options;
   struct d_option* sync_options;
   struct d_option* startup_options;
+  struct d_option* handlers;
   struct d_resource* next;
 };
 

Modified: trunk/user/drbdadm_main.c
===================================================================
--- trunk/user/drbdadm_main.c	2004-11-22 14:31:35 UTC (rev 1648)
+++ trunk/user/drbdadm_main.c	2004-11-22 22:35:08 UTC (rev 1649)
@@ -77,7 +77,6 @@
 int adm_generic_l(struct d_resource* ,char* );
 int adm_resize(struct d_resource* ,char* );
 int adm_syncer(struct d_resource* ,char* );
-static int adm_primary(struct d_resource* ,char* );
 static int adm_up(struct d_resource* ,char* );
 extern int adm_adjust(struct d_resource* ,char* );
 static int adm_dump(struct d_resource* ,char* );
@@ -90,6 +89,7 @@
 static int sh_md_dev(struct d_resource* ,char* );
 static int sh_md_idx(struct d_resource* ,char* );
 static int admm_generic(struct d_resource* ,char* );
+static int adm_khelper(struct d_resource* ,char* );
 
 char ss_buffer[255];
 struct utsname nodeinfo;
@@ -122,7 +122,7 @@
   { "disconnect",        adm_generic_s,"disconnect"      ,1,1 },
   { "up",                adm_up,      0                  ,1,1 },
   { "down",              adm_generic_s,"down"            ,1,1 },
-  { "primary",           adm_primary, 0                  ,1,1 },
+  { "primary",           adm_generic_s,"primary"         ,1,1 },
   { "secondary",         adm_generic_s,"secondary"       ,1,1 },
   { "invalidate",        adm_generic_l,"invalidate"      ,1,1 },
   { "invalidate_remote", adm_generic_l,"invalidate_remote",1,1 },
@@ -139,6 +139,9 @@
   { "get-gc",            admm_generic, "get-gc"          ,1,1 },
   { "dump-md",           admm_generic, "dump-md"         ,1,1 },
   { "set-gc",            admm_generic, "set-gc"          ,0,1 },
+  { "pri-on-incon-degr", adm_khelper,  "pri-on-incon-degr",0,1},
+  { "pri-sees-sec-with-higher-gc", adm_khelper,  "pri-sees-sec-with-higher-gc",0,1},
+  { "on-disconnect",     adm_khelper,  "on-disconnect"   ,0,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 },
@@ -181,7 +184,7 @@
 
   printI("%s {\n",name); ++indent;
   while(opts) {
-    if(opts->value) printA(opts->name,opts->value);
+    if(opts->value) printA(opts->name,esc(opts->value));
     else            printI(BFMT,opts->name);
     opts=opts->next;
   }
@@ -226,14 +229,13 @@
 {
   printI("resource %s {\n",esc(res->name)); ++indent;
   printA("protocol",res->protocol);
-  if(res->ind_cmd)
-    printA("incon-degr-cmd",esc(res->ind_cmd));
   dump_host_info(res->me);
   dump_host_info(res->peer);
   dump_options("net",res->net_options);
   dump_options("disk",res->disk_options);
   dump_options("syncer",res->sync_options);
   dump_options("startup",res->startup_options);
+  dump_options("handlers",res->handlers);
   --indent; printf("}\n\n");
 
   return 0;
@@ -324,13 +326,13 @@
   for_each_resource(f,t,res) {
     free(f->name);
     free(f->protocol);
-    free(f->ind_cmd);
     free_host_info(f->me);
     free_host_info(f->peer);
     free_options(f->net_options);
     free_options(f->disk_options);
     free_options(f->sync_options);
     free_options(f->startup_options);
+    free_options(f->handlers);
     free(f);
   }
 }
@@ -554,17 +556,18 @@
   return adm_generic(res,cmd,SLEEPS_LONG);
 }
 
-int adm_primary(struct d_resource* res,char* unused)
+static char* get_opt_val(struct d_option*,char*,char*);
+
+static int adm_khelper(struct d_resource* res ,char* cmd)
 {
-  int rv;
-  char *argv[] = { "/bin/bash", "-c", res->ind_cmd , NULL };
+  char *sh_cmd;
+  char *argv[] = { "/bin/bash", "-c", NULL , NULL };
 
-  rv = adm_generic_s(res,"primary");
-
-  if(rv==21) {
-    rv = m_system(argv,SLEEPS_VERY_LONG);
+  if( (sh_cmd = get_opt_val(res->handlers,cmd,NULL)) ) {
+    argv[2]=sh_cmd;
+    m_system(argv,SLEEPS_VERY_LONG);
   }
-  return rv;
+  return 0;
 }
 
 int adm_connect(struct d_resource* res,char* unused)
@@ -649,7 +652,27 @@
   return rv;
 }
 
+struct d_resource* res_by_minor(const char *id)
+{
+  struct d_resource *res,*t;
+  struct stat sb;
+  int mm;
 
+  if(strncmp(id,"minor-",6)) return NULL;
+  
+  mm = m_strtoll(id+6,1);
+
+  for_each_resource(res,t,config) {
+    if(stat(res->me->device,&sb)) {
+      perror("stat");
+    }
+    if( mm == minor(sb.st_rdev)) {
+      return res;
+    }
+  }
+  return NULL;
+}
+
 /* In case a child exited, or exits, its return code is stored as
    negative number in the pids[i] array */
 static int childs_running(pid_t* pids,int opts)
@@ -1218,6 +1241,7 @@
 	  for_each_resource(res,tmp,config) {
 	    if(!strcmp(argv[i],res->name)) goto found;
 	  }
+	  if( (res=res_by_minor(argv[i])) ) goto found;
 	  fprintf(stderr,"'%s' not defined in your config.\n",argv[i]);
 	  exit(E_usage);
 	found:

Modified: trunk/user/drbdadm_parser.y
===================================================================
--- trunk/user/drbdadm_parser.y	2004-11-22 14:31:35 UTC (rev 1648)
+++ trunk/user/drbdadm_parser.y	2004-11-22 22:35:08 UTC (rev 1649)
@@ -238,7 +238,7 @@
 %token TK_GLOBAL TK_RESOURCE
 %token TK_ON TK_NET TK_DISK_S TK_SYNCER TK_STARTUP
 %token TK_DISABLE_IO_HINTS
-%token TK_PROTOCOL TK_INCON_DEGR_CMD
+%token TK_PROTOCOL TK_HANDLERS
 %token TK_ADDRESS TK_DISK TK_DEVICE TK_META_DISK
 %token <txt> TK_MINOR_COUNT TK_INTEGER TK_STRING
 %token <txt> TK_ON_IO_ERROR TK_SIZE
@@ -248,12 +248,14 @@
 %token <txt> TK_WFC_TIMEOUT TK_DEGR_WFC_TIMEOUT
 %token <txt> TK_KO_COUNT TK_ON_DISCONNECT TK_DIALOG_REFRESH
 %token <txt> TK_ALLOW_TWO_PRIMARIES
+%token <txt> TK_PRI_ON_INCON_DEGR TK_PRI_SEES_SEC_WITH_HIGHER_GC
 
 %type <txt> hostname resource_name
 %type <d_option> disk_stmts disk_stmt
 %type <d_option> net_stmts net_stmt
 %type <d_option> sync_stmts sync_stmt
 %type <d_option> startup_stmts startup_stmt
+%type <d_option> handler_stmts handler_stmt
 %type <d_resource> resources resource
 
 %%
@@ -306,7 +308,6 @@
 		;
 
 res_stmt:	  TK_PROTOCOL	    TK_STRING { c_res->protocol=$2; }
-		| TK_INCON_DEGR_CMD TK_STRING { c_res->ind_cmd=$2;  }
 		;
 
 section:	  TK_DISK_S   disk_stmts
@@ -318,6 +319,8 @@
 		| TK_STARTUP  startup_stmts
 		{ CHKS("startup"); c_res->startup_options=$2; }
 		| TK_ON hostname host_stmts { host_sec($2); }
+		| TK_HANDLERS  handler_stmts
+		{ CHKS("handlers"); c_res->handlers=$2; }
 		;
 
 hostname:	TK_STRING
@@ -419,3 +422,13 @@
 		| TK_DEGR_WFC_TIMEOUT TK_INTEGER
 		{ range_check(R_DEGR_WFC_TIMEOUT,$1,$2);$$=new_opt($1,$2); }
 		;
+
+handler_stmts:	  /* empty */	           { $$ = 0; }
+		| handler_stmts handler_stmt	   { $$=APPEND($1,$2); }
+		;
+
+handler_stmt:	  TK_PRI_ON_INCON_DEGR TK_STRING	{ $$=new_opt($1,$2); }
+		| TK_PRI_SEES_SEC_WITH_HIGHER_GC TK_STRING
+		{ $$=new_opt($1,$2); }
+		| TK_ON_DISCONNECT TK_STRING		{ $$=new_opt($1,$2); }
+		;

Modified: trunk/user/drbdadm_scanner.fl
===================================================================
--- trunk/user/drbdadm_scanner.fl	2004-11-22 14:31:35 UTC (rev 1648)
+++ trunk/user/drbdadm_scanner.fl	2004-11-22 22:35:08 UTC (rev 1649)
@@ -47,7 +47,7 @@
 %option stack
 
 %x RESOURCE GLOBAL
-%x STARTUP DISK NET SYNCER HOST
+%x STARTUP DISK NET SYNCER HOST HANDLERS
 %x SEMICOLON ASSIGN NUM NUM_U NAME STRING PROTO IO_ERROR ON_DISCONNECT
 %x IP_AND_PORT PORT META_DISK META_IDX
 %x LS LBRACE IGNORE_SECTION
@@ -90,7 +90,7 @@
   {NDELIM}		expect_error("one of 'global|resource'");
 }
 
-<RESOURCE,GLOBAL,IGNORE_SECTION,STARTUP,DISK,NET,SYNCER,HOST>{
+<RESOURCE,GLOBAL,IGNORE_SECTION,STARTUP,DISK,NET,SYNCER,HOST,HANDLERS>{
   {IGNORE}		update_lcnt();
   \}			yy_pop_state();
 }
@@ -209,13 +209,14 @@
   syncer		section(SYNCER);     return TK_SYNCER;
   disk			section(DISK);	     return TK_DISK_S;
   net			section(NET);	     return TK_NET;
+  handlers		section(HANDLERS);   return TK_HANDLERS;
 
   protocol		do_assign(PROTO);  CP; return TK_PROTOCOL;
-  incon-degr-cmd	do_assign(STRING); CP; return TK_INCON_DEGR_CMD;
   {NDELIM}		{
 			  expect_error(
 				"one of 'protocol|incon-degr-cmd|"
-				"startup|disk|net|syncer|on <HOSTNAME>'");
+				"startup|disk|net|syncer|on <HOSTNAME>'|"
+				"handlers");
 			}
 }
 
@@ -272,6 +273,18 @@
   {NDELIM}		expect_error("one of 'address|device|disk|meta-disk'");
 }
 
+<HANDLERS>{
+  pri-on-incon-degr	do_assign(STRING); CP; return TK_PRI_ON_INCON_DEGR;
+  pri-sees-sec-with-higher-gc	do_assign(STRING); CP; return TK_PRI_SEES_SEC_WITH_HIGHER_GC;
+  on-disconnect		do_assign(STRING); CP; return TK_ON_DISCONNECT;
+  {NDELIM}		{
+	  		  expect_error(
+				"one of 'pri-on-incon-degr|"
+				"pri-sees-sec-with-higher-gc|"
+				"on-disconnect");
+			}
+}
+
 <*>{
   \{			syntax_error("unexpected opening brace.");
   \n			syntax_error("unexpected end of line, maybe missing ';' ? ");

Modified: trunk/user/drbdsetup.c
===================================================================
--- trunk/user/drbdsetup.c	2004-11-22 14:31:35 UTC (rev 1648)
+++ trunk/user/drbdsetup.c	2004-11-22 22:35:08 UTC (rev 1649)
@@ -700,7 +700,6 @@
 	break;
       case EIO:
 	fprintf(stderr,"Local replica is inconsistent (--do-what-I-say ?)\n");
-	return 21;
       }
     return 20;
   }



More information about the drbd-cvs mailing list