[DRBD-cvs] r1596 - trunk/user

svn at svn.drbd.org svn at svn.drbd.org
Mon Oct 18 18:14:14 CEST 2004


Author: phil
Date: 2004-10-18 18:14:11 +0200 (Mon, 18 Oct 2004)
New Revision: 1596

Modified:
   trunk/user/drbdmeta.c
Log:
A bit of work on drbdmeta...


Modified: trunk/user/drbdmeta.c
===================================================================
--- trunk/user/drbdmeta.c	2004-10-15 21:12:21 UTC (rev 1595)
+++ trunk/user/drbdmeta.c	2004-10-18 16:14:11 UTC (rev 1596)
@@ -32,19 +32,28 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <glib.h>  // gint32, GINT64_FROM_BE()
+#include <linux/drbd.h>   // only use DRBD_MAGIC from here!
+#include <glib.h>         // gint32, GINT64_FROM_BE()
 #include "drbdtool_common.h"
 
 #define ALIGN(x,a) ( ((x) + (a)-1) &~ ((a)-1) )
 
 #if G_MAXLONG == 0x7FFFFFFF
 #define LN2_BPL 5
+#define hweight_long hweight32
+#define WW UL
 #elif G_MAXLONG == 0x7FFFFFFFFFFFFFFF
 #define LN2_BPL 6
+#define hweight_long hweight64
 #else
 #error "LN2 of BITS_PER_LONG unknown!"
 #endif
 
+#define MD_AL_OFFSET_07    8
+#define MD_AL_MAX_SIZE_07  64
+#define MD_BM_OFFSET_07    (MD_AL_OFFSET_07 + MD_AL_MAX_SIZE_07)
+#define DRBD_MD_MAGIC_07   (DRBD_MAGIC+3)
+
 char* progname = 0;
 
 enum MetaDataFlags {
@@ -75,6 +84,8 @@
 	unsigned long *bitmap;  // v07
 	int al_size;            // v07
 	unsigned int  *act_log; // v07
+
+	unsigned long bits_set; // additional info, set by fopts->read()
 };
 
 struct meta_data_on_disk_07 {
@@ -87,40 +98,50 @@
 	guint32 bm_offset;         // offset to the bitmap, from here
 };
 
