[Cluster-devel] cluster/gfs2/convert Makefile gfs2_convert.c

rpeterso at sourceware.org rpeterso at sourceware.org
Mon Jun 12 20:40:34 UTC 2006


CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2006-06-12 20:40:32

Modified files:
	gfs2/convert   : Makefile gfs2_convert.c 

Log message:
	Got rid of dependency on libgfs.  Every is now done with libgfs2
	functions.  Also did some cleanup and bug fixes.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/convert/Makefile.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/convert/gfs2_convert.c.diff?cvsroot=cluster&r1=1.2&r2=1.3

--- cluster/gfs2/convert/Makefile	2006/06/09 22:13:18	1.3
+++ cluster/gfs2/convert/Makefile	2006/06/12 20:40:32	1.4
@@ -11,11 +11,11 @@
 ###############################################################################
 
 top_srcdir=..
-
 include ${top_srcdir}/make/defines.mk
 
-INCLUDES=-I../../gfs/libgfs -I../../gfs/include -I../libgfs2 -I../config -I${KERNEL_SRC}/include/
-LIBS=-L../../gfs/libgfs -L../../gfs/libgfs/.libs -L../libgfs2
+INCLUDES=-I${top_srcdir}/include -I${top_srcdir}/config -I${top_srcdir}/libgfs2 -I/usr/include -I${KERNEL_SRC}/fs/gfs2/ -I${KERNEL_SRC}/include/
+
+LIBS=-L${top_srcdir}/libgfs2
 
 CFLAGS+=-D_FILE_OFFSET_BITS=64 -DHELPER_PROGRAM -DGFS2_RELEASE_NAME=\"2\" -Wall -g
 
@@ -28,7 +28,7 @@
 	$(CC) $(INCLUDES) $(LIBS) $(CFLAGS) -c -o gfs2_convert.o gfs2_convert.c
 
 gfs2_convert: gfs2_convert.o ../libgfs2/libgfs2.a
-	$(CC) $(INCLUDES) $(LIBS) $(CFLAGS) -o gfs2_convert gfs2_convert.o -lgfs2 -lgfs 
+	$(CC) $(INCLUDES) $(LIBS) $(CFLAGS) -o gfs2_convert gfs2_convert.o -lgfs2
 
 clean:
 	@rm -f *.o gfs2_convert
--- cluster/gfs2/convert/gfs2_convert.c	2006/06/06 14:37:47	1.2
+++ cluster/gfs2/convert/gfs2_convert.c	2006/06/12 20:40:32	1.3
@@ -15,14 +15,17 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <stdlib.h>
 #include <libgen.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdarg.h>
 #include <dirent.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
 
-#include "libgfs.h"
 #include "linux_endian.h"
 #include <linux/types.h>
 #include <linux/gfs2_ondisk.h>
@@ -30,19 +33,96 @@
 #include "copyright.cf"
 #include "ondisk.h"
 #include "libgfs2.h"
-#include "incore.h"
-
 #include "global.h"
 
-#define RGRP_STUFFED_BLKS(sb) (((sb)->sb_bsize - sizeof(struct gfs_rgrp)) * GFS_NBBY)
-#define RGRP_BITMAP_BLKS(sb) (((sb)->sb_bsize - sizeof(struct gfs_meta_header)) * GFS_NBBY)
+#define RGRP_STUFFED_BLKS(sb) (((sb)->sb_bsize - sizeof(struct gfs2_rgrp)) * GFS2_NBBY)
+#define RGRP_BITMAP_BLKS(sb) (((sb)->sb_bsize - sizeof(struct gfs2_meta_header)) * GFS2_NBBY)
+
+/* Define some gfs1 constants from gfs1's gfs_ondisk.h */
+#define GFS_METATYPE_NONE       (0)
+#define GFS_METATYPE_SB         (1)    /* Super-Block */
+#define GFS_METATYPE_RG         (2)    /* Resource Group Header */
+#define GFS_METATYPE_RB         (3)    /* Resource Group Block Alloc BitBlock */
+#define GFS_METATYPE_DI         (4)    /* "Disk" inode (dinode) */
+#define GFS_METATYPE_IN         (5)    /* Indirect dinode block list */
+#define GFS_METATYPE_LF         (6)    /* Leaf dinode block list */
+#define GFS_METATYPE_JD         (7)    /* Journal Data */
+#define GFS_METATYPE_LH         (8)    /* Log Header (gfs_log_header) */
+#define GFS_METATYPE_LD         (9)    /* Log Descriptor (gfs_log_descriptor) */
+#define GFS_METATYPE_EA         (10)   /* Extended Attribute */
+#define GFS_METATYPE_ED         (11)   /* Extended Attribute data */
+
+/* GFS1 Dinode types  */
+#define GFS_FILE_NON            (0)
+#define GFS_FILE_REG            (1)    /* regular file */
+#define GFS_FILE_DIR            (2)    /* directory */
+#define GFS_FILE_LNK            (5)    /* link */
+#define GFS_FILE_BLK            (7)    /* block device node */
+#define GFS_FILE_CHR            (8)    /* character device node */
+#define GFS_FILE_FIFO           (101)  /* fifo/pipe */
+#define GFS_FILE_SOCK           (102)  /* socket */
+
+#define GFS_FORMAT_SB           (100)  /* Super-Block */
+#define GFS_FORMAT_FS           (1309) /* Filesystem (all-encompassing) */
+#define GFS_FORMAT_MULTI        (1401) /* Multi-Host */
+
+struct gfs1_rgrp {
+	struct gfs2_meta_header rg_header; /* hasn't changed from gfs1 to 2 */
+	uint32_t rg_flags;
+	uint32_t rg_free;       /* Number (qty) of free data blocks */
+	/* Dinodes are USEDMETA, but are handled separately from other METAs */
+	uint32_t rg_useddi;     /* Number (qty) of dinodes (used or free) */
+	uint32_t rg_freedi;     /* Number (qty) of unused (free) dinodes */
+	struct gfs2_inum rg_freedi_list; /* hasn't changed from gfs1 to 2 */
+	/* These META statistics do not include dinodes (used or free) */
+	uint32_t rg_usedmeta;   /* Number (qty) of used metadata blocks */
+	uint32_t rg_freemeta;   /* Number (qty) of unused metadata blocks */
+	char rg_reserved[64];
+};
+
+struct gfs1_jindex {
+	uint64_t ji_addr;       /* starting block of the journal */
+	uint32_t ji_nsegment;   /* number (quantity) of segments in journal */
+	uint32_t ji_pad;
+
+	char ji_reserved[64];
+};
+
+struct gfs1_sb {
+	/*  Order is important; need to be able to read old superblocks
+		in order to support on-disk version upgrades */
+	struct gfs2_meta_header sb_header;
+
+	uint32_t sb_fs_format;         /* GFS_FORMAT_FS (on-disk version) */
+	uint32_t sb_multihost_format;  /* GFS_FORMAT_MULTI */
+	uint32_t sb_flags;             /* ?? */
+
+	uint32_t sb_bsize;             /* fundamental FS block size in bytes */
+	uint32_t sb_bsize_shift;       /* log2(sb_bsize) */
+	uint32_t sb_seg_size;          /* Journal segment size in FS blocks */
+
+	/* These special inodes do not appear in any on-disk directory. */
+	struct gfs2_inum sb_jindex_di;  /* journal index inode */
+	struct gfs2_inum sb_rindex_di;  /* resource group index inode */
+	struct gfs2_inum sb_root_di;    /* root directory inode */
+	
+	/* Default inter-node locking protocol (lock module) and namespace */
+	char sb_lockproto[GFS2_LOCKNAME_LEN]; /* lock protocol name */
+	char sb_locktable[GFS2_LOCKNAME_LEN]; /* unique name for this FS */
+	
+	/* More special inodes */
+	struct gfs2_inum sb_quota_di;   /* quota inode */
+	struct gfs2_inum sb_license_di; /* license inode */
+
+	char sb_reserved[96];
+};
 
 struct inode_block {
 	osi_list_t list;
 	uint64_t di_addr;
 };
 
