[Cluster-devel] [Patch 44/44] fsck.gfs2: Add ability to check gfs1 file systems

Steven Whitehouse swhiteho at redhat.com
Fri Aug 12 10:50:30 UTC 2011


Hi,

On Thu, 2011-08-11 at 17:19 -0400, Bob Peterson wrote:
> >From e6dd8021b94ad3a4b1dcf9764a2909b9a29bf953 Mon Sep 17 00:00:00 2001
> From: Bob Peterson <rpeterso at redhat.com>
> Date: Thu, 11 Aug 2011 14:51:08 -0500
> Subject: [PATCH 44/44] fsck.gfs2: Add ability to check gfs1 file systems
> 
> This patch gives fsck.gfs2 the ability to check GFS1 file systems.
> 
> rhbz#675723
> ---
>  gfs2/fsck/fs_recovery.c   |   37 ++++--
>  gfs2/fsck/fsck.h          |   13 ++
>  gfs2/fsck/initialize.c    |  300 +++++++++++++++++++++++++++++++++-----------
>  gfs2/fsck/lost_n_found.c  |  118 +++++++++++++-----
>  gfs2/fsck/main.c          |   14 ++-
>  gfs2/fsck/metawalk.c      |   88 ++++++++++----
>  gfs2/fsck/pass1.c         |  197 ++++++++++++++++++++++-------
>  gfs2/fsck/pass1b.c        |    5 +-
>  gfs2/fsck/pass2.c         |   41 ++++---
>  gfs2/fsck/pass3.c         |   41 ++++++-
>  gfs2/fsck/pass4.c         |    7 +
>  gfs2/fsck/pass5.c         |   87 ++++++++++++-
>  gfs2/fsck/rgrepair.c      |   25 +++-
>  gfs2/fsck/util.h          |   77 +++++++-----
>  gfs2/libgfs2/libgfs2.h    |    3 +
>  gfs2/libgfs2/structures.c |   29 +++--
>  16 files changed, 817 insertions(+), 265 deletions(-)
> 
> diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
> index c6901d0..67aa441 100644
> --- a/gfs2/fsck/fs_recovery.c
> +++ b/gfs2/fsck/fs_recovery.c
> @@ -631,7 +631,9 @@ int ji_update(struct gfs2_sbd *sdp)
>  {
>  	struct gfs2_inode *jip, *ip = sdp->md.jiinode;
>  	char journal_name[JOURNAL_NAME_SIZE];
> -	int i;
> +	int i, error;
> +	char buf[sizeof(struct gfs_jindex)];
> +	struct gfs_jindex ji;
>  
>  	if (!ip) {
>  		log_crit("Journal index inode not found.\n");
> @@ -642,24 +644,41 @@ int ji_update(struct gfs2_sbd *sdp)
>  	   plus two for "." and "..".  So we subtract the 2 and divide by 3.
>  	   If per_node is missing or damaged, we have to trust jindex has
>  	   the correct number of entries. */
> -	if (sdp->md.pinode) /* if per_node was read in properly */
> +	if (sdp->gfs1)
> +		sdp->md.journals = ip->i_di.di_size / sizeof(struct gfs_jindex);
> +	else if (sdp->md.pinode) /* if per_node was read in properly */
>  		sdp->md.journals = (sdp->md.pinode->i_di.di_entries - 2) / 3;
>  	else
>  		sdp->md.journals = ip->i_di.di_entries - 2;
>  
>  	if (!(sdp->md.journal = calloc(sdp->md.journals,
> -				      sizeof(struct gfs2_inode *)))) {
> +				       sizeof(struct gfs2_inode *)))) {
>  		log_err("Unable to allocate journal index\n");
>  		return -1;
>  	}
>  	memset(journal_name, 0, sizeof(*journal_name));
>  	for (i = 0; i < sdp->md.journals; i++) {
> -		/* FIXME check snprintf return code */
> -		snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
> -		gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
> -			     &jip);
> -		sdp->md.journal[i] = jip;
> +		if (sdp->gfs1) {
> +			error = gfs2_readi(ip,
> +					   buf, i * sizeof(struct gfs_jindex),
> +					   sizeof(struct gfs_jindex));
> +			if (!error)
> +				break;
> +			if (error != sizeof(struct gfs_jindex)){
> +				log_err("An error occurred while reading the"
> +					" journal index file.\n");
> +				return -1;
> +			}
> +			gfs_jindex_in(&ji, buf);
> +			sdp->md.journal[i] = inode_read(sdp, ji.ji_addr);
> +		} else {
> +			/* FIXME check snprintf return code */
> +			snprintf(journal_name, JOURNAL_NAME_SIZE,
> +				 "journal%u", i);
> +			gfs2_lookupi(sdp->md.jiinode, journal_name,
> +				     strlen(journal_name), &jip);
> +			sdp->md.journal[i] = jip;
> +		}
>  	}
>  	return 0;
> -
>  }
> diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
> index 0fed06b..260c42c 100644
> --- a/gfs2/fsck/fsck.h
> +++ b/gfs2/fsck/fsck.h
> @@ -113,6 +113,7 @@ extern void gfs2_dup_free(void);
>  extern int fsck_query(const char *format, ...)
>  	__attribute__((format(printf,1,2)));
>  extern struct dir_info *dirtree_find(uint64_t block);
> +extern void dup_listent_delete(struct inode_with_dups *id);
>  extern void dup_delete(struct duptree *b);
>  extern void dirtree_delete(struct dir_info *b);
>  
> @@ -135,4 +136,16 @@ extern struct osi_root inodetree;
>  extern int dups_found; /* How many duplicate references have we found? */
>  extern int dups_found_first; /* How many duplicates have we found the original
>  				reference for? */
> +extern struct gfs_sb *sbd1;
> +
> +static inline int is_dir(struct gfs2_dinode *dinode, int gfs1)
> +{
> +	if (gfs1 && is_gfs_dir(dinode))
> +		return 1;
> +	if (S_ISDIR(dinode->di_mode))
> +		return 1;
> +
> +	return 0;
> +}
> +
>  #endif /* _FSCK_H */
> diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
> index 2d667fc..033ede0 100644
> --- a/gfs2/fsck/initialize.c
> +++ b/gfs2/fsck/initialize.c
> @@ -194,12 +194,14 @@ static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
>  				 int *fixit, int *this_rg_fixed,
>  				 int *this_rg_bad)
>  {
> -	uint32_t rg_free, rg_reclaimed;
> +	uint32_t rg_free, rg_reclaimed, rg_unlinked;
>  	int rgb, x, y, off, bytes_to_check, total_bytes_to_check, asked = 0;
>  	unsigned int state;
> +	struct gfs_rgrp *gfs1rg = (struct gfs_rgrp *)&rgd->rg;
>  
> -	rg_free = rg_reclaimed = 0;
> +	rg_free = rg_reclaimed = rg_unlinked = 0;
>  	total_bytes_to_check = rgd->ri.ri_bitbytes;
> +
>  	*this_rg_fixed = *this_rg_bad = 0;
>  
>  	for (rgb = 0; rgb < rgd->ri.ri_length; rgb++){
> @@ -247,8 +249,10 @@ static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
>  					if (query("%s", msg))
>  						*fixit = 1;
>  				}
> -				if (!(*fixit))
> +				if (!(*fixit)) {
> +					rg_unlinked++;
>  					continue;
> +				}
>  				*byte &= ~(GFS2_BIT_MASK <<
>  					   (GFS2_BIT_SIZE * y));
>  				bmodified(rgd->bh[rgb]);
> @@ -270,7 +274,29 @@ static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
>  				 rg_reclaimed);
>  		if (query( _("Fix the rgrp free blocks count? (y/n)"))) {
>  			rgd->rg.rg_free = rg_free;
> -			gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
> +			if (sdp->gfs1)
> +				gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg,
> +					     rgd->bh[0]);
> +			else
> +				gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
> +			*this_rg_fixed = 1;
> +			log_err( _("The rgrp was fixed.\n"));
> +		} else
> +			log_err( _("The rgrp was not fixed.\n"));
> +	}
> +	if (sdp->gfs1 && gfs1rg->rg_freemeta != rg_unlinked) {
> +		*this_rg_bad = 1;
> +		log_err( _("Error: resource group %lld (0x%llx): "
> +			   "free meta  (%d) does not match bitmap (%d)\n"),
> +			 (unsigned long long)rgd->ri.ri_addr,
> +			 (unsigned long long)rgd->ri.ri_addr,
> +			 gfs1rg->rg_freemeta, rg_unlinked);
> +		if (rg_reclaimed)
> +			log_err( _("(%d blocks were reclaimed)\n"),
> +				 rg_reclaimed);
> +		if (query( _("Fix the rgrp free meta blocks count? (y/n)"))) {
> +			gfs1rg->rg_freemeta = rg_unlinked;
> +			gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg, rgd->bh[0]);
>  			*this_rg_fixed = 1;
>  			log_err( _("The rgrp was fixed.\n"));
>  		} else
> @@ -539,7 +565,10 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
>  	/* Get root dinode */
>  	sdp->md.rooti = inode_read(sdp, sdp->sd_sb.sb_root_dir.no_addr);
>  
> -	gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
> +	if (sdp->gfs1)
> +		sdp->md.riinode = inode_read(sdp, sbd1->sb_rindex_di.no_addr);
> +	else
> +		gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
>  	if (!sdp->md.riinode) {
>  		if (query( _("The gfs2 system rindex inode is missing. "
>  			     "Okay to rebuild it? (y/n) "))) {
> @@ -558,7 +587,10 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
>  
>  	/* rgrepair requires the journals be read in in order to distinguish
>  	   "real" rgrps from rgrps that are just copies left in journals. */
> -	gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
> +	if (sdp->gfs1)
> +		sdp->md.jiinode = inode_read(sdp, sbd1->sb_jindex_di.no_addr);
> +	else
> +		gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
>  	if (!sdp->md.jiinode) {
>  		if (query( _("The gfs2 system jindex inode is missing. "
>  			     "Okay to rebuild it? (y/n) "))) {
> @@ -616,38 +648,60 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
>  	/*******************************************************************
>  	 *****************  Initialize more system inodes  *****************
>  	 *******************************************************************/
> -	/* Look for "inum" entry in master dinode */
> -	gfs2_lookupi(sdp->master_dir, "inum", 4, &sdp->md.inum);
> -	if (!sdp->md.inum) {
> -		if (query( _("The gfs2 system inum inode is missing. "
> -			     "Okay to rebuild it? (y/n) "))) {
> +	if (!sdp->gfs1) {
> +		/* Look for "inum" entry in master dinode */
> +		gfs2_lookupi(sdp->master_dir, "inum", 4, &sdp->md.inum);
> +		if (!sdp->md.inum) {
> +			if (!query( _("The gfs2 system inum inode is missing. "
> +				      "Okay to rebuild it? (y/n) "))) {
> +				log_err( _("fsck.gfs2 cannot continue without "
> +					   "a valid inum file; aborting.\n"));
> +				goto fail;
> +			}
>  			err = build_inum(sdp);
>  			if (err) {
>  				log_crit(_("Error rebuilding inum inode: %s\n"),
> -				         strerror(err));
> +					 strerror(err));
>  				exit(-1);
>  			}
> +			gfs2_lookupi(sdp->master_dir, "inum", 4,
> +				     &sdp->md.inum);
> +			if (!sdp->md.inum) {
> +				log_crit("System inum inode was not rebuilt.  "
> +					 "Aborting.\n");
> +				goto fail;
> +			}
>  		}
> +		/* Read inum entry into buffer */
> +		gfs2_readi(sdp->md.inum, &inumbuf, 0,
> +			   sdp->md.inum->i_di.di_size);
> +		/* call gfs2_inum_range_in() to retrieve range */
> +		sdp->md.next_inum = be64_to_cpu(inumbuf);
>  	}
> -	/* Read inum entry into buffer */
> -	gfs2_readi(sdp->md.inum, &inumbuf, 0, sdp->md.inum->i_di.di_size);
> -	/* call gfs2_inum_range_in() to retrieve range */
> -	sdp->md.next_inum = be64_to_cpu(inumbuf);
>  
> -	gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
> -	if (!sdp->md.statfs) {
> -		if (query( _("The gfs2 system statfs inode is missing. "
> -			     "Okay to rebuild it? (y/n) "))) {
> -			err = build_statfs(sdp);
> -			if (err) {
> -				log_crit(_("Error rebuilding statfs inode: %s\n"),
> -				         strerror(err));
> -				exit(-1);
> -			}
> -		} else {
> -			log_err( _("fsck.gfs2 cannot continue without a "
> -				   "valid statfs file; aborting.\n"));
> -			return FSCK_ERROR;
> +	if (sdp->gfs1)
> +		sdp->md.statfs = inode_read(sdp, sbd1->sb_license_di.no_addr);
> +	else
> +		gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
> +	if (!sdp->gfs1 && !sdp->md.statfs) {
> +		if (!query( _("The gfs2 system statfs inode is missing. "
> +			      "Okay to rebuild it? (y/n) "))) {
> +			log_err( _("fsck.gfs2 cannot continue without a valid "
> +				   "statfs file; aborting.\n"));
> +			goto fail;
> +		}
> +		err = build_statfs(sdp);
> +		if (err) {
> +			log_crit(_("Error rebuilding statfs inode: %s\n"),
> +				 strerror(err));
> +			exit(-1);
> +		}
> +		gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
> +		if (!sdp->md.statfs) {
> +			log_err( _("Rebuild of statfs system file failed."));
> +			log_err( _("fsck.gfs2 cannot continue without "
> +				   "a valid statfs file; aborting.\n"));
> +			goto fail;
>  		}
>  	}
>  	buf = malloc(sdp->md.statfs->i_di.di_size);
> @@ -657,22 +711,36 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
>  	gfs2_statfs_change_in(&sc, buf);
>  	free(buf);
>  
> -	gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
> -	if (!sdp->md.qinode) {
> -		if (query( _("The gfs2 system quota inode is missing. "
> -			     "Okay to rebuild it? (y/n) "))) {
> -			err = build_quota(sdp);
> -			if (err) {
> -				log_crit(_("Error rebuilding quota inode: %s\n"),
> -				         strerror(err));
> -				exit(-1);
> -			}
> +	if (sdp->gfs1)
> +		sdp->md.qinode = inode_read(sdp, sbd1->sb_quota_di.no_addr);
> +	else
> +		gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
> +	if (!sdp->gfs1 && !sdp->md.qinode) {
> +		if (!query( _("The gfs2 system quota inode is missing. "
> +			      "Okay to rebuild it? (y/n) "))) {
> +			log_crit("System quota inode was not "
> +				 "rebuilt.  Aborting.\n");
> +			goto fail;
> +		}
> +		err = build_quota(sdp);
> +		if (err) {
> +			log_crit(_("Error rebuilding quota inode: %s\n"),
> +				 strerror(err));
> +			exit(-1);
> +		}
> +		gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
> +		if (!sdp->md.qinode) {
> +			log_crit("Unable to rebuild system quota file "
> +				 "inode.  Aborting.\n");
> +			goto fail;
>  		}
>  	}
>  
>  	/* Try to lookup the per_node inode.  If it was missing, it is now
>  	   safe to rebuild it. */
> -	lookup_per_node(sdp, 1);
> +	if (!sdp->gfs1)
> +		lookup_per_node(sdp, 1);
> +
>  	/*******************************************************************
>  	 *******  Now, set boundary fields in the super block  *************
>  	 *******************************************************************/
> @@ -785,13 +853,15 @@ static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
>  		return;
>  	}
>  	ip = inode_read(sdp, di->di_num.no_addr);
> -	if (di->di_num.no_formal_ino == 3) {
> +	if ((!sdp->gfs1 && di->di_num.no_formal_ino == 3) ||
> +	    (sdp->gfs1 && (di->di_flags & GFS2_DIF_JDATA) &&
> +	     (di->di_size % sizeof(struct gfs_jindex) == 0))) {
>  		if (fix_md.jiinode || is_journal_copy(ip, bh))
>  			return;
>  		log_warn(_("Found system jindex file at: 0x%llx\n"),
>  			 di->di_num.no_addr);
>  		fix_md.jiinode = ip;
> -	} else if (S_ISDIR(di->di_mode)) {
> +	} else if (!sdp->gfs1 && is_dir(di, sdp->gfs1)) {
>  		/* Check for a jindex dir entry. Only one system dir has a
>  		   jindex: master */
>  		gfs2_lookupi(ip, "jindex", 6, &child_ip);
> @@ -827,7 +897,7 @@ static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
>  		log_debug(_("Unknown system directory at block 0x%llx\n"),
>  			  di->di_num.no_addr);
>  		inode_put(&ip);
> -	} else if (di->di_size == 8) {
> +	} else if (!sdp->gfs1 && di->di_size == 8) {
>  		if (fix_md.inum || is_journal_copy(ip, bh))
>  			return;
>  		fix_md.inum = ip;
> @@ -869,7 +939,7 @@ static void peruse_user_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
>  
>  	if (sdp->sd_sb.sb_root_dir.no_addr) /* if we know the root dinode */
>  		return;             /* we don't need to find the root */
> -	if (!S_ISDIR(di->di_mode))  /* if this isn't a directory */
> +	if (!is_dir(di, sdp->gfs1))  /* if this isn't a directory */
>  		return;             /* it can't lead us to the root anyway */
>  
>  	if (di->di_num.no_formal_ino == 1) {
> @@ -1004,7 +1074,6 @@ static int peruse_metadata(struct gfs2_sbd *sdp, uint64_t startblock)
>  	uint64_t blk, max_rg_size;
>  	struct gfs2_buffer_head *bh;
>  	struct gfs2_dinode di;
> -	int found_gfs2_dinodes = 0, possible_gfs1_dinodes = 0;
>  
>  	max_rg_size = 2147483648ull / sdp->bsize;
>  	/* Max RG size is 2GB. 2G / bsize. */
> @@ -1015,18 +1084,6 @@ static int peruse_metadata(struct gfs2_sbd *sdp, uint64_t startblock)
>  			continue;
>  		}
>  		gfs2_dinode_in(&di, bh);
> -		if (!found_gfs2_dinodes &&
> -		    di.di_num.no_addr == di.di_num.no_formal_ino) {
> -			possible_gfs1_dinodes++;
> -			if (possible_gfs1_dinodes > 5) {
> -				log_err(_("Found several gfs (version 1) "
> -					  "dinodes; aborting.\n"));
> -				brelse(bh);
> -				return -1;
> -			}
> -		} else {
> -			found_gfs2_dinodes++;
> -		}
>  		if (di.di_flags & GFS2_DIF_SYSTEM)
>  			peruse_system_dinode(sdp, &di, bh);
>  		else
> @@ -1177,19 +1234,109 @@ static int fill_super_block(struct gfs2_sbd *sdp)
>  		log_crit(_("Bad constants (1)\n"));
>  		exit(-1);
>  	}
> -	if (read_sb(sdp, 0) < 0) {
> -		/* First, check for a gfs1 (not gfs2) file system */
> -		if (sdp->sd_sb.sb_header.mh_magic == GFS2_MAGIC &&
> -		    sdp->sd_sb.sb_header.mh_type == GFS2_METATYPE_SB)
> -			return -1; /* This is gfs1, don't try to repair */
> -		/* It's not a "sane" gfs1 fs so try to repair it */
> +	sdp->gfs1 = read_sb(sdp, 1);
> +	if (sdp->gfs1 < 0) {
>  		if (sb_repair(sdp) != 0)
>  			return -1; /* unrepairable, so exit */
>  		/* Now that we've tried to repair it, re-read it. */
> -		if (read_sb(sdp, 0) < 0)
> +		sdp->gfs1 = read_sb(sdp, 1);
> +		if (sdp->gfs1 < 0)
>  			return -1;
>  	}
> +	if (sdp->gfs1)
> +		sbd1 = (struct gfs_sb *)&sdp->sd_sb;
> +	return 0;
> +}
> +
> +static void gfs_log_header_out(struct gfs_log_header *head, char *buf)
> +{
> +        struct gfs_log_header *str = (struct gfs_log_header *) buf;
> +
> +	str->lh_header.mh_magic = cpu_to_be32(head->lh_header.mh_magic);
> +	str->lh_header.mh_type = cpu_to_be32(head->lh_header.mh_type);
> +	str->lh_header.mh_format = cpu_to_be32(head->lh_header.mh_format);
> +	str->lh_header.__pad0 = cpu_to_be32(head->lh_header.__pad0);
> +
> +	str->lh_flags = cpu_to_be32(head->lh_flags);
> +	str->lh_pad = cpu_to_be32(head->lh_pad);
> +	str->lh_first = cpu_to_be64(head->lh_first);
> +	str->lh_sequence = cpu_to_be64(head->lh_sequence);
> +	str->lh_tail = cpu_to_be64(head->lh_tail);
> +	str->lh_last_dump = cpu_to_be64(head->lh_last_dump);
> +}
> +
> +/*
> + * reconstruct_single_journal - write a fresh GFS1 journal
> + * @sdp: superblock
> + * @jnum: journal number
> + *
> + * This function will write a fresh journal over the top of
> + * the previous journal.  All journal information is lost.  This
> + * process is basically stolen from write_journals() in the mkfs code.
> + *
> + * Returns: -1 on error, 0 otherwise
> + */
> +static int reconstruct_single_journal(struct gfs2_sbd *sdp, int jnum,
> +				      uint32_t ji_nsegment)
> +{
> +	struct gfs_log_header lh;
> +	uint32_t seg, sequence;
> +	struct gfs2_buffer_head *bh;
> +
> +	srandom(time(NULL));
> +	sequence = ji_nsegment / (RAND_MAX + 1.0) * random();
> +
> +	log_info("Clearing journal %d\n", jnum);
> +
> +	for (seg = 0; seg < ji_nsegment; seg++){
> +		bh = bget(sdp, lh.lh_first * sdp->bsize);
> +		memset(bh->b_data, 0, sdp->bsize);
> +		memset(&lh, 0, sizeof(struct gfs_log_header));
> +
> +		lh.lh_header.mh_magic = GFS2_MAGIC;
> +		lh.lh_header.mh_type = GFS2_METATYPE_LH;
> +		lh.lh_header.mh_format = GFS2_FORMAT_LH;
> +		lh.lh_header.__pad0 = 0x101674; /* mh_generation */
> +		lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
> +		lh.lh_first = sdp->md.journal[jnum]->i_di.di_num.no_addr +
> +			(seg * sbd1->sb_seg_size);
> +		lh.lh_sequence = sequence;
> +
> +		gfs_log_header_out(&lh, bh->b_data);
> +		gfs_log_header_out(&lh, bh->b_data + GFS2_BASIC_BLOCK -
> +				   sizeof(struct gfs_log_header));
> +		brelse(bh);
> +
> +		if (++sequence == ji_nsegment)
> +			sequence = 0;
> +	}
> +	return 0;
> +}
>  
> +
> +/*
> + * reconstruct_journals - write fresh journals for GFS1 only
> + * sdp: the super block
> + *
> + * Returns: 0 on success, -1 on failure
> + */
> +static int reconstruct_journals(struct gfs2_sbd *sdp)
> +{
> +	int i;
> +	struct gfs_jindex ji;
> +	char buf[sizeof(struct gfs_jindex)];
> +
> +	log_err("Clearing GFS journals (this may take a while)");
> +	for (i = 0; i < sdp->md.journals; i++) {
> +		gfs2_readi(sdp->md.jiinode, buf, i * sizeof(struct gfs_jindex),
> +			   sizeof(struct gfs_jindex));
> +		gfs_jindex_in(&ji, buf);
> +		if ((i % 2) == 0)
> +			log_err(".");
> +		if (reconstruct_single_journal(sdp, i, ji.ji_nsegment))
> +			return -1;
> +	}
> +	log_err("\nJournals cleared.\n");
>  	return 0;
>  }
>  
> @@ -1261,24 +1408,27 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
>  	}
>  
>  	/* Get master dinode */
> -	sdp->master_dir = inode_read(sdp, sdp->sd_sb.sb_master_dir.no_addr);
> -	if (sdp->master_dir->i_di.di_header.mh_magic != GFS2_MAGIC ||
> -	    sdp->master_dir->i_di.di_header.mh_type != GFS2_METATYPE_DI ||
> -	    !sdp->master_dir->i_di.di_size) {
> +	if (sdp->gfs1)
> +		sdp->master_dir = NULL;
> +	else
> +		sdp->master_dir = inode_read(sdp,
> +					     sdp->sd_sb.sb_master_dir.no_addr);
> +	if (!sdp->gfs1 &&
> +	    (sdp->master_dir->i_di.di_header.mh_magic != GFS2_MAGIC ||
> +	     sdp->master_dir->i_di.di_header.mh_type != GFS2_METATYPE_DI ||
> +	     !sdp->master_dir->i_di.di_size)) {
>  		inode_put(&sdp->master_dir);
>  		rebuild_master(sdp);
>  		sdp->master_dir = inode_read(sdp,
>  					     sdp->sd_sb.sb_master_dir.no_addr);
>  	}
>  
> -	/* Look up the "per_node" inode.  If there are journals missing, we
> -	   need to figure out what's missing from per_node. And we need all
> -	   our journals to be there before we can replay them. */
> -	lookup_per_node(sdp, 0);
> -
>  	/* verify various things */
>  
> -	if (replay_journals(sdp, preen, force_check, &clean_journals)) {
> +	if (sdp->gfs1) {
> +		if (reconstruct_journals(sdp))
> +			return FSCK_ERROR;
> +	} else if (replay_journals(sdp, preen, force_check, &clean_journals)) {
>  		if (!opts.no && preen_is_safe(sdp, preen, force_check))
>  			block_mounters(sdp, 0);
>  		stack;
> diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
> index dbb2b58..0a5c32d 100644
> --- a/gfs2/fsck/lost_n_found.c
> +++ b/gfs2/fsck/lost_n_found.c
> @@ -31,7 +31,7 @@ static void add_dotdot(struct gfs2_inode *ip)
>  	/* If there's a pre-existing .. directory entry, we have to
>  	   back out the links. */
>  	di = dirtree_find(ip->i_di.di_num.no_addr);
> -	if (di && !valid_block(sdp, di->dotdot_parent) == 0) {
> +	if (di && valid_block(sdp, di->dotdot_parent)) {
>  		struct gfs2_inode *dip;
>  
>  		log_debug(_("Directory %lld (0x%llx) already had a "
> @@ -82,10 +82,49 @@ static void add_dotdot(struct gfs2_inode *ip)
>  	if (err) {
>  		log_crit(_("Error adding .. directory: %s\n"),
>  			 strerror(errno));
> -		exit(-1);
> +		exit(FSCK_ERROR);
>  	}
>  }
>  
> +static uint64_t find_free_blk(struct gfs2_sbd *sdp)
> +{
> +	osi_list_t *tmp, *head;
> +	struct rgrp_list *rl = NULL;
> +	struct gfs2_rindex *ri;
> +	struct gfs2_rgrp *rg;
> +	unsigned int block, bn = 0, x = 0, y = 0;
> +	unsigned int state;
> +	struct gfs2_buffer_head *bh;
> +
> +	memset(&rg, 0, sizeof(rg));
> +	for (head = &sdp->rglist, tmp = head->next; tmp != head;
> +	     tmp = tmp->next) {
> +		rl = osi_list_entry(tmp, struct rgrp_list, list);
> +		if (rl->rg.rg_free)
> +			break;
> +	}
> +
> +	if (tmp == head)
> +		return 0;
> +
> +	ri = &rl->ri;
> +	rg = &rl->rg;
> +
> +	for (block = 0; block < ri->ri_length; block++) {
> +		bh = rl->bh[block];
> +		x = (block) ? sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_rgrp);
> +
> +		for (; x < sdp->bsize; x++)
> +			for (y = 0; y < GFS2_NBBY; y++) {
> +				state = (bh->b_data[x] >> (GFS2_BIT_SIZE * y)) & 0x03;
> +				if (state == GFS2_BLKST_FREE)
> +					return ri->ri_data0 + bn;
> +				bn++;
> +			}
> +	}
> +	return 0;
> +}
> +
>  /* add_inode_to_lf - Add dir entry to lost+found for the inode
>   * @ip: inode to add to lost + found
>   *
> @@ -105,19 +144,30 @@ int add_inode_to_lf(struct gfs2_inode *ip){
>  
>  	if (!lf_dip) {
>  		uint8_t q;
> +		unsigned int mode;
>  
>  		log_info( _("Locating/Creating lost+found directory\n"));
>  
> -		lf_dip = createi(sdp->md.rooti, "lost+found",
> -				 S_IFDIR | 0700, 0);
> +		/* if this is gfs1, we have to trick createi into using
> +		   no_formal_ino = no_addr, so we set next_inum to the
> +		   free block we're about to allocate. */
> +		if (sdp->gfs1)
> +			sdp->md.next_inum = find_free_blk(sdp);
> +		mode = (sdp->gfs1 ? DT2IF(GFS_FILE_DIR) : S_IFDIR) | 0700;
> +		if (sdp->gfs1)
> +			lf_dip = gfs_createi(sdp->md.rooti, "lost+found",
> +					     mode, 0);
> +		else
> +			lf_dip = createi(sdp->md.rooti, "lost+found",
> +					 S_IFDIR | 0700, 0);
>  		if (lf_dip == NULL) {
>  			log_crit(_("Error creating lost+found: %s\n"),
>  			         strerror(errno));
> -			exit(-1);
> +			exit(FSCK_ERROR);
>  		}
>  
>  		/* createi will have incremented the di_nlink link count for
> -		   the root directory.  We must increment the nlink value
> +		   the root directory.  We must set the nlink value
>  		   in the hash table to keep them in sync so that pass4 can
>  		   detect and fix any descrepancies. */
>  		set_di_nlink(sdp->md.rooti);
> @@ -144,7 +194,9 @@ int add_inode_to_lf(struct gfs2_inode *ip){
>  			/* lost+found link for '..' back to root */
>  			incr_link_count(lf_dip->i_di.di_num.no_addr,
>  					sdp->md.rooti->i_di.di_num.no_addr,
> -					"\"..\"");
> +				       "\"..\"");
> +			if (sdp->gfs1)
> +				lf_dip->i_di.__pad1 = GFS_FILE_DIR;
>  		}
>  		log_info( _("lost+found directory is dinode %lld (0x%llx)\n"),
>  			  (unsigned long long)lf_dip->i_di.di_num.no_addr,
> @@ -162,48 +214,46 @@ int add_inode_to_lf(struct gfs2_inode *ip){
>  	}
>  	lf_blocks = lf_dip->i_di.di_blocks;
>  
> -	switch(ip->i_di.di_mode & S_IFMT){
> -	case S_IFDIR:
> +	if ((ip->i_di.di_mode & S_IFMT) == S_IFDIR ||
> +	    (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_DIR)) {

This is a bit messy. Why not just retain the switch and copy the correct
mode into a local variable here according to the fs type?


>  		add_dotdot(ip);
>  		sprintf(tmp_name, "lost_dir_%llu",
>  			(unsigned long long)ip->i_di.di_num.no_addr);
> -		inode_type = DT_DIR;
> -		break;
> -	case S_IFREG:
> +		inode_type = (sdp->gfs1 ? GFS_FILE_DIR : DT_DIR);
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFREG ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_REG)) {
>  		sprintf(tmp_name, "lost_file_%llu",
>  			(unsigned long long)ip->i_di.di_num.no_addr);
> -		inode_type = DT_REG;
> -		break;
> -	case S_IFLNK:
> +		inode_type = (sdp->gfs1 ? GFS_FILE_REG : DT_REG);
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFLNK ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_LNK)) {
>  		sprintf(tmp_name, "lost_link_%llu",
>  			(unsigned long long)ip->i_di.di_num.no_addr);
> -		inode_type = DT_LNK;
> -		break;
> -	case S_IFBLK:
> +		inode_type = (sdp->gfs1 ? GFS_FILE_LNK : DT_LNK);
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFBLK ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_BLK)) {
>  		sprintf(tmp_name, "lost_blkdev_%llu",
>  			(unsigned long long)ip->i_di.di_num.no_addr);
> -		inode_type = DT_BLK;
> -		break;
> -	case S_IFCHR:
> +		inode_type = (sdp->gfs1 ? GFS_FILE_BLK : DT_BLK);
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFCHR ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_CHR)) {
>  		sprintf(tmp_name, "lost_chrdev_%llu",
>  			(unsigned long long)ip->i_di.di_num.no_addr);
> -		inode_type = DT_CHR;
> -		break;
> -	case S_IFIFO:
> +		inode_type = (sdp->gfs1 ? GFS_FILE_CHR : DT_CHR);
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFIFO ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_FIFO)) {
>  		sprintf(tmp_name, "lost_fifo_%llu",
>  			(unsigned long long)ip->i_di.di_num.no_addr);
> -		inode_type = DT_FIFO;
> -		break;
> -	case S_IFSOCK:
> +		inode_type = (sdp->gfs1 ? GFS_FILE_FIFO : DT_FIFO);
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFSOCK ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_SOCK)) {
>  		sprintf(tmp_name, "lost_socket_%llu",
>  			(unsigned long long)ip->i_di.di_num.no_addr);
> -		inode_type = DT_SOCK;
> -		break;
> -	default:
> +		inode_type = (sdp->gfs1 ? GFS_FILE_SOCK : DT_SOCK);
> +	} else {
>  		sprintf(tmp_name, "lost_%llu",
>  			(unsigned long long)ip->i_di.di_num.no_addr);
> -		inode_type = DT_REG;
> -		break;
> +		inode_type = (sdp->gfs1 ? GFS_FILE_REG : DT_REG);
>  	}
>  
>  	err = dir_add(lf_dip, tmp_name, strlen(tmp_name), &(ip->i_di.di_num),
> @@ -211,7 +261,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){
>  	if (err) {
>  		log_crit(_("Error adding directory %s: %s\n"),
>  			 tmp_name, strerror(errno));
> -		exit(-1);
> +		exit(FSCK_ERROR);
>  	}
>  	/* If the lf directory had new blocks added we have to mark them
>  	   properly in the bitmap so they're not freed. */
> @@ -222,7 +272,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){
>  	incr_link_count(ip->i_di.di_num.no_addr, lf_dip->i_di.di_num.no_addr,
>  			_("from lost+found"));
>  	/* If it's a directory, lost+found is back-linked to it via .. */
> -	if (S_ISDIR(ip->i_di.di_mode))
> +	if (is_dir(&ip->i_di, sdp->gfs1))
>  		incr_link_count(lf_dip->i_di.di_num.no_addr,
>  				ip->i_di.di_mode, _("to lost+found"));
>  
> diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
> index 52bc9a0..448f3b3 100644
> --- a/gfs2/fsck/main.c
> +++ b/gfs2/fsck/main.c
> @@ -35,6 +35,7 @@ struct osi_root dup_blocks = (struct osi_root) { NULL, };
>  struct osi_root dirtree = (struct osi_root) { NULL, };
>  struct osi_root inodetree = (struct osi_root) { NULL, };
>  int dups_found = 0, dups_found_first = 0;
> +struct gfs_sb *sbd1 = NULL;
>  
>  /* This function is for libgfs2's sake.                                      */
>  void print_it(const char *label, const char *fmt, const char *fmt2, ...)
> @@ -155,6 +156,10 @@ static void check_statfs(struct gfs2_sbd *sdp)
>  	char buf[sizeof(struct gfs2_statfs_change)];
>  	int count;
>  
> +	if (sdp->gfs1 && !sdp->md.statfs->i_di.di_size) {
> +		log_info("This GFS1 file system is not using fast_statfs.\n");
> +		return;
> +	}
>  	/* Read the current statfs values */
>  	count = gfs2_readi(sdp->md.statfs, buf, 0,
>  			   sdp->md.statfs->i_di.di_size);
> @@ -340,16 +345,19 @@ int main(int argc, char **argv)
>  		check_statfs(sdp);
>  
>  	/* Free up our system inodes */
> -	inode_put(&sdp->md.inum);
> +	if (!sdp->gfs1)
> +		inode_put(&sdp->md.inum);
>  	inode_put(&sdp->md.statfs);
>  	for (j = 0; j < sdp->md.journals; j++)
>  		inode_put(&sdp->md.journal[j]);
>  	inode_put(&sdp->md.jiinode);
>  	inode_put(&sdp->md.riinode);
>  	inode_put(&sdp->md.qinode);
> -	inode_put(&sdp->md.pinode);
> +	if (!sdp->gfs1)
> +		inode_put(&sdp->md.pinode);
>  	inode_put(&sdp->md.rooti);
> -	inode_put(&sdp->master_dir);
> +	if (!sdp->gfs1)
> +		inode_put(&sdp->master_dir);
>  	if (lf_dip)
>  		inode_put(&lf_dip);
>  
> diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
> index c6444c8..4b5f3f4 100644
> --- a/gfs2/fsck/metawalk.c
> +++ b/gfs2/fsck/metawalk.c
> @@ -42,17 +42,19 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
>  			 (unsigned long long)blk, (unsigned long long)blk);
>  		return -1;
>  	}
> -	new_bitmap_state = blockmap_to_bitmap(new_blockmap_state);
> +	new_bitmap_state = blockmap_to_bitmap(new_blockmap_state, sdp->gfs1);
>  	if (old_bitmap_state != new_bitmap_state) {
> -		const char *allocdesc[] = {"free space", "data", "unlinked",
> -					   "inode", "reserved"};
> +		const char *allocdesc[2][5] = { /* gfs2 descriptions */
> +			{"free", "data", "unlinked", "inode", "reserved"},
> +			/* gfs1 descriptions: */
> +			{"free", "data", "free meta", "metadata", "reserved"}};
>  
>  		/* Keep these messages as short as possible, or the output
>  		   gets to be huge and unmanageable. */
>  		log_err( _("Block %llu (0x%llx) was '%s', should be %s.\n"),
>  			 (unsigned long long)blk, (unsigned long long)blk,
> -			 allocdesc[new_bitmap_state],
> -			 allocdesc[old_bitmap_state]);
> +			 allocdesc[sdp->gfs1][old_bitmap_state],
> +			 allocdesc[sdp->gfs1][new_bitmap_state]);
>  		if (query( _("Fix the bitmap? (y/n)"))) {
>  			/* If the new bitmap state is free (and therefore the
>  			   old state was not) we have to add to the free
> @@ -77,10 +79,18 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
>  						inodetree_delete(ii);
>  				}
>  				rgd->rg.rg_free++;
> -				gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
> +				if (sdp->gfs1)
> +					gfs_rgrp_out((struct gfs_rgrp *)
> +						     &rgd->rg, rgd->bh[0]);
> +				else
> +					gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
>  			} else if (old_bitmap_state == GFS2_BLKST_FREE) {
>  				rgd->rg.rg_free--;
> -				gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
> +				if (sdp->gfs1)
> +					gfs_rgrp_out((struct gfs_rgrp *)
> +						     &rgd->rg, rgd->bh[0]);
> +				else
> +					gfs2_rgrp_out(&rgd->rg, rgd->bh[0]);
>  			}
>  			log_err( _("The bitmap was fixed.\n"));
>  		} else {
> @@ -170,9 +180,28 @@ struct duptree *dupfind(uint64_t block)
>  
>  struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp, uint64_t block)
>  {
> +	int j;
> +
>  	if (lf_dip && lf_dip->i_di.di_num.no_addr == block)
>  		return lf_dip;
> -	return is_system_inode(sdp, block);
> +	if (!sdp->gfs1)
> +		return is_system_inode(sdp, block);
> +
> +	if (sdp->md.statfs && block == sdp->md.statfs->i_di.di_num.no_addr)
> +		return sdp->md.statfs;
> +	if (sdp->md.jiinode && block == sdp->md.jiinode->i_di.di_num.no_addr)
> +		return sdp->md.jiinode;
> +	if (sdp->md.riinode && block == sdp->md.riinode->i_di.di_num.no_addr)
> +		return sdp->md.riinode;
> +	if (sdp->md.qinode && block == sdp->md.qinode->i_di.di_num.no_addr)
> +		return sdp->md.qinode;
> +	if (sdp->md.rooti && block == sdp->md.rooti->i_di.di_num.no_addr)
> +		return sdp->md.rooti;
> +	for (j = 0; j < sdp->md.journals; j++)
> +		if (sdp->md.journal && sdp->md.journal[j] &&
> +		    block == sdp->md.journal[j]->i_di.di_num.no_addr)
> +			return sdp->md.journal[j];
> +	return NULL;
>  }
>  
>  /* fsck_load_inode - same as gfs2_load_inode() in libgfs2 but system inodes
> @@ -184,6 +213,8 @@ struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sdp, uint64_t block)
>  	ip = fsck_system_inode(sdp, block);
>  	if (ip)
>  		return ip;
> +	if (sdp->gfs1)
> +		return gfs_inode_read(sdp, block);
>  	return inode_read(sdp, block);
>  }
>  
> @@ -198,6 +229,8 @@ struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp,
>  	if (sysip)
>  		return sysip;
>  
> +	if (sdp->gfs1)
> +		return gfs_inode_get(sdp, bh);
>  	return inode_get(sdp, bh);
>  }
>  
> @@ -431,11 +464,12 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
>  	return 0;
>  }
>  
> -/* Process a bad leaf pointer and ask to repair the first time.      */
> -/* The repair process involves extending the previous leaf's entries */
> -/* so that they replace the bad ones.  We have to hack up the old    */
> -/* leaf a bit, but it's better than deleting the whole directory,    */
> -/* which is what used to happen before.                              */
> +/* warn_and_patch - Warn the user of an error and ask permission to fix it
> + * Process a bad leaf pointer and ask to repair the first time.
> + * The repair process involves extending the previous leaf's entries
> + * so that they replace the bad ones.  We have to hack up the old
> + * leaf a bit, but it's better than deleting the whole directory,
> + * which is what used to happen before. */
>  static int warn_and_patch(struct gfs2_inode *ip, uint64_t *leaf_no, 
>  			  uint64_t *bad_leaf, uint64_t old_leaf,
>  			  uint64_t first_ok_leaf, int pindex, const char *msg)
> @@ -538,7 +572,7 @@ static int check_leaf(struct gfs2_inode *ip, int lindex,
>  		goto out_copy_old_leaf;
>  	}
>  
> -	if (pass->check_dentry && S_ISDIR(ip->i_di.di_mode)) {
> +	if (pass->check_dentry && is_dir(&ip->i_di, sdp->gfs1)) {
>  		error = check_entries(ip, lbh, DIR_EXHASH, &count, pass);
>  
>  		if (skip_this_pass || fsck_abort)
> @@ -1073,7 +1107,7 @@ static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp,
>  	   because it checks everything through the hash table using
>  	   "depth" field calculations. However, we still have to check the
>  	   indirect blocks, even if the height == 1.  */
> -	if (S_ISDIR(ip->i_di.di_mode))
> +	if (is_dir(&ip->i_di, ip->i_sbd->gfs1))
>  		height++;
>  
>  	/* if (<there are no indirect blocks to check>) */
> @@ -1081,12 +1115,15 @@ static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp,
>  		return 0;
>  	for (h = 1; h < height; h++) {
>  		if (h > 1) {
> -			if (S_ISDIR(ip->i_di.di_mode) &&
> +			if (is_dir(&ip->i_di, ip->i_sbd->gfs1) &&
>  			    h == ip->i_di.di_height + 1)
>  				iblk_type = GFS2_METATYPE_JD;
>  			else
>  				iblk_type = GFS2_METATYPE_IN;
> -			head_size = sizeof(struct gfs2_meta_header);
> +			if (ip->i_sbd->gfs1)
> +				head_size = sizeof(struct gfs_indirect);
> +			else
> +				head_size = sizeof(struct gfs2_meta_header);
>  		} else {
>  			iblk_type = GFS2_METATYPE_DI;
>  			head_size = sizeof(struct gfs2_dinode);
> @@ -1177,7 +1214,7 @@ static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass,
>  		if (skip_this_pass || fsck_abort)
>  			return error;
>  		block =  be64_to_cpu(*ptr);
> -		/* It's important that we don't call !valid_block and
> +		/* It's important that we don't call valid_block() and
>  		   bypass calling check_data on invalid blocks because that
>  		   would defeat the rangecheck_block related functions in
>  		   pass1. Therefore the individual check_data functions
> @@ -1208,7 +1245,7 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
>  	uint64_t blks_checked = 0;
>  	int error, rc;
>  
> -	if (!height && !S_ISDIR(ip->i_di.di_mode))
> +	if (!height && !is_dir(&ip->i_di, ip->i_sbd->gfs1))
>  		return 0;
>  
>  	for (i = 0; i < GFS2_MAX_META_HEIGHT; i++)
> @@ -1224,7 +1261,7 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
>  	/* For directories, we've already checked the "data" blocks which
>  	 * comprise the directory hash table, so we perform the directory
>  	 * checks and exit. */
> -        if (S_ISDIR(ip->i_di.di_mode)) {
> +        if (is_dir(&ip->i_di, ip->i_sbd->gfs1)) {
>  		free_metalist(ip, &metalist[0]);
>  		if (!(ip->i_di.di_flags & GFS2_DIF_EXHASH))
>  			return 0;
> @@ -1267,7 +1304,10 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
>  					brelse(bh);
>  				continue;
>  			}
> -			head_size = sizeof(struct gfs2_meta_header);
> +			if (ip->i_sbd->gfs1)
> +				head_size = sizeof(struct gfs_indirect);
> +			else
> +				head_size = sizeof(struct gfs2_meta_header);
>  		} else {
>  			/* if this isn't really a dinode, skip it */
>  			if (gfs2_check_meta(bh, GFS2_METATYPE_DI)) {
> @@ -1438,7 +1478,7 @@ static int alloc_metalist(struct gfs2_inode *ip, uint64_t block,
>  	   after the bitmap has been set but before the blockmap has. */
>  	*bh = bread(ip->i_sbd, block);
>  	q = block_type(block);
> -	if (blockmap_to_bitmap(q) == GFS2_BLKST_FREE) { /* If not marked yet */
> +	if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE) {
>  		log_debug(_("%s reference to new metadata block "
>  			    "%lld (0x%llx) is now marked as indirect.\n"),
>  			  desc, (unsigned long long)block,
> @@ -1457,7 +1497,7 @@ static int alloc_data(struct gfs2_inode *ip, uint64_t block, void *private)
>  	/* We can't check the bitmap here because this function is called
>  	   after the bitmap has been set but before the blockmap has. */
>  	q = block_type(block);
> -	if (blockmap_to_bitmap(q) == GFS2_BLKST_FREE) { /* If not marked yet */
> +	if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE) {
>  		log_debug(_("%s reference to new data block "
>  			    "%lld (0x%llx) is now marked as data.\n"),
>  			  desc, (unsigned long long)block,
> @@ -1475,7 +1515,7 @@ static int alloc_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
>  	/* We can't check the bitmap here because this function is called
>  	   after the bitmap has been set but before the blockmap has. */
>  	q = block_type(block);
> -	if (blockmap_to_bitmap(q) == GFS2_BLKST_FREE) /* If not marked yet */
> +	if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE)
>  		fsck_blockmap_set(ip, block, _("newly allocated leaf"),
>  				  gfs2_leaf_blk);
>  	return 0;
> diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
> index afb5925..df7ec1d 100644
> --- a/gfs2/fsck/pass1.c
> +++ b/gfs2/fsck/pass1.c
> @@ -1,5 +1,3 @@
> -#include "clusterautoconfig.h"
> -
>  /* pass1 checks inodes for format & type, duplicate blocks, & incorrect
>   * block count.
>   *
> @@ -28,6 +26,8 @@
>  #include "link.h"
>  #include "metawalk.h"
>  
> +struct special_blocks gfs1_rindex_blks;
> +
>  struct block_count {
>  	uint64_t indir_count;
>  	uint64_t data_count;
> @@ -176,9 +176,10 @@ static int resuscitate_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
>  			 (unsigned long long)ip->i_di.di_num.no_addr);
>  		return 0;
>  	}
> -	if (block == sdp->md.jiinode->i_di.di_num.no_addr ||
> -	    block == sdp->md.pinode->i_di.di_num.no_addr ||
> -	    block == sdp->master_dir->i_di.di_num.no_addr)
> +	if (block == sdp->md.jiinode->i_di.di_num.no_addr)
> +		dinode_type = gfs2_inode_dir;
> +	else if (!sdp->gfs1 && (block == sdp->md.pinode->i_di.di_num.no_addr ||
> +				block == sdp->master_dir->i_di.di_num.no_addr))
>  		dinode_type = gfs2_inode_dir;
>  	else
>  		dinode_type = gfs2_inode_file;
> @@ -241,8 +242,12 @@ static int fix_leaf_pointers(struct gfs2_inode *dip, int *lindex,
>  	   the last 8 of them.  If we have 7, write the last 4, etc.
>  	   We need to write these starting at the current lindex and adjust
>  	   lindex accordingly. */
> -	count = gfs2_writei(dip, ptrbuf + (off_by * sizeof(uint64_t)),
> -			    start_lindex * sizeof(uint64_t), bufsize);
> +	if (dip->i_sbd->gfs1)
> +		count = gfs1_writei(dip, ptrbuf + (off_by * sizeof(uint64_t)),
> +				    start_lindex * sizeof(uint64_t), bufsize);
> +	else
> +		count = gfs2_writei(dip, ptrbuf + (off_by * sizeof(uint64_t)),
> +				    start_lindex * sizeof(uint64_t), bufsize);
>  	if (count != bufsize) {
>  		log_err( _("Error: bad read while fixing leaf pointers.\n"));
>  		free(ptrbuf);
> @@ -250,8 +255,12 @@ static int fix_leaf_pointers(struct gfs2_inode *dip, int *lindex,
>  	}
>  	/* Now zero out the hole left at the end */
>  	memset(ptrbuf, 0, off_by * sizeof(uint64_t));
> -	gfs2_writei(dip, ptrbuf, (start_lindex * sizeof(uint64_t)) +
> -		    bufsize, off_by * sizeof(uint64_t));
> +	if (dip->i_sbd->gfs1)
> +		gfs1_writei(dip, ptrbuf, (start_lindex * sizeof(uint64_t)) +
> +			    bufsize, off_by * sizeof(uint64_t));
> +	else
> +		gfs2_writei(dip, ptrbuf, (start_lindex * sizeof(uint64_t)) +
> +			    bufsize, off_by * sizeof(uint64_t));
Perhaps change to a single function which takes an arg to say which
fstype is required?


>  	free(ptrbuf);
>  	*lindex -= off_by; /* adjust leaf index to account for the change */
>  	return 0;
> @@ -377,7 +386,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block,
>  
>  		return 1;
>  	}
> -	if (S_ISDIR(ip->i_di.di_mode) && h == ip->i_di.di_height) {
> +	if (is_dir(&ip->i_di, ip->i_sbd->gfs1) && h == ip->i_di.di_height) {
>  		iblk_type = GFS2_METATYPE_JD;
>  		blktypedesc = _("a directory hash table block");
>  	} else {
> @@ -445,7 +454,7 @@ static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
>  				  _("itself"), gfs2_block_free);
>  		return 1;
>  	}
> -	if (S_ISDIR(ip->i_di.di_mode) && h == ip->i_di.di_height)
> +	if (is_dir(&ip->i_di, ip->i_sbd->gfs1) && h == ip->i_di.di_height)
>  		iblk_type = GFS2_METATYPE_JD;
>  	else
>  		iblk_type = GFS2_METATYPE_IN;
> @@ -522,7 +531,22 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private)
>  		bc->data_count++;
>  		return 1;
>  	}
> -	fsck_blockmap_set(ip, block, _("data"), gfs2_block_used);
> +	/* In gfs1, rgrp indirect blocks are marked in the bitmap as "meta".
> +	   In gfs2, "meta" is only for dinodes. So here we dummy up the
> +	   blocks so that the bitmap isn't changed improperly. */
> +	if (ip->i_sbd->gfs1 && ip == ip->i_sbd->md.riinode) {
> +		log_info(_("Block %lld (0x%llx) is a GFS1 rindex block\n"),
> +			 (unsigned long long)block, (unsigned long long)block);
> +		gfs2_special_set(&gfs1_rindex_blks, block);
> +		fsck_blockmap_set(ip, block, _("rgrp"), gfs2_indir_blk);
> +		/*gfs2_meta_rgrp);*/
> +	} else if (ip->i_sbd->gfs1 && ip->i_di.di_flags & GFS2_DIF_JDATA) {
> +		log_info(_("Block %lld (0x%llx) is a GFS1 journaled data "
> +			   "block\n"),
> +			 (unsigned long long)block, (unsigned long long)block);
> +		fsck_blockmap_set(ip, block, _("jdata"), gfs2_jdata);
> +	} else
> +		fsck_blockmap_set(ip, block, _("data"), gfs2_block_used);
>  	bc->data_count++;
>  	return 0;
>  }
> @@ -1016,6 +1040,7 @@ static int invalidate_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
>   * messing with them because we don't want to mark a block as a
>   * duplicate (for example) until we know if the pointers in general can
>   * be trusted. Thus it needs to be in a separate loop.
> + * Returns: 0 if good range, otherwise != 0
>   */
>  static int rangecheck_block(struct gfs2_inode *ip, uint64_t block,
>  			    struct gfs2_buffer_head **bh,
> @@ -1128,46 +1153,43 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip)
>  		return 0;
>  	}
>  
> -	switch(ip->i_di.di_mode & S_IFMT) {
> -
> -	case S_IFDIR:
> +	if ((ip->i_di.di_mode & S_IFMT) == S_IFDIR ||
> +	    (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_DIR)) {
Same comments wrt this switch as the one above.


>  		if (fsck_blockmap_set(ip, block, _("directory"),
>  				      gfs2_inode_dir))
>  			goto bad_dinode;
>  		if (!dirtree_insert(block))
>  			goto bad_dinode;
> -		break;
> -	case S_IFREG:
> -		if (fsck_blockmap_set(ip, block, _("file"),
> -				      gfs2_inode_file))
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFREG ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_REG)) {
> +		if (fsck_blockmap_set(ip, block, _("file"), gfs2_inode_file))
>  			goto bad_dinode;
> -		break;
> -	case S_IFLNK:
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFLNK ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_LNK)) {
>  		if (fsck_blockmap_set(ip, block, _("symlink"),
>  				      gfs2_inode_lnk))
>  			goto bad_dinode;
> -		break;
> -	case S_IFBLK:
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFBLK ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_BLK)) {
>  		if (fsck_blockmap_set(ip, block, _("block device"),
>  				      gfs2_inode_device))
>  			goto bad_dinode;
> -		break;
> -	case S_IFCHR:
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFCHR ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_CHR)) {
>  		if (fsck_blockmap_set(ip, block, _("character device"),
>  				      gfs2_inode_device))
>  			goto bad_dinode;
> -		break;
> -	case S_IFIFO:
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFIFO ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_FIFO)) {
>  		if (fsck_blockmap_set(ip, block, _("fifo"),
>  				      gfs2_inode_fifo))
>  			goto bad_dinode;
> -		break;
> -	case S_IFSOCK:
> +	} else if ((ip->i_di.di_mode & S_IFMT) == S_IFSOCK ||
> +		   (sdp->gfs1 && ip->i_di.__pad1 == GFS_FILE_SOCK)) {
>  		if (fsck_blockmap_set(ip, block, _("socket"),
>  				      gfs2_inode_sock))
>  			goto bad_dinode;
> -		break;
> -	default:
> +	} else {
>  		/* We found a dinode that has an invalid mode, so we can't
>  		   tell if it's a data file, directory or a socket.
>  		   Regardless, we have to invalidate its metadata in case there
> @@ -1192,8 +1214,7 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip)
>  	if (set_di_nlink(ip))
>  		goto bad_dinode;
>  
> -	if (S_ISDIR(ip->i_di.di_mode) &&
> -	    (ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
> +	if (is_dir(&ip->i_di, sdp->gfs1) && (ip->i_di.di_flags & GFS2_DIF_EXHASH)) {
>  		if (((1 << ip->i_di.di_depth) * sizeof(uint64_t)) != ip->i_di.di_size){
>  			log_warn( _("Directory dinode block #%llu (0x%llx"
>  				 ") has bad depth.  Found %u, Expected %u\n"),
> @@ -1395,7 +1416,7 @@ static int check_system_inode(struct gfs2_sbd *sdp,
>  			return -1;
>  		}
>  	}
> -	if (S_ISDIR((*sysinode)->i_di.di_mode)) {
> +	if (is_dir(&(*sysinode)->i_di, sdp->gfs1)) {
>  		struct block_count bc = {0};
>  
>  		sysdir_fxns.private = &bc;
> @@ -1421,7 +1442,7 @@ static int build_a_journal(struct gfs2_sbd *sdp)
>  	err = build_journal(sdp, sdp->md.journals, sdp->md.jiinode);
>  	if (err) {
>  		log_crit(_("Error building journal: %s\n"), strerror(err));
> -		exit(-1);
> +		exit(FSCK_ERROR);
>  	}
>  	return 0;
>  }
> @@ -1436,13 +1457,15 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
>  	/* Mark the master system dinode as a "dinode" in the block map.
>  	   All other system dinodes in master will be taken care of by function
>  	   resuscitate_metalist.  But master won't since it has no parent.*/
> -	fsck_blockmap_set(sdp->master_dir,
> -			  sdp->master_dir->i_di.di_num.no_addr,
> -			  "master", gfs2_inode_dir);
> -	if (check_system_inode(sdp, &sdp->master_dir, "master", build_master,
> -			       gfs2_inode_dir)) {
> -		stack;
> -		return -1;
> +	if (!sdp->gfs1) {
> +		fsck_blockmap_set(sdp->master_dir,
> +				  sdp->master_dir->i_di.di_num.no_addr,
> +				  "master", gfs2_inode_dir);
> +		if (check_system_inode(sdp, &sdp->master_dir, "master",
> +				       build_master, gfs2_inode_dir)) {
> +			stack;
> +			return -1;
> +		}
>  	}
>  	/* Mark the root dinode as a "dinode" in the block map as we did
>  	   for master, since it has no parent. */
> @@ -1453,7 +1476,8 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
>  		stack;
>  		return -1;
>  	}
> -	if (check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
> +	if (!sdp->gfs1 &&
> +	    check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
>  			       gfs2_inode_file)) {
>  		stack;
>  		return -1;
> @@ -1464,7 +1488,7 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
>  		return -1;
>  	}
>  	if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex,
> -			       gfs2_inode_dir)) {
> +			       (sdp->gfs1 ? gfs2_inode_file : gfs2_inode_dir))) {
>  		stack;
>  		return -1;
>  	}
> @@ -1478,7 +1502,8 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
>  		stack;
>  		return -1;
>  	}
> -	if (check_system_inode(sdp, &sdp->md.pinode, "per_node",
> +	if (!sdp->gfs1 &&
> +	    check_system_inode(sdp, &sdp->md.pinode, "per_node",
>  			       build_per_node, gfs2_inode_dir)) {
>  		stack;
>  		return -1;
> @@ -1486,6 +1511,21 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
>  	/* We have to play a trick on build_journal:  We swap md.journals
>  	   in order to keep a count of which journal we need to build. */
>  	journal_count = sdp->md.journals;
> +	/* gfs1's journals aren't dinode, they're just a bunch of blocks. */
> +	if (sdp->gfs1) {
> +		/* gfs1 has four dinodes that are set in the superblock and
> +		   therefore not linked to anything else. We need to adjust
> +		   the link counts so pass4 doesn't get confused. */
> +		incr_link_count(sdp->md.statfs->i_di.di_num.no_addr, 0,
> +				_("gfs1 statfs inode"));
> +		incr_link_count(sdp->md.jiinode->i_di.di_num.no_addr, 0,
> +				_("gfs1 jindex inode"));
> +		incr_link_count(sdp->md.riinode->i_di.di_num.no_addr, 0,
> +				_("gfs1 rindex inode"));
> +		incr_link_count(sdp->md.qinode->i_di.di_num.no_addr, 0,
> +				_("gfs1 quota inode"));
> +		return 0;
> +	}
>  	for (sdp->md.journals = 0; sdp->md.journals < journal_count;
>  	     sdp->md.journals++) {
>  		char jname[16];
> @@ -1523,8 +1563,12 @@ int pass1(struct gfs2_sbd *sdp)
>  	struct rgrp_list *rgd;
>  	int first;
>  	uint64_t i;
> +	uint64_t blk_count;
> +	uint64_t offset;
>  	uint64_t rg_count = 0;
>  
> +	osi_list_init(&gfs1_rindex_blks.list);
> +
>  	/* FIXME: In the gfs fsck, we had to mark things like the
>  	 * journals and indices and such as 'other_meta' - in gfs2,
>  	 * the journals are files and are found in the normal file
> @@ -1555,6 +1599,7 @@ int pass1(struct gfs2_sbd *sdp)
>  			if (gfs2_blockmap_set(bl, rgd->ri.ri_addr + i,
>  					      gfs2_indir_blk)) {
>  				stack;
> +				gfs2_special_free(&gfs1_rindex_blks);
>  				return FSCK_ERROR;
>  			}
>  			/* rgrps and bitmaps don't have bits to represent
> @@ -1563,18 +1608,33 @@ int pass1(struct gfs2_sbd *sdp)
>  			gfs2_meta_rgrp);*/
>  		}
>  
> +		offset = (sdp->gfs1 ? sizeof(struct gfs_rgrp) :
> +			  sizeof(struct gfs2_rgrp));
> +		blk_count = 1;
>  		first = 1;
>  
>  		while (1) {
>  			/* "block" is relative to the entire file system */
>  			/* Get the next dinode in the file system, according
> -			   to the bitmap.  This should ONLY be dinodes. */
> +			   to the bitmap.  This should ONLY be dinodes unless
> +			   it's GFS1, in which case it can be any metadata. */
>  			if (gfs2_next_rg_meta(rgd, &block, first))
>  				break;
> +			/* skip gfs1 rindex indirect blocks */
> +			if (sdp->gfs1 && blockfind(&gfs1_rindex_blks, block)) {
> +				log_debug(_("Skipping rindex indir block "
> +					    "%lld (0x%llx)\n"),
> +					  (unsigned long long)block,
> +					  (unsigned long long)block);
> +				first = 0;
> +				continue;
> +			}
>  			warm_fuzzy_stuff(block);
>  
> -			if (fsck_abort) /* if asked to abort */
> +			if (fsck_abort) { /* if asked to abort */
> +				gfs2_special_free(&gfs1_rindex_blks);
>  				return FSCK_OK;
> +			}
>  			if (skip_this_pass) {
>  				printf( _("Skipping pass 1 is not a good idea.\n"));
>  				skip_this_pass = FALSE;
> @@ -1590,7 +1650,35 @@ int pass1(struct gfs2_sbd *sdp)
>  			}
>  			bh = bread(sdp, block);
>  
> +			/*log_debug( _("Checking metadata block #%" PRIu64
> +			  " (0x%" PRIx64 ")\n"), block, block);*/
> +
>  			if (gfs2_check_meta(bh, GFS2_METATYPE_DI)) {
> +				/* In gfs2, a bitmap mark of 2 means an inode,
> +				   but in gfs1 it means any metadata.  So if
> +				   this is gfs1 and not an inode, it may be
> +				   okay.  If it's non-dinode metadata, it will
> +				   be referenced by an inode, so we need to
> +				   skip it here and it will be sorted out
> +				   when the referencing inode is checked. */
> +				if (sdp->gfs1) {
> +					uint32_t check_magic;
> +
> +					check_magic = ((struct
> +							gfs2_meta_header *)
> +						       (bh->b_data))->mh_magic;
> +					if (be32_to_cpu(check_magic) ==
> +					    GFS2_MAGIC) {
> +						log_debug( _("Deferring GFS1 "
> +							     "metadata block #"
> +							     "%" PRIu64" (0x%"
> +							     PRIx64 ")\n"),
> +							   block, block);
> +						brelse(bh);
> +						first = 0;
> +						continue;
> +					}
> +				}
>  				log_err( _("Found invalid inode at block #"
>  					   "%llu (0x%llx)\n"),
>  					 (unsigned long long)block,
> @@ -1599,6 +1687,7 @@ int pass1(struct gfs2_sbd *sdp)
>  						      gfs2_block_free)) {
>  					stack;
>  					brelse(bh);
> +					gfs2_special_free(&gfs1_rindex_blks);
>  					return FSCK_ERROR;
>  				}
>  				check_n_fix_bitmap(sdp, block,
> @@ -1606,6 +1695,7 @@ int pass1(struct gfs2_sbd *sdp)
>  			} else if (handle_di(sdp, bh) < 0) {
>  				stack;
>  				brelse(bh);
> +				gfs2_special_free(&gfs1_rindex_blks);
>  				return FSCK_ERROR;
>  			}
>  			/* Ignore everything else - they should be hit by the
> @@ -1618,6 +1708,19 @@ int pass1(struct gfs2_sbd *sdp)
>  			brelse(bh);
>  			first = 0;
>  		}
> +		/*
> +		  For GFS1, we have to count the "free meta" blocks in the
> +		  resource group and mark them specially so we can count them
> +		  properly in pass5.
> +		 */
> +		if (!sdp->gfs1)
> +			continue;
> +		first = 1;
> +		while (gfs2_next_rg_freemeta(rgd, &block, first) == 0) {
> +			gfs2_blockmap_set(bl, block, gfs2_freemeta);
> +			first = 0;
> +		}
>  	}
> +	gfs2_special_free(&gfs1_rindex_blks);
>  	return FSCK_OK;
>  }
> diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
> index f744eae..e514575 100644
> --- a/gfs2/fsck/pass1b.c
> +++ b/gfs2/fsck/pass1b.c
> @@ -360,7 +360,8 @@ static int find_block_ref(struct gfs2_sbd *sdp, uint64_t inode)
>  	/* Exhash dir leafs will be checked by check_metatree (right after
>  	   the "end:" label.)  But if this is a linear directory we need to
>  	   check the dir with check_linear_dir. */
> -	if (S_ISDIR(ip->i_di.di_mode) && !(ip->i_di.di_flags & GFS2_DIF_EXHASH))
> +	if (is_dir(&ip->i_di, sdp->gfs1) &&
> +	   !(ip->i_di.di_flags & GFS2_DIF_EXHASH))
>  		error = check_linear_dir(ip, ip->i_bh, &find_dirents);
>  
>  	/* Check for ea references in the inode */
> @@ -697,7 +698,7 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *b)
>  					  _("reference-repaired data"),
>  					  gfs2_block_used);
>  		} else if (id->reftypecount[ref_as_meta]) {
> -			if (S_ISDIR(ip->i_di.di_mode))
> +			if (is_dir(&ip->i_di, sdp->gfs1))
>  				fsck_blockmap_set(ip, b->block,
>  						  _("reference-repaired leaf"),
>  						  gfs2_leaf_blk);
> diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
> index e2c6697..52763a2 100644
> --- a/gfs2/fsck/pass2.c
> +++ b/gfs2/fsck/pass2.c
> @@ -123,31 +123,32 @@ static const char *de_type_string(uint8_t de_type)
>  	return de_types[3]; /* invalid */
>  }
>  
> -static int check_file_type(uint8_t de_type, uint8_t blk_type)
> +static int check_file_type(uint8_t de_type, uint8_t blk_type, int gfs1)
>  {
>  	switch(blk_type) {
>  	case gfs2_inode_dir:
> -		if (de_type != DT_DIR)
> +		if (de_type != (gfs1 ? GFS_FILE_DIR : DT_DIR))
>  			return 1;
>  		break;
>  	case gfs2_inode_file:
> -		if (de_type != DT_REG)
> +		if (de_type != (gfs1 ? GFS_FILE_REG : DT_REG))
>  			return 1;
>  		break;
>  	case gfs2_inode_lnk:
> -		if (de_type != DT_LNK)
> +		if (de_type != (gfs1 ? GFS_FILE_LNK : DT_LNK))
>  			return 1;
>  		break;
>  	case gfs2_inode_device:
> -		if (de_type != DT_BLK && de_type != DT_CHR)
> +		if ((de_type != (gfs1 ? GFS_FILE_BLK : DT_BLK)) &&
> +		    (de_type != (gfs1 ? GFS_FILE_CHR : DT_CHR)))
>  			return 1;
>  		break;
>  	case gfs2_inode_fifo:
> -		if (de_type != DT_FIFO)
> +		if (de_type != (gfs1 ? GFS_FILE_FIFO : DT_FIFO))
>  			return 1;
>  		break;
>  	case gfs2_inode_sock:
> -		if (de_type != DT_SOCK)
> +		if (de_type != (gfs1 ? GFS_FILE_SOCK : DT_SOCK))
>  			return 1;
>  		break;
>  	default:
> @@ -395,7 +396,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
>  		goto nuke_dentry;
>  	}
>  
> -	error = check_file_type(de->de_type, q);
> +	error = check_file_type(de->de_type, q, sdp->gfs1);
>  	if (error < 0) {
>  		log_err( _("Error: directory entry type is "
>  			   "incompatible with block type at block %lld "
> @@ -668,7 +669,9 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
>  			memcpy(filename, tmp_name, filename_len);
>  			log_warn( _("Adding '.' entry\n"));
>  			error = dir_add(sysinode, filename, filename_len,
> -				&(sysinode->i_di.di_num), DT_DIR);
> +					&(sysinode->i_di.di_num),
> +					(sysinode->i_sbd->gfs1 ?
> +					 GFS_FILE_DIR : DT_DIR));
>  			if (error) {
>  				log_err(_("Error adding directory %s: %s\n"),
>  				        filename, strerror(error));
> @@ -715,8 +718,11 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
>   */
>  static inline int is_system_dir(struct gfs2_sbd *sdp, uint64_t block)
>  {
> -	if (block == sdp->md.rooti->i_di.di_num.no_addr ||
> -	    block == sdp->md.jiinode->i_di.di_num.no_addr ||
> +	if (block == sdp->md.rooti->i_di.di_num.no_addr)
> +		return TRUE;
> +	if (sdp->gfs1)
> +		return FALSE;
> +	if (block == sdp->md.jiinode->i_di.di_num.no_addr ||
>  	    block == sdp->md.pinode->i_di.di_num.no_addr ||
>  	    block == sdp->master_dir->i_di.di_num.no_addr)
>  		return TRUE;
> @@ -746,19 +752,22 @@ int pass2(struct gfs2_sbd *sdp)
>  	int error = 0;
>  
>  	/* Check all the system directory inodes. */
> -	if (check_system_dir(sdp->md.jiinode, "jindex", build_jindex)) {
> +	if (!sdp->gfs1 &&
> +	    check_system_dir(sdp->md.jiinode, "jindex", build_jindex)) {
>  		stack;
>  		return FSCK_ERROR;
>  	}
>  	if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
>  		return FSCK_OK;
> -	if (check_system_dir(sdp->md.pinode, "per_node", build_per_node)) {
> +	if (!sdp->gfs1 &&
> +	    check_system_dir(sdp->md.pinode, "per_node", build_per_node)) {
>  		stack;
>  		return FSCK_ERROR;
>  	}
>  	if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
>  		return FSCK_OK;
> -	if (check_system_dir(sdp->master_dir, "master", build_master)) {
> +	if (!sdp->gfs1 &&
> +	    check_system_dir(sdp->master_dir, "master", build_master)) {
>  		stack;
>  		return FSCK_ERROR;
>  	}
> @@ -880,7 +889,9 @@ int pass2(struct gfs2_sbd *sdp)
>  
>  				cur_blks = ip->i_di.di_blocks;
>  				error = dir_add(ip, filename, filename_len,
> -					&(ip->i_di.di_num), DT_DIR);
> +						&(ip->i_di.di_num),
> +						(sdp->gfs1 ? GFS_FILE_DIR :
> +						 DT_DIR));
>  				if (error) {
>  					log_err(_("Error adding directory %s: %s\n"),
>  					        filename, strerror(error));
> diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
> index 1363606..f0b35e2 100644
> --- a/gfs2/fsck/pass3.c
> +++ b/gfs2/fsck/pass3.c
> @@ -54,11 +54,12 @@ static int attach_dotdot_to(struct gfs2_sbd *sdp, uint64_t newdotdot,
>  	else
>  		decr_link_count(olddotdot, block, _("old \"..\""));
>  	cur_blks = ip->i_di.di_blocks;
> -	err = dir_add(ip, filename, filename_len, &pip->i_di.di_num, DT_DIR);
> +	err = dir_add(ip, filename, filename_len, &pip->i_di.di_num,
> +		      (sdp->gfs1 ? GFS_FILE_DIR : DT_DIR));
>  	if (err) {
>  		log_err(_("Error adding directory %s: %s\n"),
>  		        filename, strerror(err));
> -		exit(-1);
> +		exit(FSCK_ERROR);
>  	}
>  	if (cur_blks != ip->i_di.di_blocks) {
>  		char dirname[80];
> @@ -195,10 +196,38 @@ int pass3(struct gfs2_sbd *sdp)
>  		log_info( _("Marking root inode connected\n"));
>  		di->checked = 1;
>  	}
> -	di = dirtree_find(sdp->master_dir->i_di.di_num.no_addr);
> -	if (di) {
> -		log_info( _("Marking master directory inode connected\n"));
> -		di->checked = 1;
> +	if (sdp->gfs1) {
> +		di = dirtree_find(sdp->md.statfs->i_di.di_num.no_addr);
> +		if (di) {
> +			log_info( _("Marking GFS1 statfs file inode "
> +				    "connected\n"));
> +			di->checked = 1;
> +		}
> +		di = dirtree_find(sdp->md.jiinode->i_di.di_num.no_addr);
> +		if (di) {
> +			log_info( _("Marking GFS1 jindex file inode "
> +				    "connected\n"));
> +			di->checked = 1;
> +		}
> +		di = dirtree_find(sdp->md.riinode->i_di.di_num.no_addr);
> +		if (di) {
> +			log_info( _("Marking GFS1 rindex file inode "
> +				    "connected\n"));
> +			di->checked = 1;
> +		}
> +		di = dirtree_find(sdp->md.qinode->i_di.di_num.no_addr);
> +		if (di) {
> +			log_info( _("Marking GFS1 quota file inode "
> +				    "connected\n"));
> +			di->checked = 1;
> +		}
> +	} else {
> +		di = dirtree_find(sdp->master_dir->i_di.di_num.no_addr);
> +		if (di) {
> +			log_info( _("Marking master directory inode "
> +				    "connected\n"));
> +			di->checked = 1;
> +		}
>  	}
>  
>  	/* Go through the directory list, working up through the parents
> diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c
> index 556719a..80ecb38 100644
> --- a/gfs2/fsck/pass4.c
> +++ b/gfs2/fsck/pass4.c
> @@ -58,6 +58,13 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
>  			log_crit( _("osi_tree broken in scan_info_list!!\n"));
>  			exit(FSCK_ERROR);
>  		}
> +		/* Don't check reference counts on the special gfs files */
> +		if (sdp->gfs1 &&
> +		    ((ii->inode == sdp->md.riinode->i_di.di_num.no_addr) ||
> +		     (ii->inode == sdp->md.jiinode->i_di.di_num.no_addr) ||
> +		     (ii->inode == sdp->md.qinode->i_di.di_num.no_addr) ||
> +		     (ii->inode == sdp->md.statfs->i_di.di_num.no_addr)))
> +			continue;
>  		if (ii->counted_links == 0) {
>  			log_err( _("Found unlinked inode at %llu (0x%llx)\n"),
>  				(unsigned long long)ii->inode,
> diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
> index 9cd4804..2a4ffbc 100644
> --- a/gfs2/fsck/pass5.c
> +++ b/gfs2/fsck/pass5.c
> @@ -11,7 +11,7 @@
>  #include "fsck.h"
>  #include "util.h"
>  
> -static int convert_mark(uint8_t q, uint32_t *count)
> +static int gfs1_convert_mark(uint8_t q, uint32_t *count)
>  {
>  	switch(q) {
>  
> @@ -37,10 +37,62 @@ static int convert_mark(uint8_t q, uint32_t *count)
>  
>  	case gfs2_indir_blk:
>  	case gfs2_leaf_blk:
> +	/*case gfs2_meta_rgrp:*/
> +	case gfs2_jdata: /* gfs1 jdata blocks count as "metadata" and gfs1
> +			    metadata is marked the same as gfs2 inode in the
> +			    bitmap. */
> +	case gfs2_meta_eattr:
> +		count[3]++;
> +		return GFS2_BLKST_DINODE;
> +
> +	case gfs2_freemeta:
> +		count[4]++;
> +		return GFS2_BLKST_UNLINKED;
> +
> +	default:
> +		log_err( _("Invalid block type %d found\n"), q);
> +	}
> +	return -1;
> +}
> +
> +static int gfs2_convert_mark(uint8_t q, uint32_t *count)
> +{
> +	switch(q) {
> +
> +	case gfs2_meta_inval:
> +	case gfs2_inode_invalid:
> +		/* Convert invalid metadata to free blocks */
> +	case gfs2_block_free:
> +		count[0]++;
> +		return GFS2_BLKST_FREE;
> +
> +	case gfs2_block_used:
> +		count[2]++;
> +		return GFS2_BLKST_USED;
> +
> +	case gfs2_inode_dir:
> +	case gfs2_inode_file:
> +	case gfs2_inode_lnk:
> +	case gfs2_inode_device:
> +	case gfs2_jdata: /* gfs1 jdata blocks count as "metadata" and gfs1
> +			    metadata is marked the same as gfs2 inode in the
> +			    bitmap. */
> +	case gfs2_inode_fifo:
> +	case gfs2_inode_sock:
> +		count[1]++;
> +		return GFS2_BLKST_DINODE;
> +
> +	case gfs2_indir_blk:
> +	case gfs2_leaf_blk:
>  	case gfs2_meta_eattr:
>  		count[2]++;
>  		return GFS2_BLKST_USED;
>  
> +	case gfs2_freemeta:
> +		log_err( _("Invalid freemeta type %d found\n"), q);
> +		count[4]++;
> +		return -1;
> +
>  	default:
>  		log_err( _("Invalid block type %d found\n"), q);
>  	}
> @@ -71,7 +123,10 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
>  			return 0;
>  		q = block_type(block);
>  
> -		block_status = convert_mark(q, count);
> +		if (sdp->gfs1)
> +			block_status = gfs1_convert_mark(q, count);
> +		else
> +			block_status = gfs2_convert_mark(q, count);
>  
>  		/* If one node opens a file and another node deletes it, we
>  		   may be left with a block that appears to be "unlinked" in
> @@ -147,6 +202,7 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_list *rgp,
>  	struct gfs2_bitmap *bits;
>  	uint64_t rg_block = 0;
>  	int update = 0;
> +	struct gfs_rgrp *gfs1rg = (struct gfs_rgrp *)&rgp->rg;
>  
>  	for(i = 0; i < rgp->ri.ri_length; i++) {
>  		bits = &rgp->bits[i];
> @@ -178,7 +234,25 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_list *rgp,
>  		rgp->rg.rg_dinodes = count[1];
>  		update = 1;
>  	}
> -	if ((rgp->ri.ri_data - count[0] - count[1]) != count[2]) {
> +	if (sdp->gfs1 && gfs1rg->rg_usedmeta != count[3]) {
> +		log_err( _("RG #%llu (0x%llx) Used metadata count "
> +			   "inconsistent: is %u should be %u\n"),
> +			 (unsigned long long)rgp->ri.ri_addr,
> +			 (unsigned long long)rgp->ri.ri_addr,
> +			 gfs1rg->rg_usedmeta, count[3]);
> +		gfs1rg->rg_usedmeta = count[3];
> +		update = 1;
> +	}
> +	if (sdp->gfs1 && gfs1rg->rg_freemeta != count[4]) {
> +		log_err( _("RG #%llu (0x%llx) Free metadata count "
> +			   "inconsistent: is %u should be %u\n"),
> +			 (unsigned long long)rgp->ri.ri_addr,
> +			 (unsigned long long)rgp->ri.ri_addr,
> +			 gfs1rg->rg_freemeta, count[4]);
> +		gfs1rg->rg_freemeta = count[4];
> +		update = 1;
> +	}
> +	if (!sdp->gfs1 && (rgp->ri.ri_data - count[0] - count[1]) != count[2]) {
>  		/* FIXME not sure how to handle this case ATM - it
>  		 * means that the total number of blocks we've counted
>  		 * exceeds the blocks in the rg */
> @@ -189,7 +263,10 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_list *rgp,
>  		if (query( _("Update resource group counts? (y/n) "))) {
>  			log_warn( _("Resource group counts updated\n"));
>  			/* write out the rgrp */
> -			gfs2_rgrp_out(&rgp->rg, rgp->bh[0]);
> +			if (sdp->gfs1)
> +				gfs_rgrp_out(gfs1rg, rgp->bh[0]);
> +			else
> +				gfs2_rgrp_out(&rgp->rg, rgp->bh[0]);
>  		} else
>  			log_err( _("Resource group counts left inconsistent\n"));
>  	}
> @@ -205,7 +282,7 @@ int pass5(struct gfs2_sbd *sdp)
>  {
>  	osi_list_t *tmp;
>  	struct rgrp_list *rgp = NULL;
> -	uint32_t count[3];
> +	uint32_t count[5];
>  	uint64_t rg_count = 0;
>  
>  	/* Reconcile RG bitmaps with fsck bitmap */
> diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c
> index 911aad3..f452d29 100644
> --- a/gfs2/fsck/rgrepair.c
> +++ b/gfs2/fsck/rgrepair.c
> @@ -152,9 +152,8 @@ static uint64_t find_shortest_rgdist(struct gfs2_sbd *sdp,
>  	if (*first_rg_dist >= shortest_dist_btwn_rgs +
>  	    (shortest_dist_btwn_rgs / 4)) {
>  		/* read in the second RG index entry for this subd. */
> -		gfs2_readi(sdp->md.riinode, (char *)&buf,
> -			   sizeof(struct gfs2_rindex),
> -			   sizeof(struct gfs2_rindex));
> +		gfs2_readi(sdp->md.riinode, (char *)&buf, risize(sdp),
> +			   risize(sdp));
>  		gfs2_rindex_in(&tmpndx, (char *)&buf);
>  		if (tmpndx.ri_addr > sdp->sb_addr + 1) { /* sanity check */
>  			log_warn( _("rgrp 2 is damaged: getting dist from index: "));
> @@ -187,8 +186,13 @@ static uint64_t count_usedspace(struct gfs2_sbd *sdp, int first,
>  	unsigned int state;
>  
>  	/* Count up the free blocks in the bitmap */
> -	off = (first) ? sizeof(struct gfs2_rgrp) :
> -		sizeof(struct gfs2_meta_header);
> +	if (first) {
> +		if (sdp->gfs1)
> +			off = sizeof(struct gfs_rgrp);
> +		else
> +			off = sizeof(struct gfs2_rgrp);
> +	} else
> +		off = sizeof(struct gfs2_meta_header);
>  	bytes_to_check = sdp->bsize - off;
>  	for (x = 0; x < bytes_to_check; x++) {
>  		unsigned char *byte;
> @@ -685,12 +689,19 @@ static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rg,
>  			mh.mh_format = GFS2_FORMAT_RB;
>  			gfs2_meta_header_out(&mh, rg->bh[x]);
>  		} else {
> -			memset(&rg->rg, 0, sizeof(struct gfs2_rgrp));
> +			if (sdp->gfs1)
> +				memset(&rg->rg, 0, sizeof(struct gfs_rgrp));
> +			else
> +				memset(&rg->rg, 0, sizeof(struct gfs2_rgrp));
>  			rg->rg.rg_header.mh_magic = GFS2_MAGIC;
>  			rg->rg.rg_header.mh_type = GFS2_METATYPE_RG;
>  			rg->rg.rg_header.mh_format = GFS2_FORMAT_RG;
>  			rg->rg.rg_free = rg->ri.ri_data;
> -			gfs2_rgrp_out(&rg->rg, rg->bh[x]);
> +			if (sdp->gfs1)
> +				gfs_rgrp_out((struct gfs_rgrp *)&rg->rg,
> +					     rg->bh[x]);
> +			else
> +				gfs2_rgrp_out(&rg->rg, rg->bh[x]);
>  		}
>  		brelse(rg->bh[x]);
>  		rg->bh[x] = NULL;
> diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h
> index 106cca8..add97b4 100644
> --- a/gfs2/fsck/util.h
> +++ b/gfs2/fsck/util.h
> @@ -42,15 +42,15 @@ enum gfs2_mark_block {
>  	gfs2_inode_file    = (0x4),
>  
>  	gfs2_inode_lnk     = (0x5),
> -	gfs2_inode_device  = (0x6),
> -
> +	gfs2_inode_device  = (0x6), /* char or block device */
> +	gfs2_jdata         = (0x7), /* gfs journaled data blocks */
>  	gfs2_inode_fifo    = (0x8),
>  	gfs2_inode_sock    = (0x9),
>  
>  	gfs2_inode_invalid = (0xa),
>  	gfs2_meta_inval    = (0xb),
>  	gfs2_leaf_blk      = (0xc),
> -
> +	gfs2_freemeta      = (0xd), /* was: gfs2_meta_rgrp */
>  	gfs2_meta_eattr    = (0xe),
>  
>  	gfs2_bad_block     = (0xf), /* Contains at least one bad block */
> @@ -67,14 +67,14 @@ static const inline char *block_type_string(uint8_t q)
>  
>  		"symlink",
>  		"device",
> -		"",
> +		"journaled data",
>  		"fifo",
>  		"socket",
>  
>  		"invalid inode",
>  		"invalid meta",
>  		"dir leaf",
> -		"",
> +		"free metadata",
>  		"eattribute",
>  
>  		"bad"};
> @@ -85,30 +85,50 @@ static const inline char *block_type_string(uint8_t q)
>  
>  /* Must be kept in sync with gfs2_mark_block enum above. Blocks marked as
>     invalid or bad are considered metadata until actually freed. */
> -static inline int blockmap_to_bitmap(enum gfs2_mark_block m)
> +static inline int blockmap_to_bitmap(enum gfs2_mark_block m, int gfs1)
>  {
> -	static int bitmap_states[16] = {
> -		GFS2_BLKST_FREE,  /* free */
> -		GFS2_BLKST_USED,  /* data */
> -		GFS2_BLKST_USED,  /* indirect data or rgrp meta*/
> -		GFS2_BLKST_DINODE,  /* directory */
> -		GFS2_BLKST_DINODE,  /* file */
> -
> -		GFS2_BLKST_DINODE,  /* symlink */
> -		GFS2_BLKST_DINODE,  /* block or char device */
> -		GFS2_BLKST_USED,    /* reserved */
> -		GFS2_BLKST_DINODE,  /* fifo */
> -		GFS2_BLKST_DINODE,  /* socket */
> -
> -		GFS2_BLKST_FREE,  /* invalid inode */
> -		GFS2_BLKST_FREE,  /* invalid meta */
> -		GFS2_BLKST_USED,  /* dir leaf */
> -		GFS2_BLKST_UNLINKED,  /* unused */
> -		GFS2_BLKST_USED,  /* eattribute */
> -
> -		GFS2_BLKST_USED,  /* bad */
> -	};
> -	return bitmap_states[m];
> +	static int bitmap_states[2][16] = {
> +		/* ---------------------- gfs2 ------------------------------*/
> +		{GFS2_BLKST_FREE,  /* free */
> +		 GFS2_BLKST_USED,  /* data */
> +		 GFS2_BLKST_USED,  /* indirect data or rgrp meta */
> +		 GFS2_BLKST_DINODE,  /* directory */
> +		 GFS2_BLKST_DINODE,  /* file */
> +
> +		 GFS2_BLKST_DINODE,  /* symlink */
> +		 GFS2_BLKST_DINODE,  /* block or char device */
> +		 GFS2_BLKST_USED,    /* journaled data */
> +		 GFS2_BLKST_DINODE,  /* fifo */
> +		 GFS2_BLKST_DINODE,  /* socket */
> +
> +		 GFS2_BLKST_FREE,  /* invalid inode */
> +		 GFS2_BLKST_FREE,  /* invalid meta */
> +		 GFS2_BLKST_USED,  /* dir leaf */
> +		 GFS2_BLKST_UNLINKED,  /* GFS unlinked metadata */
> +		 GFS2_BLKST_USED,  /* eattribute */
> +
> +		 GFS2_BLKST_USED},  /* bad */
> +		/* ---------------------- gfs1 ----------------------------- */
> +		{GFS2_BLKST_FREE,  /* free */
> +		 GFS2_BLKST_USED,  /* data */
> +		 GFS2_BLKST_DINODE,  /* indirect data or rgrp meta*/
> +		 GFS2_BLKST_DINODE,  /* directory */
> +		 GFS2_BLKST_DINODE,  /* file */
> +
> +		 GFS2_BLKST_DINODE,  /* symlink */
> +		 GFS2_BLKST_DINODE,  /* block or char device */
> +		 GFS2_BLKST_DINODE,  /* journaled data */
> +		 GFS2_BLKST_DINODE,  /* fifo */
> +		 GFS2_BLKST_DINODE,  /* socket */
> +
> +		 GFS2_BLKST_FREE,  /* invalid inode */
> +		 GFS2_BLKST_FREE,  /* invalid meta */
> +		 GFS2_BLKST_DINODE,  /* dir leaf */
> +		 GFS2_BLKST_UNLINKED, /* GFS unlinked metadata */
> +		 GFS2_BLKST_DINODE,  /* eattribute */
> +
> +		 GFS2_BLKST_USED}};  /* bad */
> +	return bitmap_states[gfs1][m];
>  }
>  
>  extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size,
> @@ -116,5 +136,4 @@ extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size,
>  extern void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il);
>  extern int gfs2_blockmap_set(struct gfs2_bmap *il, uint64_t block,
>  			     enum gfs2_mark_block mark);
> -
>  #endif /* __UTIL_H__ */
> diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
> index 7ec38a5..04de28f 100644
> --- a/gfs2/libgfs2/libgfs2.h
> +++ b/gfs2/libgfs2/libgfs2.h
> @@ -724,6 +724,9 @@ extern int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block,
>  			     int first);
>  extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
>  				 uint64_t *block, uint32_t type, int first);
> +extern int gfs2_next_rg_freemeta(struct rgrp_list *rgd, uint64_t *block,
> +				 int first);
> +
>  /* super.c */
>  extern int check_sb(struct gfs2_sb *sb, int allow_gfs);
>  extern int read_sb(struct gfs2_sbd *sdp, int allow_gfs);
> diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
> index 8b2c9d9..e8a8c65 100644
> --- a/gfs2/libgfs2/structures.c
> +++ b/gfs2/libgfs2/structures.c
> @@ -502,39 +502,50 @@ int gfs2_check_meta(struct gfs2_buffer_head *bh, int type)
>   *
>   * Returns: 0 on success, -1 when finished
>   */
> -int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first)
> +static int __gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block,
> +			       int first, unsigned char state)
>  {
>  	struct gfs2_bitmap *bits = NULL;
>  	uint32_t length = rgd->ri.ri_length;
> -	uint32_t blk = (first)? 0: (uint32_t)((*block+1)-rgd->ri.ri_data0);
> +	uint32_t blk = (first)? 0: (uint32_t)((*block + 1) - rgd->ri.ri_data0);
>  	int i;
>  
>  	if(!first && (*block < rgd->ri.ri_data0)) {
>  		log_err("next_rg_meta:  Start block is outside rgrp bounds.\n");
>  		exit(1);
>  	}
> -	for(i=0; i < length; i++){
> +	for(i = 0; i < length; i++){
>  		bits = &rgd->bits[i];
> -		if(blk < bits->bi_len*GFS2_NBBY)
> +		if (blk < bits->bi_len * GFS2_NBBY)
>  			break;
> -		blk -= bits->bi_len*GFS2_NBBY;
> +		blk -= bits->bi_len * GFS2_NBBY;
>  	}
>  	for(; i < length; i++){
>  		bits = &rgd->bits[i];
>  		blk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data +
> -				  bits->bi_offset, bits->bi_len, blk,
> -				  GFS2_BLKST_DINODE);
> +				  bits->bi_offset, bits->bi_len, blk, state);
>  		if(blk != BFITNOENT){
> -			*block = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0;
> +			*block = blk + (bits->bi_start * GFS2_NBBY) +
> +				rgd->ri.ri_data0;
>  			break;
>  		}
> -		blk=0;
> +		blk = 0;
>  	}
>  	if(i == length)
>  		return -1;
>  	return 0;
>  }
>  
> +int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first)
> +{
> +	return __gfs2_next_rg_meta(rgd, block, first, GFS2_BLKST_DINODE);
> +}
> +
> +int gfs2_next_rg_freemeta(struct rgrp_list *rgd, uint64_t *block, int first)
> +{
> +	return __gfs2_next_rg_meta(rgd, block, first, GFS2_BLKST_UNLINKED);
> +}
> +
>  /**
>   * next_rg_metatype
>   * @rgd:

Generally though I think this patch set is good and heading in the right
direction. It looks like a number of the patches are nice cleanups and
fairly trivial, so that they should be merged right away.

So also, this is an ACK for all the otherwise unacked patches in this
series.

I wonder whether we should start collecting some tables in libgfs2 in
order to describe various aspects of the filesystem. For example there
seems to be a lot of converting of block types. We could have a table to
convert block types for gfs1/gfs2 directly in disk byte order into a
single internal representation so that a number of tests would just
become a dereference of that table.

It would also be good to eliminate any gfs1 structure which is identical
to the equiv. gfs2 structure and just use the gfs2 structure directly
where possible. That is perhaps something we need to document in the
header file (i.e. where the differences are),

Steve.





More information about the Cluster-devel mailing list