-struct conf_06 {
+struct format_06 {
 	int fd;
 	int minor;
 };
 
-struct conf_07 {
+struct format_07 {
 	int fd;
 	char *device_name;
 	int index;
 };
 
+struct format_ops;
+
+struct format {
+	struct format_ops *ops;
+	union {
+		struct format_06 f06;
+		struct format_07 f07;
+	} d;
+};
+
 typedef void* conf_t;
 
-struct format {
+struct format_ops {
 	const char* name;
 	char** args;
 	int conf_size;
-	int (* parse)(conf_t, char **argv, int*);
-	int (* open) (conf_t);
-	int (* close)(conf_t);
-	int (* read) (conf_t, struct meta_data *);
-	int (* write)(conf_t, struct meta_data *);
+	int (* parse)(struct format *, char **argv, int argc, int*);
+	int (* open) (struct format *);
+	int (* close)(struct format *);
+	int (* read) (struct format *, struct meta_data *);
+	int (* write)(struct format *, struct meta_data *);
 };
 
-int v07_parse(conf_t config, char **argv, int *ai);
-int v07_open(conf_t config);
-int v07_close(conf_t config);
-int v07_read(conf_t config, struct meta_data *);
-int v07_write(conf_t config, struct meta_data *);
+int v07_parse(struct format * config, char **argv, int argc, int *ai);
+int v07_open(struct format * config);
+int v07_close(struct format * config);
+int v07_read(struct format * config, struct meta_data *);
+int v07_write(struct format * config, struct meta_data *);
 
-struct format formats[] = {
+struct format_ops formats[] = {
 	{ "v07",
 	  (char *[]) { "device","index",0 },
-	  sizeof(struct conf_07),
+	  sizeof(struct format_07),
 	  v07_parse,
 	  v07_open,
 	  v07_close,
@@ -129,6 +150,32 @@
 	}
 };
 
+
+static inline guint32 hweight32(guint32 w)
+{
+        guint32 res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
+        res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+        res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
+        res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
+        return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
+}
+
+static inline guint64 hweight64(guint64 w)
+{
+#if G_MAXLONG == 0x7FFFFFFF
+	return hweight32((unsigned int)(w >> 32)) +
+				hweight32((unsigned int)w);
+#else
+	guint64 res;
+	res = (w & 0x5555555555555555ul) + ((w >> 1) & 0x5555555555555555ul);
+	res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
+	res = (res & 0x0F0F0F0F0F0F0F0Ful) + ((res >> 4) & 0x0F0F0F0F0F0F0F0Ful);
+	res = (res & 0x00FF00FF00FF00FFul) + ((res >> 8) & 0x00FF00FF00FF00FFul);
+	res = (res & 0x0000FFFF0000FFFFul) + ((res >> 16) & 0x0000FFFF0000FFFFul);
+	return (res & 0x00000000FFFFFFFFul) + ((res >> 32) & 0x00000000FFFFFFFFul);
+#endif
+}
+
 /* capacity in units of 512 byte (AKA sectors)
  */
 int bm_words(unsigned long capacity)
@@ -143,11 +190,16 @@
 	return words;
 }
 
-int v07_parse(conf_t config, char **argv, int *ai)
+int v07_parse(struct format * config, char **argv, int argc, int *ai)
 {
-	struct conf_07* cfg = (struct conf_07*) config;
+	struct format_07* cfg = &config->d.f07;
 	char *e;
 
+	if(argc < 2) {
+		fprintf(stderr,"Too few arguments for format\n");
+		return 0;
+	}
+
 	cfg->device_name = strdup(argv[0]);
 	e = argv[1];
 	cfg->index = strtol(argv[1],&e,0);
@@ -161,32 +213,35 @@
 	return 1;
 }
 
-int v07_open(conf_t config)
+int v07_open(struct format * config)
 {
-	struct conf_07* cfg = (struct conf_07*) config;
+	struct format_07* cfg = &config->d.f07;
 	struct stat sb;
 
 	cfg->fd = open(cfg->device_name,O_RDWR);
 
-	if(!cfg->fd == -1) return 0;
+	if(cfg->fd == -1) {
+		PERROR("open() failed");
+		return 0;
+	}
 
 	if(fstat(cfg->fd, &sb)) {
 		PERROR("fstat() failed");
-		exit(20);
+		return 0;
 	}
 
 	if(!S_ISBLK(sb.st_mode)) {
 		fprintf(stderr, "'%s' is not a block device!\n", 
 			cfg->device_name);
-		exit(20);
+		return 0;
 	}
 
 	return 1;
 }
 
-int v07_close(conf_t config)
+int v07_close(struct format * config)
 {
-	struct conf_07* cfg = (struct conf_07*) config;
+	struct format_07* cfg = &config->d.f07;
 
 	return close(cfg->fd) == 0;
 }
@@ -238,9 +293,24 @@
 	return size64;
 }
 
-int v07_read(conf_t config, struct meta_data * m)
+unsigned long from_lel(unsigned long* buffer, int words)
 {
-	struct conf_07* cfg = (struct conf_07*) config;
+	int i;
+	unsigned long w;
+	unsigned long bits=0;
+
+	for (i=0;i<words;i++) {
+		w = GULONG_FROM_LE(buffer[i]);
+		bits += hweight_long(w);
+		buffer[i] = w;
+	}
+
+	return bits;
+}
+
+int v07_read(struct format * config, struct meta_data * m)
+{
+	struct format_07* cfg = &config->d.f07;
 	struct meta_data_on_disk_07 * buffer;
 	int rr,i,bmw;
 	guint64 offset;
@@ -256,45 +326,95 @@
 	
 	if(lseek64(cfg->fd,offset,SEEK_SET) == -1) {
 		PERROR("lseek() failed");
-		exit(20);
+		return 0;
 	}
 
 	rr = read(cfg->fd, buffer, sizeof(struct meta_data_on_disk_07));
 	if( rr != sizeof(struct meta_data_on_disk_07)) {
 		PERROR("read failed");
-		exit(20);
+		return 0;
 	}
     
+	if( GUINT32_FROM_BE(buffer->magic) != DRBD_MD_MAGIC_07 ) {
+		fprintf(stderr,"Magic number not found");
+		return 0;
+	}
+
+	if( GUINT32_FROM_BE(buffer->al_offset) != MD_AL_OFFSET_07 ) {
+		fprintf(stderr,"Magic number (al_offset) not found");
+		return 0;
+	}
+
+	if( GUINT32_FROM_BE(buffer->bm_offset) != MD_BM_OFFSET_07 ) {
+		fprintf(stderr,"Magic number (bm_offset) not found");
+		return 0;
+	}
+
 	for (i = Flags; i < GEN_CNT_SIZE; i++)
-		m->gc[i] = GINT32_FROM_BE(buffer->gc[Flags]);
+		m->gc[i] = GUINT32_FROM_BE(buffer->gc[Flags]);
 
-	m->la_size = GINT64_FROM_BE(buffer->la_size);
+	m->la_size = GUINT64_FROM_BE(buffer->la_size);
 	bmw = bm_words(m->la_size);
 
+	m->bitmap = malloc(sizeof(long) * bmw);
+	if( ! m->bitmap) {
+		PERROR("Can not allocate memory for bitmap.");
+		return 0;
+	}
+	m->bm_size = bmw*sizeof(long);
+
+	if(lseek64(cfg->fd,offset + 512 * MD_BM_OFFSET_07 ,SEEK_SET) == -1) {
+		PERROR("lseek() failed");
+		return 0;
+	}
+
+	rr = read(cfg->fd, m->bitmap, bmw*sizeof(long));
+	if( rr != bmw*sizeof(long) ) {
+		PERROR("read failed");
+		return 0;
+	}
+
+	m->bits_set = from_lel(m->bitmap,bmw);
+
 	return 1;
 }
 
-int v07_write(conf_t config, struct meta_data * m)
+int v07_write(struct format * config, struct meta_data * m)
 {
+	//struct format_07* cfg = &config->d.f07;
+
 	return 0;
 }
 
 struct meta_cmd {
 	const char* name;
 	const char* args;
-	int (* function)(struct format*, conf_t);
+	int (* function)(struct format *, char** argv, int argc );
 	int show_in_usage;
 };
 
-int meta_show_gc(struct format* fmt, conf_t fcfg)
+void format_op_failed(struct format * fcfg, char* op)
 {
+	fprintf(stderr,"%s_%s() failed\n",fcfg->ops->name,op);
+	exit(20);
+}
+
+#define F_OP_OR_EXIT(OP,args...) \
+({ if(! fcfg->ops-> OP(fcfg, ##args) ) format_op_failed(fcfg, #OP ); })
+
+int meta_show_gc(struct format * fcfg, char** argv, int argc )
+{
 	struct meta_data* md;
 	char ppb[10];
 
+	if(argc > 0) {
+		fprintf(stderr,"Ignoring additional arguments\n");
+	}
+
 	md = md_alloc();
 
-	fmt->open(fcfg);
-	fmt->read(fcfg,md);
+	F_OP_OR_EXIT(open);
+	F_OP_OR_EXIT(read,md);
 	printf(
 		"                                        WantFullSync |\n"
 		"                                  ConnectedInd |     |\n"
@@ -316,17 +436,17 @@
 		md->gc[Flags] & MDF_FullSync ? "1/y" : "0/n",
 		ppsize(ppb,md->la_size));
 
-	fmt->close(fcfg);
+	fcfg->ops->close(fcfg);
 	
 	md_free(md);
 
 	return 1;
 }
 
-int meta_create_md(struct format* fmt, conf_t fcfg) { return 0; }
-int meta_dump_md(struct format* fmt, conf_t fcfg) { return 0; }
-int meta_convert_md(struct format* fmt, conf_t fcfg) { return 0; }
-int meta_modify_gc(struct format* fmt, conf_t fcfg) { return 0; }
+int meta_create_md(struct format * fcfg, char** argv, int argc ) { return 0; }
+int meta_dump_md(struct format * fcfg, char** argv, int argc ) { return 0; }
+int meta_convert_md(struct format * fcfg, char** argv, int argc ) { return 0; }
+int meta_modify_gc(struct format * fcfg, char** argv, int argc ) { return 0; }
 
 struct meta_cmd cmds[] = {
 	{ "create-md",  0,                         meta_create_md,      1 },
@@ -377,12 +497,43 @@
 	}	
 }
 
+struct format* parse_format(char** argv, int argc, int* ai)
+{
+	struct format_ops* fmt = NULL;
+	struct format* fcfg;
+
+	int i;
+
+	if(argc < 1) {
+		fprintf(stderr,"Format identifier missing\n");
+		exit(20);
+	}
+
+	for (i = 0; i < ARRY_SIZE(formats); i++ ) {
+		if( !strcmp(formats[i].name,argv[0]) ) {
+			fmt = formats+i;
+			break;
+		}
+	}
+	if(fmt == NULL) {
+		fprintf(stderr,"Unknown format '%s'.\n",argv[0]);
+		exit(20);
+	}
+
+	(*ai)++;
+
+	fcfg = malloc(fmt->conf_size + sizeof(void*) );
+	fcfg->ops = fmt;
+	fmt->parse(fcfg,argv+1,argc-1,ai);
+
+	return fcfg;
+}
+
 int main(int argc, char** argv)
 {
+	struct meta_cmd* command = NULL;
+	struct format * fcfg;
 	int i,ai;
-	struct format* fmt = NULL;
-	struct meta_cmd* command = NULL;
-	conf_t fcfg;
 
 	if ( (progname = strrchr(argv[0],'/')) ) {
 		argv[0] = ++progname;
@@ -400,28 +551,15 @@
 		int fd2 = open(drbd_dev_name,O_RDWR);
 		// I want to avoid DRBD specific ioctls here...
 		if(fd2) {
-			fprintf(stderr,"Device '%s' is configured!",
+			fprintf(stderr,"Device '%s' is configured!\n",
 				drbd_dev_name);
 			exit(20);
 		}
 		close(fd2);
 	}
 
-	for (i = 0; i < ARRY_SIZE(formats); i++ ) {
-		if( !strcmp(formats[i].name,argv[ai]) ) {
-			fmt = formats+i;
-			break;
-		}
-	}
-	if(fmt == NULL) {
-		fprintf(stderr,"Unknown format '%s'.\n",argv[ai]);
-		exit(20);
-	}
-	ai++;
+	fcfg = parse_format(argv+ai, argc-ai, &ai);
 
-	fcfg = malloc(fmt->conf_size);
-	fmt->parse(fcfg,argv+ai,&ai);
-
 	for (i = 0; i < ARRY_SIZE(cmds); i++ ) {
 		if( !strcmp(cmds[i].name,argv[ai]) ) {
 			command = cmds+i;
@@ -434,7 +572,7 @@
 	}
 	ai++;
 
-	command->function(fmt,fcfg);
+	command->function(fcfg, argv+ai, argc-ai);
 
 	return 0;
 }



More information about the drbd-cvs mailing list