-struct gfs_sbd sb;
+struct gfs1_sb  raw_gfs1_ondisk_sb;
 struct gfs2_sbd sb2;
 char device[256];
 struct inode_block dirs_to_fix;  /* linked list of directories to fix */
@@ -51,6 +131,7 @@
 uint64_t dirs_fixed;
 uint64_t dirents_fixed;
 char *prog_name = "gfs2_convert"; /* needed by libgfs2 */
+struct gfs1_jindex *sd_jindex = NULL;    /* gfs1 journal index in memory */
 
 /* ------------------------------------------------------------------------- */
 /* This function is for libgfs's sake.                                       */
@@ -77,12 +158,14 @@
 	int x, y;
 	struct gfs2_rindex *ri;
 	unsigned char state;
+	struct gfs2_buffer_head *bh;
 
 	ri = &rgd2->ri;
 	gfs2_compute_bitstructs(sdp, rgd2); /* mallocs bh as array */
 	for (blk = 0; blk < ri->ri_length; blk++) {
-		rgd2->bh[blk] = bget_generic(sdp, ri->ri_addr + blk, read_disk,
-									 read_disk);
+		bh = bget_generic(sdp, ri->ri_addr + blk, read_disk, read_disk);
+		if (!rgd2->bh[blk])
+			rgd2->bh[blk] = bh;
 		x = (blk) ? sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_rgrp);
 
 		for (; x < sdp->bsize; x++)
@@ -92,96 +175,39 @@
 				if (state == 0x02) /* unallocated metadata state invalid */
 					rgd2->bh[blk]->b_data[x] &= ~(0x02 << (GFS2_BIT_SIZE * y));
 			}
-		brelse(rgd2->bh[blk], updated);
 	}
 }/* convert_bitmaps */
 
 /* ------------------------------------------------------------------------- */
-/* superblock_cvt - Convert gfs1 superblock and the existing rgs to gfs2.    */
+/* convert_rgs - Convert gfs1 resource groups to gfs2.                       */
 /* Returns: 0 on success, -1 on failure                                      */
 /* ------------------------------------------------------------------------- */
-static int superblock_cvt(int disk_fd, const struct gfs_sbd *sb1,
-						  struct gfs2_sbd *sb2)
+static int convert_rgs(struct gfs2_sbd *sbp)
 {
-	int x;
-	struct gfs_rgrpd *rgd;
-	struct rgrp_list *rgd2;
+	struct rgrp_list *rgd;
 	osi_list_t *tmp;
 	struct gfs2_buffer_head *bh;
-
-	/* --------------------------------- */
-	/* convert the incore sb structure   */
-	/* --------------------------------- */
-	memset(sb2, 0, sizeof(sb2));
-	sb2->bsize = sb1->sd_sb.sb_bsize; /* block size */
-	sb2->md.journals = sb1->sd_journals; /* number of journals */
-	sb2->jsize = GFS2_DEFAULT_JSIZE;
-	sb2->rgsize = GFS2_DEFAULT_RGSIZE;
-	sb2->utsize = GFS2_DEFAULT_UTSIZE;
-	sb2->qcsize = GFS2_DEFAULT_QCSIZE;
-	sb2->time = time(NULL);
-	sb2->device_fd = disk_fd;
-	sb2->blks_total = 0;   /* total blocks         - total them up later */
-	sb2->blks_alloced = 0; /* blocks allocated     - total them up later */
-	sb2->dinodes_alloced = 0; /* dinodes allocated - total them up later */
-	osi_list_init(&sb2->rglist);
-	osi_list_init(&sb2->buf_list);
-	for (x = 0; x < BUF_HASH_SIZE; x++)
-		osi_list_init(&sb2->buf_hash[x]);
-	compute_constants(sb2);
-
-	/* --------------------------------- */
-	/* convert the ondisk sb structure   */
-	/* --------------------------------- */
-	sb2->sd_sb.sb_header.mh_magic = GFS2_MAGIC;
-	sb2->sd_sb.sb_fs_format = GFS2_FORMAT_FS;
-	sb2->sd_sb.sb_header.mh_type = GFS2_METATYPE_SB;
-	sb2->sd_sb.sb_header.mh_format = GFS2_FORMAT_SB;
-	sb2->sd_sb.sb_multihost_format = GFS2_FORMAT_MULTI;
-	sb2->sd_sb.sb_bsize = sb1->sd_sb.sb_bsize;
-	sb2->sd_sb.sb_bsize_shift = sb1->sd_sb.sb_bsize_shift;
-	strcpy(sb2->sd_sb.sb_lockproto, sb1->sd_sb.sb_lockproto);
-	strcpy(sb2->sd_sb.sb_locktable, sb1->sd_sb.sb_locktable);
+	struct gfs1_rgrp *rgd1;
 
 	/* --------------------------------- */
 	/* Now convert its rgs into gfs2 rgs */
 	/* --------------------------------- */
-	for (tmp = (osi_list_t *)sb1->sd_rglist.next;
-		 tmp != (osi_list_t *)&sb1->sd_rglist; tmp = tmp->next) {
-		rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
-		/* convert the gfs1 rgrp into a new gfs2 rgrp */
-		rgd2 = malloc(sizeof(struct rgrp_list));
-		if (!rgd2) {
-			log_crit("Error: unable to allocate memory for rg conversion.\n");
-			return -1;
-		}
-		memset(rgd2, 0, sizeof(struct rgrp_list));
-
-		rgd2->length = rgd->rd_ri.ri_data;
-		rgd2->rg.rg_header.mh_magic = GFS_MAGIC;
-		rgd2->rg.rg_header.mh_type = GFS_METATYPE_RG;
-		rgd2->rg.rg_header.mh_format = GFS_FORMAT_RG;
-		rgd2->rg.rg_flags = rgd->rd_rg.rg_flags;
-		rgd2->rg.rg_free = rgd->rd_rg.rg_free + rgd->rd_rg.rg_freemeta;
-		rgd2->rg.rg_dinodes = rgd->rd_rg.rg_useddi;
-
-		sb2->blks_total += rgd->rd_ri.ri_data;
-		sb2->blks_alloced += (rgd->rd_ri.ri_data - rgd2->rg.rg_free);
-		sb2->dinodes_alloced += rgd->rd_rg.rg_useddi;
-
-		rgd2->ri.ri_addr = rgd->rd_ri.ri_addr;
-		rgd2->ri.ri_length = rgd->rd_ri.ri_length;
-		rgd2->ri.ri_data0 = rgd->rd_ri.ri_data1;
-		rgd2->ri.ri_data = rgd->rd_ri.ri_data;
-		rgd2->ri.ri_bitbytes = rgd->rd_ri.ri_bitbytes;
-		/* commit the changes to a gfs2 buffer */
-		bh = bread(sb2, rgd2->ri.ri_addr); /* get a gfs2 buffer for the rg */
-		gfs2_rgrp_out(&rgd2->rg, bh->b_data);
+	osi_list_foreach(tmp, &sbp->rglist) {
+		rgd = osi_list_entry(tmp, struct rgrp_list, list);
+		rgd1 = (struct gfs1_rgrp *)&rgd->rg; /* recast as gfs1 structure */
+		/* rg_freemeta is a gfs1 structure, so libgfs2 doesn't know to */
+		/* convert from be to cpu. We must do it now. */
+		rgd->rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta);
+
+		sbp->blks_total += rgd->ri.ri_data;
+		sbp->blks_alloced += (rgd->ri.ri_data - rgd->rg.rg_free);
+		sbp->dinodes_alloced += rgd1->rg_useddi;
+
+		convert_bitmaps(sbp, rgd, TRUE);
+		/* Write the updated rgrp to the gfs2 buffer */
+		bh = bget(sbp, rgd->ri.ri_addr); /* get a gfs2 buffer for the rg */
+		gfs2_rgrp_out(&rgd->rg, rgd->bh[0]->b_data);
 		brelse(bh, updated); /* release the buffer */
-		/* Add the new gfs2 rg to our list: We'll output the index later. */
-		osi_list_add_prev((osi_list_t *)&rgd2->list,
-						  (osi_list_t *)&sb2->rglist);
-		convert_bitmaps(sb2, rgd2, TRUE);
 	}
 	return 0;
 }/* superblock_cvt */
@@ -195,8 +221,12 @@
 {
 	struct gfs2_inode *inode;
 	struct inode_block *fixdir;
+	int inode_was_gfs1;
 
 	inode = inode_get(sbp, bh);
+
+	inode_was_gfs1 = (inode->i_di.di_num.no_formal_ino ==
+					  inode->i_di.di_num.no_addr);
 	/* Fix the inode number: */
 	inode->i_di.di_num.no_formal_ino = sbp->md.next_inum;           ;
 	
@@ -207,7 +237,7 @@
 		/* Add this directory to the list of dirs to fix later. */
 		fixdir = malloc(sizeof(struct inode_block));
 		if (!fixdir) {
-			fprintf(stderr,"Error: out of memory.\n");
+			log_crit("Error: out of memory.\n");
 			return -1;
 		}
 		memset(fixdir, 0, sizeof(struct inode_block));
@@ -240,11 +270,23 @@
 	/* di_goal_meta has shifted locations and di_goal_data has     */
 	/* changed from 32-bits to 64-bits.  The following code        */
 	/* adjusts for the shift.                                      */
+	/*                                                             */
+	/* Note: It may sound absurd, but we need to check if this     */
+	/*       inode has already been converted to gfs2 or if it's   */
+	/*       still a gfs1 inode.  That's just in case there was a  */
+	/*       prior attempt to run gfs2_convert that never finished */
+	/*       (due to power out, ctrl-c, kill, segfault, whatever.) */
+	/*       If it is unconverted gfs1 we want to do a full        */
+	/*       conversion.  If it's a gfs2 inode from a prior run,   */
+	/*       we still need to renumber the inode, but here we      */
+	/*       don't want to shift the data around.                  */
 	/* ----------------------------------------------------------- */
-	inode->i_di.di_goal_meta = inode->i_di.di_goal_data;
-	inode->i_di.di_goal_data = 0; /* make sure the upper 32b are 0 */
-	inode->i_di.di_goal_data = inode->i_di.__pad[0];
-	inode->i_di.__pad[1] = 0;
+	if (inode_was_gfs1) {
+		inode->i_di.di_goal_meta = inode->i_di.di_goal_data;
+		inode->i_di.di_goal_data = 0; /* make sure the upper 32b are 0 */
+		inode->i_di.di_goal_data = inode->i_di.__pad[0];
+		inode->i_di.__pad[1] = 0;
+	}
 	
 	gfs2_dinode_out(&inode->i_di, bh->b_data);
 	sbp->md.next_inum++; /* update inode count */
@@ -268,7 +310,7 @@
 	int first;
 	int error = 0;
 
-	printf("Converting inodes.\n");
+	log_notice("Converting inodes.\n");
 	sbp->md.next_inum = 1; /* starting inode numbering */
 	gettimeofday(&tv, NULL);
 	seconds = tv.tv_sec;
@@ -289,7 +331,8 @@
 			/* doesn't think we hung.  (This may take a long time).       */
 			if (tv.tv_sec - seconds) {
 				seconds = tv.tv_sec;
-				printf("\r%" PRIu64" inodes converted.", sbp->md.next_inum);
+				log_notice("\r%" PRIu64" inodes converted.",
+						   sbp->md.next_inum);
 				fflush(stdout);
 			}
 			/* Get the next metadata block.  Break out if we reach the end. */
@@ -336,7 +379,7 @@
 		} /* while 1 */
 		gfs2_rgrp_relse(rgd, updated);
 	} /* for all rgs */
-	printf("\r%" PRIu64" inodes converted.", sbp->md.next_inum);
+	log_notice("\r%" PRIu64" inodes converted.", sbp->md.next_inum);
 	fflush(stdout);
 	return 0;
 }/* inode_renumber */
@@ -344,7 +387,7 @@
 /* ------------------------------------------------------------------------- */
 /* fetch_inum - fetch an inum entry from disk, given its block               */
 /* ------------------------------------------------------------------------- */
-int fetch_and_fix_inum(struct gfs2_sbd *sbp, uint64_t iblock,
+int fetch_inum(struct gfs2_sbd *sbp, uint64_t iblock,
 					   struct gfs2_inum *inum)
 {
 	struct gfs2_buffer_head *bh_fix;
@@ -356,7 +399,7 @@
 	inum->no_addr = fix_inode->i_di.di_num.no_addr;
 	brelse(bh_fix, updated);
 	return 0;
-}/* fetch_and_fix_inum */
+}/* fetch_inum */
 
 /* ------------------------------------------------------------------------- */
 /* process_dirent_info - fix one dirent (directory entry) buffer             */
@@ -375,64 +418,71 @@
 	
 	error = gfs2_dirent_first(dip, bh, &dent);
 	if (error != IS_LEAF && error != IS_DINODE) {
-		printf("Error retrieving directory.\n");
+		log_crit("Error retrieving directory.\n");
 		return -1;
 	}
 	/* Go through every dirent in the buffer and process it. */
 	/* Turns out you can't trust dir_entries is correct.     */
 	for (de = 0; ; de++) {
 		struct gfs2_inum inum;
+		int dent_was_gfs1;
 		
 		gettimeofday(&tv, NULL);
 		/* Do more warm fuzzy stuff for the customer. */
 		dirents_fixed++;
 		if (tv.tv_sec - seconds) {
 			seconds = tv.tv_sec;
-			printf("\r%" PRIu64 " directories, %" PRIu64 " dirents fixed.",
-				   dirs_fixed, dirents_fixed);
+			log_notice("\r%" PRIu64 " directories, %" PRIu64 " dirents fixed.",
+					   dirs_fixed, dirents_fixed);
 			fflush(stdout);
 		}
 		/* fix the dirent's inode number based on the inode */
 		gfs2_inum_in(&inum, (char *)&dent->de_inum);
+		dent_was_gfs1 = (dent->de_inum.no_addr == dent->de_inum.no_formal_ino);
 		if (inum.no_formal_ino) { /* if not a sentinel (placeholder) */
-			error = fetch_and_fix_inum(sbp, inum.no_addr, &inum);
+			error = fetch_inum(sbp, inum.no_addr, &inum);
 			if (error) {
-				printf("Error retrieving inode %" PRIx64 "\n", inum.no_addr);
+				log_crit("Error retrieving inode %" PRIx64 "\n", inum.no_addr);
 				break;
 			}
+			/* fix the dirent's inode number from the fetched inum. */
+			dent->de_inum.no_formal_ino = cpu_to_be64(inum.no_formal_ino);
 		}
 		/* Fix the dirent's filename hash: They are the same as gfs1 */
 		/* dent->de_hash = cpu_to_be32(gfs2_disk_hash((char *)(dent + 1), */
 		/*                             be16_to_cpu(dent->de_name_len))); */
 		/* Fix the dirent's file type.  Gfs1 used home-grown values.  */
 		/* Gfs2 uses standard values from include/linux/fs.h          */
-		switch be16_to_cpu(dent->de_type) {
-		case GFS_FILE_NON:
-			dent->de_type = cpu_to_be16(DT_UNKNOWN);
-			break;
-		case GFS_FILE_REG:    /* regular file */
-			dent->de_type = cpu_to_be16(DT_REG);
-			break;
-		case GFS_FILE_DIR:    /* directory */
-			dent->de_type = cpu_to_be16(DT_DIR);
-			break;
-		case GFS_FILE_LNK:    /* link */
-			dent->de_type = cpu_to_be16(DT_LNK);
-			break;
-		case GFS_FILE_BLK:    /* block device node */
-			dent->de_type = cpu_to_be16(DT_BLK);
-			break;
-		case GFS_FILE_CHR:    /* character device node */
-			dent->de_type = cpu_to_be16(DT_CHR);
-			break;
-		case GFS_FILE_FIFO:   /* fifo/pipe */
-			dent->de_type = cpu_to_be16(DT_FIFO);
-			break;
-		case GFS_FILE_SOCK:   /* socket */
-			dent->de_type = cpu_to_be16(DT_SOCK);
-			break;
+		/* Only do this if the dent was a true gfs1 dent, and not a   */
+		/* gfs2 dent converted from a previously aborted run.         */
+		if (dent_was_gfs1) {
+			switch be16_to_cpu(dent->de_type) {
+			case GFS_FILE_NON:
+				dent->de_type = cpu_to_be16(DT_UNKNOWN);
+				break;
+			case GFS_FILE_REG:    /* regular file */
+				dent->de_type = cpu_to_be16(DT_REG);
+				break;
+			case GFS_FILE_DIR:    /* directory */
+				dent->de_type = cpu_to_be16(DT_DIR);
+				break;
+			case GFS_FILE_LNK:    /* link */
+				dent->de_type = cpu_to_be16(DT_LNK);
+				break;
+			case GFS_FILE_BLK:    /* block device node */
+				dent->de_type = cpu_to_be16(DT_BLK);
+				break;
+			case GFS_FILE_CHR:    /* character device node */
+				dent->de_type = cpu_to_be16(DT_CHR);
+				break;
+			case GFS_FILE_FIFO:   /* fifo/pipe */
+				dent->de_type = cpu_to_be16(DT_FIFO);
+				break;
+			case GFS_FILE_SOCK:   /* socket */
+				dent->de_type = cpu_to_be16(DT_SOCK);
+				break;
+			}
 		}
-
 		error = gfs2_dirent_next(dip, bh, &dent);
 		if (error)
 			break;
@@ -480,7 +530,7 @@
 		/* read the leaf buffer in */
 		error = gfs2_get_leaf(dip, leaf_block, &bh_leaf);
 		if (error) {
-			printf("Error reading leaf %" PRIx64 "\n", leaf_block);
+			log_crit("Error reading leaf %" PRIx64 "\n", leaf_block);
 			break;
 		}
 		gfs2_leaf_in(&leaf, (char *)bh_leaf->b_data); /* buffer to structure */
@@ -506,7 +556,7 @@
 	dirents_fixed = 0;
 	gettimeofday(&tv, NULL);
 	seconds = tv.tv_sec;
-	printf("\nFixing file and directory information.\n");
+	log_notice("\nFixing file and directory information.\n");
 	offset = 0;
 	tmp = NULL;
 	/* for every directory in the list */
@@ -524,7 +574,7 @@
 		bh_dir = bread(sbp, dirblock);
 		dip = inode_get(sbp, bh_dir);
 		/* fix the directory: either exhash (leaves) or linear (stuffed) */
-		if (dip->i_di.di_flags & GFS_DIF_EXHASH) {
+		if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
 			if (fix_one_directory_exhash(sbp, dip)) {
 				log_crit("Error fixing exhash directory.\n");
 				brelse(bh_dir, updated);
@@ -549,44 +599,151 @@
 }/* fix_directory_info */
 
 /* ------------------------------------------------------------------------- */
-/* fill_super_block                                                          */
-/* Returns: 0 on success, -1 on failure                                      */
+/* Fetch gfs1 jindex structure from buffer                                   */
 /* ------------------------------------------------------------------------- */
-static int fill_super_block(int disk_fd, struct gfs_sbd *sdp)
+void gfs1_jindex_in(struct gfs1_jindex *jindex, char *buf)
 {
-	struct gfs_inode *ip = NULL;
+	struct gfs1_jindex *str = (struct gfs1_jindex *)buf;
 
-	log_info("Reading old filesystem information.\n");
-	/* get ri inode */
-	if(load_inode(disk_fd, sdp, sdp->sd_sb.sb_rindex_di.no_addr, &ip))
-		return -1;
-	sdp->sd_riinode = ip;
+	jindex->ji_addr = be64_to_cpu(str->ji_addr);
+	jindex->ji_nsegment = be32_to_cpu(str->ji_nsegment);
+	memset(jindex->ji_reserved, 0, 64);
+}
 
-	/* get ji inode */
-	if(load_inode(disk_fd, sdp, sdp->sd_sb.sb_jindex_di.no_addr, &ip)) {
-		stack;
+/* ------------------------------------------------------------------------- */
+/* read_gfs1_jiindex - read the gfs1 jindex file.                            */
+/* Returns: 0 on success, -1 on failure                                      */
+/* ------------------------------------------------------------------------- */
+int read_gfs1_jiindex(struct gfs2_sbd *sdp)
+{
+	struct gfs2_inode *ip = sdp->md.jiinode;
+	char buf[sizeof(struct gfs1_jindex)];
+	unsigned int j;
+	int error=0;
+
+	if(ip->i_di.di_size % sizeof(struct gfs1_jindex) != 0){
+		log_crit("The size reported in the journal index"
+				" inode is not a\n"
+				"\tmultiple of the size of a journal index.\n");
 		return -1;
 	}
-	sdp->sd_jiinode = ip;
-	/* get root dinode */
-	if(!load_inode(disk_fd, sdp, sdp->sd_sb.sb_root_di.no_addr, &ip)) {
-		if(!check_inode(ip))
-			sdp->sd_rooti = ip;
-		else
-			free(ip);
-	} else
-		log_warn("Unable to load root inode\n");
-	/* read in the journal index data */
-	if (ji_update(disk_fd, sdp)){
-		log_err("Unable to read in journal index inode.\n");
+	if(!(sd_jindex = (struct gfs1_jindex *)malloc(ip->i_di.di_size))) {
+		log_crit("Unable to allocate journal index\n");
 		return -1;
 	}
-	/* read in the resource group index data */
-	if(ri_update(disk_fd, sdp)){
-		log_err("Unable to fill in resource group information.\n");
+	if(!memset(sd_jindex, 0, ip->i_di.di_size)) {
+		log_crit("Unable to zero journal index\n");
 		return -1;
 	}
-	printf("%d rgs found.\n", sdp->sd_rgcount);
+	for (j = 0; ; j++) {
+		struct gfs1_jindex *journ;
+
+		error = gfs2_readi(ip, buf, j * sizeof(struct gfs1_jindex),
+						   sizeof(struct gfs1_jindex));
+		if(!error)
+			break;
+		if (error != sizeof(struct gfs1_jindex)){
+			log_crit("An error occurred while reading the"
+					" journal index file.\n");
+			goto fail;
+		}
+		journ = sd_jindex + j;
+		gfs1_jindex_in(journ, buf);
+	}
+	if(j * sizeof(struct gfs1_jindex) != ip->i_di.di_size){
+		log_crit("journal inode size invalid\n");
+		goto fail;
+	}
+	sdp->orig_journals = j;
+	return 0;
+
+ fail:
+	free(sd_jindex);
+	return -1;
+}
+
+/* ------------------------------------------------------------------------- */
+/* init - initialization code                                                */
+/* Returns: 0 on success, -1 on failure                                      */
+/* ------------------------------------------------------------------------- */
+static int init(struct gfs2_sbd *sbp)
+{
+	struct gfs2_buffer_head *bh;
+	int rgcount, i;
+	struct gfs2_inum inum;
+
+	memset(sbp, 0, sizeof(struct gfs2_sbd));
+	if ((sbp->device_fd = open(device, O_RDWR)) < 0) {
+		perror(device);
+		exit(-1);
+	}
+	/* --------------------------------- */
+	/* initialize the incore superblock  */
+	/* --------------------------------- */
+	sbp->sd_sb.sb_header.mh_magic = GFS2_MAGIC;
+	sbp->sd_sb.sb_header.mh_type = GFS2_METATYPE_SB;
+	sbp->sd_sb.sb_header.mh_format = GFS2_FORMAT_SB;
+
+	osi_list_init((osi_list_t *)&dirs_to_fix);
+	/* ---------------------------------------------- */
+	/* Initialize lists and read in the superblock.   */
+	/* ---------------------------------------------- */
+	sbp->jsize = GFS2_DEFAULT_JSIZE;
+	sbp->rgsize = GFS2_DEFAULT_RGSIZE;
+	sbp->utsize = GFS2_DEFAULT_UTSIZE;
+	sbp->qcsize = GFS2_DEFAULT_QCSIZE;
+	sbp->time = time(NULL);
+	sbp->blks_total = 0;   /* total blocks         - total them up later */
+	sbp->blks_alloced = 0; /* blocks allocated     - total them up later */
+	sbp->dinodes_alloced = 0; /* dinodes allocated - total them up later */
+	sbp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
+	sbp->bsize = sbp->sd_sb.sb_bsize;
+	osi_list_init(&sbp->rglist);
+	osi_list_init(&sbp->buf_list);
+	for(i = 0; i < BUF_HASH_SIZE; i++)
+		osi_list_init(&sbp->buf_hash[i]);
+	compute_constants(sbp);
+
+	bh = bread(sbp, GFS2_SB_ADDR >> sbp->sd_fsb2bb_shift);
+	memcpy(&raw_gfs1_ondisk_sb, (struct gfs1_sb *)bh->b_data,
+		   sizeof(struct gfs1_sb));
+	gfs2_sb_in(&sbp->sd_sb, bh->b_data);
+	brelse(bh, not_updated);
+	/* ---------------------------------------------- */
+	/* Make sure we're really gfs1                    */
+	/* ---------------------------------------------- */
+	if (sbp->sd_sb.sb_fs_format != GFS_FORMAT_FS ||
+		sbp->sd_sb.sb_header.mh_type != GFS_METATYPE_SB ||
+		sbp->sd_sb.sb_header.mh_format != GFS_FORMAT_SB ||
+		sbp->sd_sb.sb_multihost_format != GFS_FORMAT_MULTI) {
+		log_crit("Error: %s does not look like a gfs1 filesystem.\n",
+				device);
+		close(sbp->device_fd);
+		exit(-1);
+	}
+	/* get gfs1 rindex inode - gfs1's rindex inode ptr became __pad2 */
+	gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_rindex_di);
+	sbp->md.riinode = gfs2_load_inode(sbp, inum.no_addr);
+	/* get gfs1 jindex inode - gfs1's journal index inode ptr became master */
+	gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_jindex_di);
+	sbp->md.jiinode = gfs2_load_inode(sbp, inum.no_addr);
+	/* read in the journal index data */
+	read_gfs1_jiindex(sbp);
+	/* read in the resource group index data: */
+
+	/* We've got a slight dilemma here.  In gfs1, we used to have a meta */
+	/* header in front of the rgindex pages.  In gfs2, we don't.  That's */
+	/* apparently only for directories.  So we need to fake out libgfs2  */
+	/* so that it adjusts for the metaheader by faking out the inode to  */
+	/* look like a directory, temporarily.                               */
+	sbp->md.riinode->i_di.di_mode |= S_IFDIR; 
+	if (ri_update(sbp, &rgcount)){
+		log_crit("Unable to fill in resource group information.\n");
+		return -1;
+	}
+	inode_put(sbp->md.riinode, updated);
+	inode_put(sbp->md.jiinode, updated);
+	log_debug("%d rgs found.\n", rgcount);
 	return 0;
 }/* fill_super_block */
 
@@ -606,22 +763,39 @@
 }/* give_warning */
 
 /* ------------------------------------------------------------------------- */
+/* version  - print version information                                      */
+/* ------------------------------------------------------------------------- */
+void version(void)
+{
+	log_notice("gfs2_convert version %s (built %s %s)\n", GFS2_RELEASE_NAME,
+			   __DATE__, __TIME__);
+	log_notice("%s\n\n", REDHAT_COPYRIGHT);
+}
+
+/* ------------------------------------------------------------------------- */
 /* usage - print usage information                                           */
 /* ------------------------------------------------------------------------- */
 void usage(const char *name)
 {
 	give_warning();
-	printf("\nFormat is:\n");
-	printf("%s [--verbose] [-y] /dev/your/device\n\n", name);
+	printf("\nUsage:\n");
+	printf("%s [-hnqvVy] <device>\n\n", name);
+	printf("Flags:\n");
+	printf("\th - print this help message\n");
+	printf("\tn - assume 'no' to all questions\n");
+	printf("\tq - quieter output\n");
+	printf("\tv - more verbose output\n");
+	printf("\tV - print version information\n");
+	printf("\ty - assume 'yes' to all questions\n");
 }/* usage */
 
 /* ------------------------------------------------------------------------- */
 /* process_parameters                                                        */
 /* ------------------------------------------------------------------------- */
-void process_parameters(int argc, char **argv, struct options *opts)
+void process_parameters(int argc, char **argv, struct gfs2_options *opts)
 
 {
-	int i;
+	char c;
 
 	opts->yes = 0;
 	opts->no = 0;
@@ -630,27 +804,51 @@
 		exit(0);
 	}
 	memset(device, 0, sizeof(device));
-	for (i = 1; i < argc; i++) {
-		if (!strcmp(argv[i], "--verbose"))
+	while((c = getopt(argc, argv, "hnqvyV")) != -1) {
+		switch(c) {
+
+		case 'h':
+			usage(argv[0]);
+			exit(0);
+			break;
+		case 'n':
+			opts->no = 1;
+			break;
+		case 'q':
+			decrease_verbosity();
+			break;
+		case 'v':
 			increase_verbosity();
-		else if (!strcmp(argv[i], "-y"))
+			break;
+		case 'V':
+			exit(0);
+		case 'y':
 			opts->yes = 1;
-		else if (argv[i][0] == '-') {
+			break;
+		default:
+			fprintf(stderr,"Parameter not understood: %c\n", c);
 			usage(argv[0]);
-			fprintf(stderr, "Error: parameter %s not understood.\n", argv[i]);
-			exit(-1);
+			exit(0);
 		}
-		else
-			strcpy(device, argv[i]);
 	}
-	opts->device = device;
+	if(argc > optind) {
+		strcpy(device, argv[optind]);
+		opts->device = device;
+		if(!opts->device) {
+			fprintf(stderr, "Please use '-h' for usage.\n");
+			exit(1);
+		}
+	} else {
+		fprintf(stderr, "No device specified.  Use '-h' for usage.\n");
+		exit(1);
+	}
 } /* process_parameters */
 
 /* ------------------------------------------------------------------------- */
 /* rgrp_length - Calculate the length of a resource group                    */
 /* @size: The total size of the resource group                               */
 /* ------------------------------------------------------------------------- */
-uint64_t rgrp_length(uint64_t size, struct gfs_sbd *sdp)
+uint64_t rgrp_length(uint64_t size, struct gfs2_sbd *sdp)
 {
 	uint64_t bitbytes = RGRP_BITMAP_BLKS(&sdp->sd_sb) + 1;
 	uint64_t stuff = RGRP_STUFFED_BLKS(&sdp->sd_sb) + 1;
@@ -679,26 +877,24 @@
 /*                                                                           */
 /* Returns: 0 on success, -1 on failure                                      */
 /* ------------------------------------------------------------------------- */
-int journ_space_to_rg(int disk_fd, struct gfs_sbd *sdp, struct gfs2_sbd *sdp2)
+int journ_space_to_rg(struct gfs2_sbd *sdp)
 {
 	int error = 0;
 	int j, x;
-	struct gfs_jindex *jndx;
-	struct gfs_rgrpd *rgd, *rgdhigh;
-	struct rgrp_list *rgd2;
+	struct gfs1_jindex *jndx;
+	struct rgrp_list *rgd, *rgdhigh;
 	osi_list_t *tmp;
 	struct gfs2_meta_header mh;
 
 	mh.mh_magic = GFS2_MAGIC;
 	mh.mh_type = GFS2_METATYPE_RB;
 	mh.mh_format = GFS2_FORMAT_RB;
-	log_info("Converting journal space to rg space.\n");
+	log_notice("Converting journal space to rg space.\n");
 	/* Go through each journal, converting them one by one */
-	for (j = 0; j < sdp->sd_journals; j++) { /* for each journal */
+	for (j = 0; j < sdp->orig_journals; j++) { /* for each journal */
 		uint64_t size;
 
-		log_info("Processing journal %d.\n", j + 1);
-		jndx = &sdp->sd_jindex[j];
+		jndx = &sd_jindex[j];
 		/* go through all rg index entries, keeping track of the highest */
 		/* that's still in the first subdevice.                          */
 		/* Note: we really should go through all of the rgindex because  */
@@ -706,79 +902,55 @@
 		/* by jadd.  gfs_grow adds rgs out of order, so we can't count   */
 		/* on them being in ascending order.                             */
 		rgdhigh = NULL;
-		for (tmp = (osi_list_t *)sdp->sd_rglist.next;
-			 tmp != (osi_list_t *)&sdp->sd_rglist; tmp = tmp->next) {
-			rgd = osi_list_entry(tmp, struct gfs_rgrpd, rd_list);
-			if (rgd->rd_ri.ri_addr < jndx->ji_addr &&
+		osi_list_foreach(tmp, &sdp->rglist) {
+			rgd = osi_list_entry(tmp, struct rgrp_list, list);
+			if (rgd->ri.ri_addr < jndx->ji_addr &&
 				((rgdhigh == NULL) ||
-				 (rgd->rd_ri.ri_addr > rgdhigh->rd_ri.ri_addr)))
+				 (rgd->ri.ri_addr > rgdhigh->ri.ri_addr)))
 				rgdhigh = rgd;
 		} /* for each rg */
 		log_info("Addr %" PRIx64 " comes after rg at addr %" PRIx64 "\n",
-				 jndx->ji_addr, rgdhigh->rd_ri.ri_addr);
+				 jndx->ji_addr, rgdhigh->ri.ri_addr);
 		if (!rgdhigh) { /* if we somehow didn't find one. */
 			log_crit("Error: No suitable rg found for journal.\n");
 			return -1;
 		}
 		/* Allocate a new rgd entry which includes rg and ri. */
-		rgd = malloc(sizeof(struct gfs_rgrpd));
-		if (!rgd) {
-			log_crit("Error: out of memory creating new rg entry.\n");
-			return -1;
-		}
-		memset(rgd, 0, sizeof(struct gfs_rgrpd));
-		rgd->rd_sbd = sdp;
-		size = jndx->ji_nsegment * sdp->sd_sb.sb_seg_size;
-
-		rgd->rd_ri.ri_addr = jndx->ji_addr; /* new rg addr becomes ji addr */
-		rgd->rd_ri.ri_length = rgrp_length(size, sdp); /* aka bitblocks */
-		rgd->rd_ri.ri_data1 = jndx->ji_addr + rgd->rd_ri.ri_length;
-		rgd->rd_ri.ri_data = size - rgd->rd_ri.ri_length;
-
-		sdp2->blks_total += rgd->rd_ri.ri_data; /* For statfs file update */
-
-		/* Round down to nearest multiple of GFS_NBBY */
-		while (rgd->rd_ri.ri_data & 0x03)
-			rgd->rd_ri.ri_data--;
-		rgd->rd_ri.ri_bitbytes = rgd->rd_ri.ri_data / GFS_NBBY;
-
-		rgd->rd_rg.rg_header.mh_magic = GFS_MAGIC;
-		rgd->rd_rg.rg_header.mh_type = GFS_METATYPE_RG;
-		rgd->rd_rg.rg_header.mh_format = GFS_FORMAT_RG;
-		rgd->rd_rg.rg_free = rgd->rd_ri.ri_data;
-
 		/* convert the gfs1 rgrp into a new gfs2 rgrp */
-		rgd2 = malloc(sizeof(struct rgrp_list));
-		if (!rgd2) {
+		rgd = malloc(sizeof(struct rgrp_list));
+		if (!rgd) {
 			log_crit("Error: unable to allocate memory for rg conversion.\n");
 			return -1;
 		}
-		memset(rgd2, 0, sizeof(struct rgrp_list));
-		rgd2->rg.rg_header.mh_magic = GFS2_MAGIC;
-		rgd2->rg.rg_header.mh_type = GFS2_METATYPE_RG;
-		rgd2->rg.rg_header.mh_format = GFS2_FORMAT_RG;
-		rgd2->rg.rg_flags = 0;
-		rgd2->rg.rg_free = rgd->rd_ri.ri_data;
-		rgd2->rg.rg_dinodes = 0;
-
-		rgd2->ri.ri_addr = rgd->rd_ri.ri_addr;
-		rgd2->ri.ri_length = rgd->rd_ri.ri_length;
-		rgd2->ri.ri_data0 = rgd->rd_ri.ri_data1;
-		rgd2->ri.ri_data = rgd->rd_ri.ri_data;
-		rgd2->ri.ri_bitbytes = rgd->rd_ri.ri_bitbytes;
-		convert_bitmaps(sdp2, rgd2, FALSE); /* allocates rgd2->bh */
-		for (x = 0; x < rgd2->ri.ri_length; x++) {
+		memset(rgd, 0, sizeof(struct rgrp_list));
+		size = jndx->ji_nsegment * be32_to_cpu(raw_gfs1_ondisk_sb.sb_seg_size);
+		rgd->rg.rg_header.mh_magic = GFS2_MAGIC;
+		rgd->rg.rg_header.mh_type = GFS2_METATYPE_RG;
+		rgd->rg.rg_header.mh_format = GFS2_FORMAT_RG;
+		rgd->rg.rg_flags = 0;
+		rgd->rg.rg_dinodes = 0;
+
+		rgd->ri.ri_addr = jndx->ji_addr; /* new rg addr becomes ji addr */
+		rgd->ri.ri_length = rgrp_length(size, sdp); /* aka bitblocks */
+
+		rgd->ri.ri_data0 = jndx->ji_addr + rgd->ri.ri_length;
+		rgd->ri.ri_data = size - rgd->ri.ri_length;
+		sdp->blks_total += rgd->ri.ri_data; /* For statfs file update */
+		/* Round down to nearest multiple of GFS2_NBBY */
+		while (rgd->ri.ri_data & 0x03)
+			rgd->ri.ri_data--;
+		rgd->rg.rg_free = rgd->ri.ri_data;
+		rgd->ri.ri_bitbytes = rgd->ri.ri_data / GFS2_NBBY;
+		convert_bitmaps(sdp, rgd, FALSE); /* allocates rgd2->bh */
+		for (x = 0; x < rgd->ri.ri_length; x++) {
 			if (x)
-				gfs2_meta_header_out(&mh, rgd2->bh[x]->b_data);
+				gfs2_meta_header_out(&mh, rgd->bh[x]->b_data);
 			else
-				gfs2_rgrp_out(&rgd2->rg, rgd2->bh[x]->b_data);
+				gfs2_rgrp_out(&rgd->rg, rgd->bh[x]->b_data);
 		}
-		/* Add the new rg to our list: We'll output the rg index later. */
-		osi_list_add_prev((osi_list_t *)&rgd->rd_list,
-						  (osi_list_t *)&sdp->sd_rglist);
 		/* Add the new gfs2 rg to our list: We'll output the rg index later. */
-		osi_list_add_prev((osi_list_t *)&rgd2->list,
-						  (osi_list_t *)&sdp2->rglist);
+		osi_list_add_prev((osi_list_t *)&rgd->list,
+						  (osi_list_t *)&sdp->rglist);
 	} /* for each journal */
 	return error;
 }/* journ_space_to_rg */
@@ -797,8 +969,7 @@
 	if (count != sizeof(uint64_t))
 		die("update_inode_file\n");
 	
-	if (sdp->debug)
-		printf("\nNext Inum: %"PRIu64"\n", sdp->md.next_inum);
+	log_debug("\nNext Inum: %"PRIu64"\n", sdp->md.next_inum);
 }/* update_inode_file */
 
 /* ------------------------------------------------------------------------- */
@@ -819,83 +990,76 @@
 	count = gfs2_writei(ip, buf, 0, sizeof(struct gfs2_statfs_change));
 	if (count != sizeof(struct gfs2_statfs_change))
 		die("do_init (2)\n");
-	
-	if (sdp->debug) {
-		printf("\nStatfs:\n");
-		gfs2_statfs_change_print(&sc);
-	}
 }/* write_statfs_file */
 
 /* ------------------------------------------------------------------------- */
+/* remove_obsolete_gfs1 - remove obsolete gfs1 inodes.                       */
+/* ------------------------------------------------------------------------- */
+void remove_obsolete_gfs1(struct gfs2_sbd *sbp)
+{
+	struct gfs2_inum inum;
+
+	log_notice("Removing obsolete gfs1 structures.\n");
+	fflush(stdout);
+	/* Delete the old gfs1 Journal index: */
+	gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_jindex_di);
+	gfs2_freedi(sbp, inum.no_addr);
+
+	/* Delete the old gfs1 rgindex: */
+	gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_rindex_di);
+	gfs2_freedi(sbp, inum.no_addr);
+
+	/* Delete the old gfs1 Quota file: */
+	gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_quota_di);
+	gfs2_freedi(sbp, inum.no_addr);
+
+	/* Delete the old gfs1 License file: */
+	gfs2_inum_in(&inum, (char *)&raw_gfs1_ondisk_sb.sb_license_di);
+	gfs2_freedi(sbp, inum.no_addr);
+}
+
+/* ------------------------------------------------------------------------- */
 /* main - mainline code                                                      */
 /* ------------------------------------------------------------------------- */
 int main(int argc, char **argv)
-{	
-	int disk_fd;
+{
 	int error;
 	struct gfs2_buffer_head *bh;
-	struct options opts;
+	struct gfs2_options opts;
 
-	printf("gfs2_convert version %s (built %s %s)\n", GFS2_RELEASE_NAME,
-		   __DATE__, __TIME__);
-	printf("%s\n\n", REDHAT_COPYRIGHT);
+	version();
 	process_parameters(argc, argv, &opts);
-	memset(&sb, 0, sizeof(sb));
-	if ((disk_fd = open(device, O_RDWR)) < 0){
-		perror(device);
-		exit(-1);
-	}
-	osi_list_init((osi_list_t *)&dirs_to_fix);
-	/* ---------------------------------------------- */
-	/* Initialize lists and read in the superblock.   */
-	/* ---------------------------------------------- */
-	error = read_super_block(disk_fd, &sb);
-	if (error)
-		fprintf(stderr, "%s: Unable to read superblock.\n", device);
-	/* ---------------------------------------------- */
-	/* Make sure we're really gfs1                    */
-	/* ---------------------------------------------- */
-	if (sb.sd_sb.sb_fs_format != GFS_FORMAT_FS ||
-		sb.sd_sb.sb_header.mh_type != GFS_METATYPE_SB ||
-		sb.sd_sb.sb_header.mh_format != GFS_FORMAT_SB ||
-		sb.sd_sb.sb_multihost_format != GFS_FORMAT_MULTI) {
-		fprintf(stderr, "Error: %s does not look like a gfs1 filesystem.\n",
-				device);
-		close(disk_fd);
-		exit(-1);
-	}
+	error = init(&sb2);
+
 	/* ---------------------------------------------- */
 	/* Make them seal their fate.                     */
 	/* ---------------------------------------------- */
-	give_warning();
-	if (!query(&opts, "Convert %s from GFS1 to GFS2? (y/n)", device)) {
-		fprintf(stderr, "%s not converted.\n", device);
-		close(disk_fd);
-		exit(0);
-	}
-	printf("Initializing...");
 	if (!error) {
-		error = fill_super_block(disk_fd, &sb);
-		if (error)
-			fprintf(stderr, "%s: Unable to fill superblock.\n", device);
+		give_warning();
+		if (!query(&opts, "Convert %s from GFS1 to GFS2? (y/n)", device)) {
+			log_crit("%s not converted.\n", device);
+			close(sb2.device_fd);
+			exit(0);
+		}
 	}
 	/* ---------------------------------------------- */
 	/* Convert incore gfs1 sb to gfs2 sb              */
 	/* ---------------------------------------------- */
 	if (!error) {
-		printf("Converting superblock.\n");
-		error = superblock_cvt(disk_fd, &sb, &sb2);
+		log_notice("Converting resource groups.\n");
+		error = convert_rgs(&sb2);
 		if (error)
-			fprintf(stderr, "%s: Unable to convert superblock.\n", device);
+			log_crit("%s: Unable to convert resource groups.\n",
+					device);
 		bcommit(&sb2); /* write the buffers to disk */
 	}
 	/* ---------------------------------------------- */
 	/* Renumber the inodes consecutively.             */
 	/* ---------------------------------------------- */
 	if (!error) {
-		error = inode_renumber(&sb2, sb.sd_sb.sb_root_di.no_addr);
+		error = inode_renumber(&sb2, sb2.sd_sb.sb_root_dir.no_addr);
 		if (error)
-			fprintf(stderr, "\n%s: Error renumbering inodes.\n", device);
+			log_crit("\n%s: Error renumbering inodes.\n", device);
 		bcommit(&sb2); /* write the buffers to disk */
 	}
 	/* ---------------------------------------------- */
@@ -903,27 +1067,27 @@
 	/* ---------------------------------------------- */
 	if (!error) {
 		error = fix_directory_info(&sb2, (osi_list_t *)&dirs_to_fix);
-		printf("\r%" PRIu64 " directories, %" PRIu64 " dirents fixed.",
-			   dirs_fixed, dirents_fixed);
+		log_notice("\r%" PRIu64 " directories, %" PRIu64 " dirents fixed.",
+				   dirs_fixed, dirents_fixed);
 		fflush(stdout);
 		if (error)
-			fprintf(stderr, "\n%s: Error fixing directories.\n", device);
+			log_crit("\n%s: Error fixing directories.\n", device);
 	}
 	/* ---------------------------------------------- */
 	/* Convert journal space to rg space              */
 	/* ---------------------------------------------- */
 	if (!error) {
-		printf("\nConverting journals.\n");
-		error = journ_space_to_rg(disk_fd, &sb, &sb2);
+		log_notice("\nConverting journals.\n");
+		error = journ_space_to_rg(&sb2);
 		if (error)
-			fprintf(stderr, "%s: Error converting journal space.\n", device);
+			log_crit("%s: Error converting journal space.\n", device);
 		bcommit(&sb2); /* write the buffers to disk */
 	}
 	/* ---------------------------------------------- */
 	/* Create our system files and directories.       */
 	/* ---------------------------------------------- */
 	if (!error) {
-		printf("Building system structures.\n");
+		log_notice("Building system structures.\n");
 		/* Build the master subdirectory. */
 		build_master(&sb2); /* Does not do inode_put */
 		sb2.sd_sb.sb_master_dir = sb2.master_dir->i_di.di_num;
@@ -948,34 +1112,34 @@
 		inode_put(sb2.md.inum, updated);
 		inode_put(sb2.md.statfs, updated);
 
-		bh = bread(&sb2, sb2.sb_addr);
-		gfs2_sb_out(&sb2.sd_sb, bh->b_data);
-		brelse(bh, updated);
 		bcommit(&sb2); /* write the buffers to disk */
 
 		/* Now delete the now-obsolete gfs1 files: */
-		printf("Removing obsolete gfs1 structures.\n");
-		fflush(stdout);
-		/* Delete the Journal index: */
-		gfs2_freedi(&sb2, sb.sd_sb.sb_jindex_di.no_addr);
-		/* Delete the rgindex: */
-		gfs2_freedi(&sb2, sb.sd_sb.sb_rindex_di.no_addr);
-		/* Delete the Quota file: */
-		gfs2_freedi(&sb2, sb.sd_sb.sb_quota_di.no_addr);
-		/* Delete the License file: */
-		gfs2_freedi(&sb2, sb.sd_sb.sb_license_di.no_addr);
-		/* Now free all the rgrps */
+		remove_obsolete_gfs1(&sb2);
+		/* Now free all the in memory */
 		gfs2_rgrp_free(&sb2, updated);
-		printf("Committing changes to disk.\n");
+		log_notice("Committing changes to disk.\n");
 		fflush(stdout);
+		/* Set filesystem type in superblock to gfs2.  We do this at the */
+		/* end because if the tool is interrupted in the middle, we want */
+		/* it to not reject the partially converted fs as already done   */
+		/* when it's run a second time.                                  */
+		bh = bread(&sb2, sb2.sb_addr);
+		sb2.sd_sb.sb_fs_format = GFS2_FORMAT_FS;
+		sb2.sd_sb.sb_multihost_format = GFS2_FORMAT_MULTI;
+		gfs2_sb_out(&sb2.sd_sb, bh->b_data);
+		brelse(bh, updated);
+
 		bsync(&sb2); /* write the buffers to disk */
-		error = fsync(disk_fd);
+		error = fsync(sb2.device_fd);
 		if (error)
-			die("can't fsync device (%d): %s\n",
-				error, strerror(errno));
+			perror(device);
 		else
-			printf("%s: filesystem converted successfully to gfs2.\n", device);
+			log_notice("%s: filesystem converted successfully to gfs2.\n",
+					   device);
 	}
-	close(disk_fd);
+	close(sb2.device_fd);
+	if (sd_jindex)
+		free(sd_jindex);
 	exit(0);
 }




More information about the Cluster-devel mailing list