Blame gfs2/fsck/rgrepair.c

Packit 6ef888
#include "clusterautoconfig.h"
Packit 6ef888
Packit 6ef888
#include <unistd.h>
Packit 6ef888
#include <inttypes.h>
Packit 6ef888
#include <stdio.h>
Packit 6ef888
#include <stdint.h>
Packit 6ef888
#include <stdlib.h>
Packit 6ef888
#include <string.h>
Packit 6ef888
#include <errno.h>
Packit 6ef888
#include <libintl.h>
Packit 6ef888
#define _(String) gettext(String)
Packit 6ef888
Packit 6ef888
#include <logging.h>
Packit 6ef888
#include "libgfs2.h"
Packit 6ef888
#include "osi_list.h"
Packit 6ef888
#include "fsck.h"
Packit 6ef888
#include "fs_recovery.h"
Packit 6ef888
Packit 6ef888
int rindex_modified = FALSE;
Packit 6ef888
struct special_blocks false_rgrps;
Packit 6ef888
Packit 6ef888
#define BAD_RG_PERCENT_TOLERANCE 11
Packit 6ef888
#define AWAY_FROM_BITMAPS 0x1000
Packit 6ef888
#define MAX_RGSEGMENTS 20
Packit 6ef888
Packit 6ef888
#define ri_equal(ondisk, expected, field) (ondisk.field == expected.field)
Packit 6ef888
Packit 6ef888
#define ri_compare(rg, ondisk, expected, field, fmt, type)	\
Packit 6ef888
	if (ondisk.field != expected.field) { \
Packit 6ef888
		log_warn( _("rindex #%d " #field " discrepancy: index 0x%" \
Packit 6ef888
			    fmt	" != expected: 0x%" fmt "\n"),		\
Packit 6ef888
			  rg + 1, (type)ondisk.field, (type)expected.field);	\
Packit 6ef888
		ondisk.field = expected.field;				\
Packit 6ef888
		rindex_modified = TRUE;					\
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * find_journal_entry_rgs - find all RG blocks within all journals
Packit 6ef888
 *
Packit 6ef888
 * Since Resource Groups (RGs) are journaled, it is not uncommon for them
Packit 6ef888
 * to appear inside a journal.  But if there is severe damage to the rindex
Packit 6ef888
 * file or some of the RGs, we may need to hunt and peck for RGs and in that
Packit 6ef888
 * case, we don't want to mistake these blocks that look just a real RG
Packit 6ef888
 * for a real RG block.  These are "fake" RGs that need to be ignored for
Packit 6ef888
 * the purposes of finding where things are.
Packit 6ef888
 *
Packit 6ef888
 * NOTE: This function assumes that the jindex and journals have been read in,
Packit 6ef888
 *       which isn't often the case. Normally the rindex needs to be read in
Packit 6ef888
 *       first. If the rindex is damaged, that's not an option.
Packit 6ef888
 */
Packit 6ef888
static void find_journaled_rgs(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	int j, new = 0;
Packit 6ef888
	unsigned int jblocks;
Packit 6ef888
	uint64_t b, dblock;
Packit 6ef888
	struct gfs2_inode *ip;
Packit 6ef888
	struct gfs2_buffer_head *bh;
Packit 6ef888
	int false_count;
Packit 6ef888
Packit 6ef888
	osi_list_init(&false_rgrps.list);
Packit 6ef888
	for (j = 0; j < sdp->md.journals; j++) {
Packit 6ef888
		ip = sdp->md.journal[j];
Packit 6ef888
		log_debug(_("Checking for rgrps in journal%d which starts "
Packit 6ef888
			    "at block 0x%llx.\n"), j,
Packit 6ef888
			  (unsigned long long)ip->i_di.di_num.no_addr);
Packit 6ef888
		jblocks = ip->i_di.di_size / sdp->sd_sb.sb_bsize;
Packit 6ef888
		false_count = 0;
Packit 6ef888
		for (b = 0; b < jblocks; b++) {
Packit 6ef888
			block_map(ip, b, &new, &dblock, NULL, 0);
Packit 6ef888
			if (!dblock)
Packit 6ef888
				break;
Packit 6ef888
			bh = bread(sdp, dblock);
Packit 6ef888
			if (!gfs2_check_meta(bh, GFS2_METATYPE_RG)) {
Packit 6ef888
				/* False rgrp found at block dblock */
Packit 6ef888
				false_count++;
Packit 6ef888
				gfs2_special_set(&false_rgrps, dblock);
Packit 6ef888
			}
Packit 6ef888
			brelse(bh);
Packit 6ef888
		}
Packit 6ef888
		log_debug("\n%d false positives identified.\n", false_count);
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int is_false_rg(uint64_t block)
Packit 6ef888
{
Packit 6ef888
	if (blockfind(&false_rgrps, block))
Packit 6ef888
		return 1;
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * find_shortest_rgdist - hunt and peck for the shortest distance between RGs.
Packit 6ef888
 *
Packit 6ef888
 * Sample several of them because an RG that's been blasted may
Packit 6ef888
 * look like twice the distance.  If we can find 6 of them, that
Packit 6ef888
 * should be enough to figure out the correct layout.
Packit 6ef888
 * This also figures out first_rg_dist since that's always different.
Packit 6ef888
 *
Packit 6ef888
 * This function was revised to return the number of segments, usually 2.
Packit 6ef888
 * The shortest distance is now returned in the highest entry in rg_dist
Packit 6ef888
 */
Packit 6ef888
static int find_shortest_rgdist(struct gfs2_sbd *sdp, uint64_t *dist_array,
Packit 6ef888
				int *dist_cnt)
Packit 6ef888
{
Packit 6ef888
	uint64_t blk, block_last_rg, shortest_dist_btwn_rgs;
Packit 6ef888
	struct gfs2_buffer_head *bh;
Packit 6ef888
	int rgs_sampled = 0;
Packit 6ef888
	struct gfs2_rindex buf, tmpndx;
Packit 6ef888
	uint64_t initial_first_rg_dist;
Packit 6ef888
	int gsegment = 0;
Packit 6ef888
	int is_rgrp;
Packit 6ef888
Packit 6ef888
	/* Figure out if there are any RG-looking blocks in the journal we
Packit 6ef888
	   need to ignore. */
Packit 6ef888
	find_journaled_rgs(sdp);
Packit 6ef888
Packit 6ef888
	initial_first_rg_dist = dist_array[0] = block_last_rg =
Packit 6ef888
		LGFS2_SB_ADDR(sdp) + 1;
Packit 6ef888
	shortest_dist_btwn_rgs = sdp->device.length;
Packit 6ef888
Packit 6ef888
	for (blk = LGFS2_SB_ADDR(sdp) + 1; blk < sdp->device.length; blk++) {
Packit 6ef888
		uint64_t dist;
Packit 6ef888
Packit 6ef888
		if (blk == LGFS2_SB_ADDR(sdp) + 1)
Packit 6ef888
			is_rgrp = 1;
Packit 6ef888
		else if (is_false_rg(blk))
Packit 6ef888
			is_rgrp = 0;
Packit 6ef888
		else {
Packit 6ef888
			bh = bread(sdp, blk);
Packit 6ef888
			is_rgrp = (gfs2_check_meta(bh, GFS2_METATYPE_RG) == 0);
Packit 6ef888
			brelse(bh);
Packit 6ef888
		}
Packit 6ef888
		if (!is_rgrp) {
Packit 6ef888
			if (rgs_sampled >= 6) {
Packit 6ef888
				uint64_t nblk;
Packit 6ef888
Packit 6ef888
				log_info(_("rgrp not found at block 0x%llx. "
Packit 6ef888
					   "Last found rgrp was 0x%llx. "
Packit 6ef888
					   "Checking the next one.\n"),
Packit 6ef888
					 (unsigned long long)blk,
Packit 6ef888
					 (unsigned long long)block_last_rg);
Packit 6ef888
				/* check for just a damaged rgrp */
Packit 6ef888
				nblk = blk + dist_array[gsegment];
Packit 6ef888
				if (is_false_rg(nblk)) {
Packit 6ef888
					is_rgrp = 0;
Packit 6ef888
				} else {
Packit 6ef888
					bh = bread(sdp, nblk);
Packit 6ef888
					is_rgrp = (((gfs2_check_meta(bh,
Packit 6ef888
						GFS2_METATYPE_RG) == 0)));
Packit 6ef888
					brelse(bh);
Packit 6ef888
				}
Packit 6ef888
				if (is_rgrp) {
Packit 6ef888
					log_info(_("Next rgrp is intact, so "
Packit 6ef888
						   "this one is damaged.\n"));
Packit 6ef888
					blk = nblk - 1;
Packit 6ef888
					dist_cnt[gsegment]++;
Packit 6ef888
					continue;
Packit 6ef888
				}
Packit 6ef888
				log_info(_("Looking for new segment.\n"));
Packit 6ef888
				blk -= 16;
Packit 6ef888
				rgs_sampled = 0;
Packit 6ef888
				shortest_dist_btwn_rgs = sdp->device.length;
Packit 6ef888
				/* That last one didn't pan out, so: */
Packit 6ef888
				dist_cnt[gsegment]--;
Packit 6ef888
				gsegment++;
Packit 6ef888
				if (gsegment >= MAX_RGSEGMENTS)
Packit 6ef888
					break;
Packit 6ef888
			}
Packit 6ef888
			if ((blk - block_last_rg) > (524288 * 2)) {
Packit 6ef888
				log_info(_("No rgrps were found within 4GB "
Packit 6ef888
					   "of the last rgrp. Must be the "
Packit 6ef888
					   "end of the file system.\n"));
Packit 6ef888
Packit 6ef888
				break;
Packit 6ef888
			}
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
Packit 6ef888
		dist_cnt[gsegment]++;
Packit 6ef888
		if (rgs_sampled >= 6) {
Packit 6ef888
			block_last_rg = blk;
Packit 6ef888
			blk += dist_array[gsegment] - 1; /* prev value in
Packit 6ef888
							    array minus 1. */
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
		log_info(_("segment %d: rgrp found at block 0x%llx\n"),
Packit 6ef888
			 gsegment + 1, (unsigned long long)blk);
Packit 6ef888
		dist = blk - block_last_rg;
Packit 6ef888
		if (blk > LGFS2_SB_ADDR(sdp) + 1) { /* not the very first rgrp */
Packit 6ef888
Packit 6ef888
			log_info("dist 0x%llx = 0x%llx - 0x%llx ",
Packit 6ef888
				 (unsigned long long)dist,
Packit 6ef888
				 (unsigned long long)blk,
Packit 6ef888
				 (unsigned long long)block_last_rg);
Packit 6ef888
			/**
Packit 6ef888
			 * We found an RG.  Check to see if we need to set the
Packit 6ef888
			 * first_rg_dist based on whether it is still at its
Packit 6ef888
			 * initial value (i.e. the fs.)  The first rg distance
Packit 6ef888
			 * is different from the rest because of the
Packit 6ef888
			 * superblock and 64K dead space.
Packit 6ef888
			 **/
Packit 6ef888
			if (dist_array[0] == initial_first_rg_dist) {
Packit 6ef888
				dist_array[0] = dist;
Packit 6ef888
				dist_cnt[0] = 1;
Packit 6ef888
				rgs_sampled = 0;
Packit 6ef888
			}
Packit 6ef888
			if (dist < shortest_dist_btwn_rgs) {
Packit 6ef888
				shortest_dist_btwn_rgs = dist;
Packit 6ef888
				log_info( _("(shortest so far)"));
Packit 6ef888
			}
Packit 6ef888
			log_info("\n");
Packit 6ef888
			if (++rgs_sampled == 6) {
Packit 6ef888
				dist_array[gsegment] = shortest_dist_btwn_rgs;
Packit 6ef888
				log_info(_("Settled on distance 0x%llx for "
Packit 6ef888
					   "segment %d\n"),
Packit 6ef888
					 (unsigned long long)
Packit 6ef888
					 dist_array[gsegment], gsegment + 1);
Packit 6ef888
			}
Packit 6ef888
		} else {
Packit 6ef888
			gsegment++;
Packit 6ef888
			if (gsegment >= MAX_RGSEGMENTS)
Packit 6ef888
				break;
Packit 6ef888
		}
Packit 6ef888
		block_last_rg = blk;
Packit 6ef888
		if (rgs_sampled < 6)
Packit 6ef888
			blk += 250; /* skip ahead for performance */
Packit 6ef888
		else
Packit 6ef888
			blk += shortest_dist_btwn_rgs - 1;
Packit 6ef888
	}
Packit 6ef888
	if (gsegment >= MAX_RGSEGMENTS) {
Packit 6ef888
		log_err(_("Maximum number of rgrp grow segments reached.\n"));
Packit 6ef888
		log_err(_("This file system has more than %d resource "
Packit 6ef888
			  "group segments.\n"), MAX_RGSEGMENTS);
Packit 6ef888
	}
Packit 6ef888
	/* -------------------------------------------------------------- */
Packit 6ef888
	/* Sanity-check our first_rg_dist. If RG #2 got nuked, the        */
Packit 6ef888
	/* first_rg_dist would measure from #1 to #3, which would be bad. */
Packit 6ef888
	/* We need to take remedial measures to fix it (from the index).  */
Packit 6ef888
	/* -------------------------------------------------------------- */
Packit 6ef888
	if (*dist_array >= shortest_dist_btwn_rgs +
Packit 6ef888
	    (shortest_dist_btwn_rgs / 4)) {
Packit 6ef888
		/* read in the second RG index entry for this subd. */
Packit 6ef888
		gfs2_readi(sdp->md.riinode, (char *)&buf,
Packit 6ef888
			   sizeof(struct gfs2_rindex),
Packit 6ef888
			   sizeof(struct gfs2_rindex));
Packit 6ef888
		gfs2_rindex_in(&tmpndx, (char *)&buf;;
Packit 6ef888
		if (tmpndx.ri_addr > LGFS2_SB_ADDR(sdp) + 1) { /* sanity check */
Packit 6ef888
			log_warn( _("rgrp 2 is damaged: getting dist from index: "));
Packit 6ef888
			*dist_array = tmpndx.ri_addr - (LGFS2_SB_ADDR(sdp) + 1);
Packit 6ef888
			log_warn("0x%llx\n", (unsigned long long)*dist_array);
Packit 6ef888
		} else {
Packit 6ef888
			log_warn( _("rgrp index 2 is damaged: extrapolating dist: "));
Packit 6ef888
			*dist_array = sdp->device.length - (sdp->rgrps - 1) *
Packit 6ef888
				(sdp->device.length / sdp->rgrps);
Packit 6ef888
			log_warn("0x%llx\n", (unsigned long long)*dist_array);
Packit 6ef888
		}
Packit 6ef888
		log_debug( _("Adjusted first rgrp distance: 0x%llx\n"),
Packit 6ef888
			   (unsigned long long)*dist_array);
Packit 6ef888
	} /* if first RG distance is within tolerance */
Packit 6ef888
Packit 6ef888
	gfs2_special_free(&false_rgrps);
Packit 6ef888
	return gsegment;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * count_usedspace - count the used bits in a rgrp bitmap buffer
Packit 6ef888
 */
Packit 6ef888
static uint64_t count_usedspace(struct gfs2_sbd *sdp, int first,
Packit 6ef888
				struct gfs2_buffer_head *bh)
Packit 6ef888
{
Packit 6ef888
	int off, x, y, bytes_to_check;
Packit 6ef888
	uint32_t rg_used = 0;
Packit 6ef888
	unsigned int state;
Packit 6ef888
Packit 6ef888
	/* Count up the free blocks in the bitmap */
Packit 6ef888
	if (first) {
Packit 6ef888
		if (sdp->gfs1)
Packit 6ef888
			off = sizeof(struct gfs_rgrp);
Packit 6ef888
		else
Packit 6ef888
			off = sizeof(struct gfs2_rgrp);
Packit 6ef888
	} else
Packit 6ef888
		off = sizeof(struct gfs2_meta_header);
Packit 6ef888
	bytes_to_check = sdp->bsize - off;
Packit 6ef888
	for (x = 0; x < bytes_to_check; x++) {
Packit 6ef888
		unsigned char *byte;
Packit 6ef888
Packit 6ef888
		byte = (unsigned char *)&bh->b_data[off + x];
Packit 6ef888
		if (*byte == 0x55) {
Packit 6ef888
			rg_used += GFS2_NBBY;
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
		if (*byte == 0x00)
Packit 6ef888
			continue;
Packit 6ef888
		for (y = 0; y < GFS2_NBBY; y++) {
Packit 6ef888
			state = (*byte >> (GFS2_BIT_SIZE * y)) & GFS2_BIT_MASK;
Packit 6ef888
			if (state == GFS2_BLKST_FREE ||
Packit 6ef888
			    state == GFS2_BLKST_UNLINKED)
Packit 6ef888
				continue;
Packit 6ef888
			rg_used++;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	return rg_used;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * find_next_rgrp_dist - find the distance to the next rgrp
Packit 6ef888
 *
Packit 6ef888
 * This function is only called if the rgrps are determined to be on uneven
Packit 6ef888
 * boundaries.  In a normal gfs2 file system, after mkfs.gfs2, all the
Packit 6ef888
 * rgrps but the first and second one will be the same distance from the
Packit 6ef888
 * previous rgrp.  (The first rgrp will predictably be after the superblock
Packit 6ef888
 * and the second one will be adjusted based on the number 64KB skipped
Packit 6ef888
 * at the start of the file system.)  The only way we can deviate from that
Packit 6ef888
 * pattern is if the user did gfs_grow on a gfs1 file system, then converted
Packit 6ef888
 * it to gfs2 using gfs2_convert.
Packit 6ef888
 *
Packit 6ef888
 * This function finds the distance to the next rgrp for these cases.
Packit 6ef888
 */
Packit 6ef888
static uint64_t find_next_rgrp_dist(struct gfs2_sbd *sdp, uint64_t blk,
Packit 6ef888
				    struct rgrp_tree *prevrgd)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n, *next = NULL;
Packit 6ef888
	uint64_t rgrp_dist = 0, used_blocks, block, next_block, twogigs;
Packit 6ef888
	struct rgrp_tree *rgd = NULL, *next_rgd;
Packit 6ef888
	struct gfs2_buffer_head *bh;
Packit 6ef888
	struct gfs2_meta_header mh;
Packit 6ef888
	int first, length, b, found;
Packit 6ef888
	uint64_t mega_in_blocks;
Packit 6ef888
	uint32_t free_blocks;
Packit 6ef888
Packit 6ef888
	for (n = osi_first(&sdp->rgtree); n; n = next) {
Packit 6ef888
		next = osi_next(n);
Packit 6ef888
		rgd = (struct rgrp_tree *)n;
Packit 6ef888
		if (rgd->ri.ri_addr == blk)
Packit 6ef888
			break;
Packit 6ef888
	}
Packit 6ef888
	if (rgd && n && osi_next(n) && rgd->ri.ri_addr == blk) {
Packit 6ef888
		n = osi_next(n);
Packit 6ef888
		next_rgd = (struct rgrp_tree *)n;
Packit 6ef888
		rgrp_dist = next_rgd->ri.ri_addr - rgd->ri.ri_addr;
Packit 6ef888
		return rgrp_dist;
Packit 6ef888
	}
Packit 6ef888
	mega_in_blocks = (1024 * 1024)  / sdp->bsize;
Packit 6ef888
	twogigs = (uint64_t)mega_in_blocks * 2048;
Packit 6ef888
	/* Unfortunately, if we fall through to here we can't trust the
Packit 6ef888
	   rindex.  So we have to analyze the current rgrp to figure out
Packit 6ef888
	   the bare minimum block number where it ends. If we don't have
Packit 6ef888
	   rindex, all we know about this rgrp is what's on disk: its
Packit 6ef888
	   rg_free.  If we analyze the rgrp's bitmap and the bitmaps that
Packit 6ef888
	   follow, we can figure out how many bits are used.  If we add
Packit 6ef888
	   rg_free, we get the total number of blocks this rgrp
Packit 6ef888
	   represents.  After that should be the next rgrp, but it may
Packit 6ef888
	   skip a few blocks (hopefully no more than 4).  */
Packit 6ef888
	used_blocks = 0;
Packit 6ef888
	length = 0;
Packit 6ef888
	block = prevrgd->ri.ri_addr;
Packit 6ef888
	first = 1;
Packit 6ef888
	found = 0;
Packit 6ef888
	while (1) {
Packit 6ef888
		if (block >= sdp->device.length)
Packit 6ef888
			break;
Packit 6ef888
		if (block >= prevrgd->ri.ri_addr + twogigs)
Packit 6ef888
			break;
Packit 6ef888
		bh = bread(sdp, block);
Packit 6ef888
		gfs2_meta_header_in(&mh, bh->b_data);
Packit 6ef888
		if ((mh.mh_magic != GFS2_MAGIC) ||
Packit 6ef888
		    (first && mh.mh_type != GFS2_METATYPE_RG) ||
Packit 6ef888
		    (!first && mh.mh_type != GFS2_METATYPE_RB)) {
Packit 6ef888
			brelse(bh);
Packit 6ef888
			break;
Packit 6ef888
		}
Packit 6ef888
		if (first) {
Packit 6ef888
			struct gfs2_rgrp *rg;
Packit 6ef888
Packit 6ef888
			rg = (struct gfs2_rgrp *)bh->b_data;
Packit 6ef888
			free_blocks = be32_to_cpu(rg->rg_free);
Packit 6ef888
		}
Packit 6ef888
		used_blocks += count_usedspace(sdp, first, bh);
Packit 6ef888
		first = 0;
Packit 6ef888
		block++;
Packit 6ef888
		length++;
Packit 6ef888
		brelse(bh);
Packit 6ef888
		/* Check if this distance points to an rgrp:
Packit 6ef888
		   We have to look for blocks that resemble rgrps and bitmaps.
Packit 6ef888
		   If they do, we need to count blocks used and free and see
Packit 6ef888
		   if adding that number of free blocks accounts for the
Packit 6ef888
		   next rgrp we find. Otherwise, you could have a length of
Packit 6ef888
		   6 with additional user blocks that just happen to look like
Packit 6ef888
		   bitmap blocks.  Count them all as bitmaps and you'll be
Packit 6ef888
		   hopelessly lost. */
Packit 6ef888
		rgrp_dist = used_blocks + free_blocks + length;
Packit 6ef888
		next_block = prevrgd->ri.ri_addr + rgrp_dist;
Packit 6ef888
		/* Now we account for block rounding done by mkfs.gfs2 */
Packit 6ef888
		for (b = 0; b <= length + GFS2_NBBY; b++) {
Packit 6ef888
			if (next_block >= sdp->device.length)
Packit 6ef888
				break;
Packit 6ef888
			bh = bread(sdp, next_block + b);
Packit 6ef888
			gfs2_meta_header_in(&mh, bh->b_data);
Packit 6ef888
			brelse(bh);
Packit 6ef888
			if (mh.mh_magic == GFS2_MAGIC) {
Packit 6ef888
				if (mh.mh_type == GFS2_METATYPE_RG) {
Packit 6ef888
					found = 1;
Packit 6ef888
					break;
Packit 6ef888
				}
Packit 6ef888
				/* if the first thing we find is a bitmap,
Packit 6ef888
				   there must be a damaged rgrp on the
Packit 6ef888
				   previous block. */
Packit 6ef888
				if (mh.mh_type == GFS2_METATYPE_RB) {
Packit 6ef888
					found = 1;
Packit 6ef888
					rgrp_dist--;
Packit 6ef888
					break;
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
			rgrp_dist++;
Packit 6ef888
		}
Packit 6ef888
		if (found) {
Packit 6ef888
			log_info( _("rgrp found at 0x%llx, length=%d, "
Packit 6ef888
				    "used=%llu, free=%d\n"),
Packit 6ef888
				  prevrgd->ri.ri_addr, length,
Packit 6ef888
				  (unsigned long long)used_blocks,
Packit 6ef888
				  free_blocks);
Packit 6ef888
			break;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	return rgrp_dist;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * hunt_and_peck - find the distance to the next rgrp
Packit 6ef888
 *
Packit 6ef888
 * This function is only called if the rgrps are determined to be on uneven
Packit 6ef888
 * boundaries, and also corrupt.  So we have to go out searching for one.
Packit 6ef888
 */
Packit 6ef888
static uint64_t hunt_and_peck(struct gfs2_sbd *sdp, uint64_t blk,
Packit 6ef888
			      struct rgrp_tree *prevrgd, uint64_t last_bump)
Packit 6ef888
{
Packit 6ef888
	uint64_t rgrp_dist = 0, block, twogigs, last_block, last_meg;
Packit 6ef888
	struct gfs2_buffer_head *bh;
Packit 6ef888
	struct gfs2_meta_header mh;
Packit 6ef888
	int b, mega_in_blocks;
Packit 6ef888
Packit 6ef888
	/* Skip ahead the previous amount: we might get lucky.
Packit 6ef888
	   If we're close to the end of the device, take the rest. */
Packit 6ef888
	if (gfs2_check_range(sdp, blk + last_bump))
Packit 6ef888
		return sdp->fssize - blk;
Packit 6ef888
Packit 6ef888
	bh = bread(sdp, blk + last_bump);
Packit 6ef888
	gfs2_meta_header_in(&mh, bh->b_data);
Packit 6ef888
	brelse(bh);
Packit 6ef888
	if (mh.mh_magic == GFS2_MAGIC && mh.mh_type == GFS2_METATYPE_RG) {
Packit 6ef888
		log_info( _("rgrp found at 0x%llx, length=%lld\n"),
Packit 6ef888
			  (unsigned long long)blk + last_bump,
Packit 6ef888
			  (unsigned long long)last_bump);
Packit 6ef888
		return last_bump;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	rgrp_dist = AWAY_FROM_BITMAPS; /* Get away from any bitmaps
Packit 6ef888
					  associated with the previous rgrp */
Packit 6ef888
	block = prevrgd->ri.ri_addr + rgrp_dist;
Packit 6ef888
	/* Now we account for block rounding done by mkfs.gfs2.  A rgrp can
Packit 6ef888
	   be at most 2GB in size, so that's where we call it. We do somewhat
Packit 6ef888
	   obscure math here to avoid integer overflows. */
Packit 6ef888
	mega_in_blocks = (1024 * 1024)  / sdp->bsize;
Packit 6ef888
	twogigs = 2048 * mega_in_blocks;
Packit 6ef888
	if (block + twogigs <= sdp->fssize) {
Packit 6ef888
		last_block = twogigs;
Packit 6ef888
		last_meg = 0;
Packit 6ef888
	} else {
Packit 6ef888
		/* There won't be a rgrp in the last megabyte. */
Packit 6ef888
		last_block = sdp->fssize - block - mega_in_blocks;
Packit 6ef888
		last_meg = mega_in_blocks;
Packit 6ef888
	}
Packit 6ef888
	for (b = AWAY_FROM_BITMAPS; b < last_block; b++) {
Packit 6ef888
		bh = bread(sdp, block + b);
Packit 6ef888
		gfs2_meta_header_in(&mh, bh->b_data);
Packit 6ef888
		brelse(bh);
Packit 6ef888
		if (mh.mh_magic == GFS2_MAGIC) {
Packit 6ef888
			if (mh.mh_type == GFS2_METATYPE_RG)
Packit 6ef888
				break;
Packit 6ef888
			/* if the first thing we find is a bitmap, there must
Packit 6ef888
			   be a damaged rgrp on the previous block. */
Packit 6ef888
			if (mh.mh_type == GFS2_METATYPE_RB) {
Packit 6ef888
				rgrp_dist--;
Packit 6ef888
				break;
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		rgrp_dist++;
Packit 6ef888
	}
Packit 6ef888
	return rgrp_dist + last_meg;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * gfs2_rindex_rebuild - rebuild a corrupt Resource Group (RG) index manually
Packit 6ef888
 *                        where trust_lvl == distrust
Packit 6ef888
 *
Packit 6ef888
 * If this routine is called, it means we have RGs in odd/unexpected places,
Packit 6ef888
 * and there is a corrupt RG or RG index entry.  It also means we can't trust
Packit 6ef888
 * the RG index to be sane, and the RGs don't agree with how mkfs would have
Packit 6ef888
 * built them by default.  So we have no choice but to go through and count
Packit 6ef888
 * them by hand.  We've tried twice to recover the RGs and RG index, and
Packit 6ef888
 * failed, so this is our last chance to remedy the situation.
Packit 6ef888
 *
Packit 6ef888
 * This routine tries to minimize performance impact by:
Packit 6ef888
 * 1. Skipping through the filesystem at known increments when possible.
Packit 6ef888
 * 2. Shuffle through every block when RGs are not found at the predicted
Packit 6ef888
 *    locations.
Packit 6ef888
 *
Packit 6ef888
 * Note: A GFS2 filesystem differs from a GFS1 file system in that there will
Packit 6ef888
 * only be ONE chunk (i.e. no artificial subdevices on either size of the
Packit 6ef888
 * journals).  The journals and even the rindex are kept as part of the file
Packit 6ef888
 * system, so we need to rebuild that information by hand.  Also, with GFS1,
Packit 6ef888
 * the different chunks ("subdevices") could have different RG sizes, which
Packit 6ef888
 * made for quite a mess when trying to recover RGs.  GFS2 always uses the
Packit 6ef888
 * same RG size determined by the original mkfs, so recovery is easier.
Packit 6ef888
 *
Packit 6ef888
 * If "gfs_grow" is specified the file system was most likely converted
Packit 6ef888
 * from gfs1 to gfs2 after a gfs_grow operation.  In that case, the rgrps
Packit 6ef888
 * will not be on predictable boundaries.
Packit 6ef888
 */
Packit 6ef888
static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, int *num_rgs,
Packit 6ef888
			       int gfs_grow)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n, *next = NULL;
Packit 6ef888
	struct gfs2_buffer_head *bh;
Packit 6ef888
	uint64_t rg_dist[MAX_RGSEGMENTS] = {0, };
Packit 6ef888
	int rg_dcnt[MAX_RGSEGMENTS] = {0, };
Packit 6ef888
	uint64_t blk;
Packit 6ef888
	uint64_t fwd_block, block_bump;
Packit 6ef888
	struct rgrp_tree *calc_rgd, *prev_rgd;
Packit 6ef888
	int number_of_rgs, rgi, segment_rgs;
Packit 6ef888
	int rg_was_fnd = FALSE, corrupt_rgs = 0;
Packit 6ef888
	int error = -1, j, i;
Packit 6ef888
	int grow_segments, segment = 0;
Packit 6ef888
Packit 6ef888
	/*
Packit 6ef888
	 * In order to continue, we need to initialize the jindex. We need
Packit 6ef888
	 * the journals in order to correctly eliminate false positives during
Packit 6ef888
	 * rgrp repair. IOW, we need to properly ignore rgrps that appear in
Packit 6ef888
	 * the journals, and we can only do that if we have the journals.
Packit 6ef888
	 * To make matters worse, journals may span several (small) rgrps,
Packit 6ef888
	 * so we can't go by the rgrps.
Packit 6ef888
	 */
Packit 6ef888
	if (init_jindex(sdp, 0) != 0) {
Packit 6ef888
		log_crit(_("Error: Can't read jindex required for rindex "
Packit 6ef888
			   "repairs.\n"));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	sdp->rgcalc.osi_node = NULL;
Packit 6ef888
	grow_segments = find_shortest_rgdist(sdp, &rg_dist[0], &rg_dcnt[0]);
Packit 6ef888
	for (i = 0; i < grow_segments; i++)
Packit 6ef888
		log_info(_("Segment %d: rgrp distance: 0x%llx, count: %d\n"),
Packit 6ef888
			  i + 1, (unsigned long long)rg_dist[i], rg_dcnt[i]);
Packit 6ef888
	number_of_rgs = segment_rgs = 0;
Packit 6ef888
	/* -------------------------------------------------------------- */
Packit 6ef888
	/* Now go through the RGs and verify their integrity, fixing as   */
Packit 6ef888
	/* needed when corruption is encountered.                         */
Packit 6ef888
	/* -------------------------------------------------------------- */
Packit 6ef888
	prev_rgd = NULL;
Packit 6ef888
	block_bump = rg_dist[0];
Packit 6ef888
	blk = LGFS2_SB_ADDR(sdp) + 1;
Packit 6ef888
	while (blk <= sdp->device.length) {
Packit 6ef888
		log_debug( _("Block 0x%llx\n"), (unsigned long long)blk);
Packit 6ef888
		bh = bread(sdp, blk);
Packit 6ef888
		rg_was_fnd = (!gfs2_check_meta(bh, GFS2_METATYPE_RG));
Packit 6ef888
		brelse(bh);
Packit 6ef888
		/* Allocate a new RG and index. */
Packit 6ef888
		calc_rgd = rgrp_insert(&sdp->rgcalc, blk);
Packit 6ef888
		if (!calc_rgd) {
Packit 6ef888
			log_crit( _("Can't allocate memory for rgrp repair.\n"));
Packit 6ef888
			goto out;
Packit 6ef888
		}
Packit 6ef888
		calc_rgd->ri.ri_length = 1;
Packit 6ef888
		if (!rg_was_fnd) { /* if not an RG */
Packit 6ef888
			/* ------------------------------------------------- */
Packit 6ef888
			/* This SHOULD be an RG but isn't.                   */
Packit 6ef888
			/* ------------------------------------------------- */
Packit 6ef888
			corrupt_rgs++;
Packit 6ef888
			if (corrupt_rgs < 5)
Packit 6ef888
				log_debug(_("Missing or damaged rgrp at block "
Packit 6ef888
					    "%llu (0x%llx)\n"),
Packit 6ef888
					  (unsigned long long)blk,
Packit 6ef888
					  (unsigned long long)blk);
Packit 6ef888
			else {
Packit 6ef888
				log_crit( _("Error: too many missing or "
Packit 6ef888
					    "damaged rgrps using this method. "
Packit 6ef888
					    "Time to try another method.\n"));
Packit 6ef888
				goto out;
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		/* ------------------------------------------------ */
Packit 6ef888
		/* Now go through and count the bitmaps for this RG */
Packit 6ef888
		/* ------------------------------------------------ */
Packit 6ef888
		for (fwd_block = blk + 1; fwd_block < sdp->device.length; fwd_block++) {
Packit 6ef888
			int bitmap_was_fnd;
Packit 6ef888
			bh = bread(sdp, fwd_block);
Packit 6ef888
			bitmap_was_fnd = !gfs2_check_meta(bh, GFS2_METATYPE_RB);
Packit 6ef888
			brelse(bh);
Packit 6ef888
			if (bitmap_was_fnd) /* if a bitmap */
Packit 6ef888
				calc_rgd->ri.ri_length++;
Packit 6ef888
			else
Packit 6ef888
				break; /* end of bitmap, so call it quits. */
Packit 6ef888
		} /* for subsequent bitmaps */
Packit 6ef888
		
Packit 6ef888
		gfs2_compute_bitstructs(sdp->sd_sb.sb_bsize, calc_rgd);
Packit 6ef888
		calc_rgd->ri.ri_data0 = calc_rgd->ri.ri_addr +
Packit 6ef888
			calc_rgd->ri.ri_length;
Packit 6ef888
		if (prev_rgd) {
Packit 6ef888
			uint32_t rgblocks;
Packit 6ef888
Packit 6ef888
			prev_rgd->ri.ri_length = rgblocks2bitblocks(sdp->bsize, block_bump, &rgblocks);
Packit 6ef888
			prev_rgd->ri.ri_data = rgblocks;
Packit 6ef888
			prev_rgd->ri.ri_data0 = prev_rgd->ri.ri_addr +
Packit 6ef888
				prev_rgd->ri.ri_length;
Packit 6ef888
			prev_rgd->ri.ri_data -= prev_rgd->ri.ri_data %
Packit 6ef888
				GFS2_NBBY;
Packit 6ef888
			prev_rgd->ri.ri_bitbytes = prev_rgd->ri.ri_data /
Packit 6ef888
				GFS2_NBBY;
Packit 6ef888
			log_debug( _("Prev ri_data set to: %lx.\n"),
Packit 6ef888
				  (unsigned long)prev_rgd->ri.ri_data);
Packit 6ef888
		}
Packit 6ef888
		number_of_rgs++;
Packit 6ef888
		segment_rgs++;
Packit 6ef888
		if (rg_was_fnd)
Packit 6ef888
			log_info( _("  rgrp %d at block 0x%llx intact\n"),
Packit 6ef888
				  number_of_rgs, (unsigned long long)blk);
Packit 6ef888
		else
Packit 6ef888
			log_warn( _("* rgrp %d at block 0x%llx *** DAMAGED ***\n"),
Packit 6ef888
				  number_of_rgs, (unsigned long long)blk);
Packit 6ef888
		prev_rgd = calc_rgd;
Packit 6ef888
		/*
Packit 6ef888
		 * Figure out where our next rgrp should be.
Packit 6ef888
		 */
Packit 6ef888
		if ((blk == LGFS2_SB_ADDR(sdp) + 1) || (!gfs_grow)) {
Packit 6ef888
			block_bump = rg_dist[segment];
Packit 6ef888
			if (segment_rgs >= rg_dcnt[segment]) {
Packit 6ef888
				log_debug(_("End of segment %d\n"), ++segment);
Packit 6ef888
				segment_rgs = 0;
Packit 6ef888
				if (segment >= grow_segments) {
Packit 6ef888
					log_debug(_("Last segment.\n"));
Packit 6ef888
					break;
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
			/* if we have uniformly-spaced rgrps, there may be
Packit 6ef888
			   some wasted space at the end of the device.
Packit 6ef888
			   Since we don't want to create a short rgrp and
Packit 6ef888
			   break our uniformity, just quit here. */
Packit 6ef888
			if (blk + (2 * block_bump) > sdp->device.length)
Packit 6ef888
				break;
Packit 6ef888
		} else if (rg_was_fnd)
Packit 6ef888
			block_bump = find_next_rgrp_dist(sdp, blk, prev_rgd);
Packit 6ef888
		else
Packit 6ef888
			block_bump = hunt_and_peck(sdp, blk, prev_rgd,
Packit 6ef888
						   block_bump);
Packit 6ef888
		if (block_bump != 1) {
Packit 6ef888
			if (rg_was_fnd)
Packit 6ef888
				log_info( _(" [length 0x%llx]\n"),
Packit 6ef888
					  (unsigned long long)block_bump);
Packit 6ef888
			else
Packit 6ef888
				log_warn( _(" [length 0x%llx]\n"),
Packit 6ef888
					  (unsigned long long)block_bump);
Packit 6ef888
		} else {
Packit 6ef888
			log_warn("\n");
Packit 6ef888
		}
Packit 6ef888
		blk += block_bump;
Packit 6ef888
	} /* for each rg block */
Packit 6ef888
	/* ----------------------------------------------------------------- */
Packit 6ef888
	/* If we got to the end of the fs, we still need to fix the          */
Packit 6ef888
	/* allocation information for the very last RG.                      */
Packit 6ef888
	/* ----------------------------------------------------------------- */
Packit 6ef888
	if (prev_rgd && !prev_rgd->ri.ri_data) {
Packit 6ef888
		uint32_t rgblocks;
Packit 6ef888
Packit 6ef888
		prev_rgd->ri.ri_length = rgblocks2bitblocks(sdp->bsize, block_bump, &rgblocks);
Packit 6ef888
		prev_rgd->ri.ri_data0 = prev_rgd->ri.ri_addr +
Packit 6ef888
			prev_rgd->ri.ri_length;
Packit 6ef888
		prev_rgd->ri.ri_data = rgblocks;
Packit 6ef888
		prev_rgd->ri.ri_data -= prev_rgd->ri.ri_data % GFS2_NBBY;
Packit 6ef888
		prev_rgd->ri.ri_bitbytes = prev_rgd->ri.ri_data / GFS2_NBBY;
Packit 6ef888
		log_debug( _("Prev ri_data set to: %lx.\n"),
Packit 6ef888
			  (unsigned long)prev_rgd->ri.ri_data);
Packit 6ef888
		prev_rgd = NULL; /* make sure we don't use it later */
Packit 6ef888
	}
Packit 6ef888
        /* ---------------------------------------------- */
Packit 6ef888
        /* Now dump out the information (if verbose mode) */      
Packit 6ef888
        /* ---------------------------------------------- */
Packit 6ef888
        log_debug( _("rindex rebuilt as follows:\n"));
Packit 6ef888
	for (n = osi_first(&sdp->rgcalc), rgi = 0; n; n = next, rgi++) {
Packit 6ef888
		next = osi_next(n);
Packit 6ef888
		calc_rgd = (struct rgrp_tree *)n;
Packit 6ef888
                log_debug("%d: 0x%llx / %x / 0x%llx"
Packit 6ef888
			  " / 0x%x / 0x%x\n", rgi + 1,
Packit 6ef888
			  (unsigned long long)calc_rgd->ri.ri_addr,
Packit 6ef888
			  calc_rgd->ri.ri_length,
Packit 6ef888
			  calc_rgd->ri.ri_data0, calc_rgd->ri.ri_data, 
Packit 6ef888
			  calc_rgd->ri.ri_bitbytes);
Packit 6ef888
        }
Packit 6ef888
	*num_rgs = number_of_rgs;
Packit 6ef888
	error = 0;
Packit 6ef888
out:
Packit 6ef888
	for (j = 0; j < sdp->md.journals; j++)
Packit 6ef888
		inode_put(&sdp->md.journal[j]);
Packit 6ef888
	free(sdp->md.journal);
Packit 6ef888
	return error;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * how_many_rgrps - figure out how many RG to put in a subdevice
Packit 6ef888
 * @w: the command line
Packit 6ef888
 * @dev: the device
Packit 6ef888
 *
Packit 6ef888
 * Returns: the number of RGs
Packit 6ef888
 */
Packit 6ef888
static uint64_t how_many_rgrps(struct gfs2_sbd *sdp, struct device *dev, int rgsize_specified)
Packit 6ef888
{
Packit 6ef888
	uint64_t nrgrp;
Packit 6ef888
	uint32_t rgblocks1, rgblocksn, bitblocks1, bitblocksn;
Packit 6ef888
	int bitmap_overflow = 0;
Packit 6ef888
Packit 6ef888
	while (1) {
Packit 6ef888
		nrgrp = DIV_RU(dev->length, (sdp->rgsize << 20) / sdp->bsize);
Packit 6ef888
Packit 6ef888
		/* check to see if the rg length overflows max # bitblks */
Packit 6ef888
		bitblocksn = rgblocks2bitblocks(sdp->bsize, dev->length / nrgrp, &rgblocksn);
Packit 6ef888
		/* calculate size of the first rgrp */
Packit 6ef888
		bitblocks1 = rgblocks2bitblocks(sdp->bsize, dev->length - (nrgrp - 1) * (dev->length / nrgrp),
Packit 6ef888
		                                &rgblocks1);
Packit 6ef888
		if (bitblocks1 > 2149 || bitblocksn > 2149) {
Packit 6ef888
			bitmap_overflow = 1;
Packit 6ef888
			if (sdp->rgsize <= GFS2_DEFAULT_RGSIZE) {
Packit 6ef888
				fprintf(stderr, "error: It is not possible "
Packit 6ef888
					"to use the entire device with "
Packit 6ef888
					"block size %u bytes.\n",
Packit 6ef888
					sdp->bsize);
Packit 6ef888
				exit(-1);
Packit 6ef888
			}
Packit 6ef888
			sdp->rgsize -= GFS2_DEFAULT_RGSIZE; /* smaller rgs */
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
		if (bitmap_overflow ||
Packit 6ef888
		    rgsize_specified || /* If user specified an rg size or */
Packit 6ef888
		    nrgrp <= GFS2_EXCESSIVE_RGS || /* not an excessive # or  */
Packit 6ef888
		    sdp->rgsize >= 2048)   /* we reached the max rg size */
Packit 6ef888
			break;
Packit 6ef888
Packit 6ef888
		sdp->rgsize += GFS2_DEFAULT_RGSIZE; /* bigger rgs */
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	log_debug("  rg sz = %"PRIu32"\n  nrgrp = %"PRIu64"\n", sdp->rgsize,
Packit 6ef888
		  nrgrp);
Packit 6ef888
Packit 6ef888
	return nrgrp;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * compute_rgrp_layout - figure out where the RG in a FS are
Packit 6ef888
 */
Packit 6ef888
static void compute_rgrp_layout(struct gfs2_sbd *sdp, struct osi_root *rgtree, int rgsize_specified)
Packit 6ef888
{
Packit 6ef888
	struct device *dev;
Packit 6ef888
	struct rgrp_tree *rl, *rlast = NULL;
Packit 6ef888
	struct osi_node *n, *next = NULL;
Packit 6ef888
	unsigned int rgrp = 0, nrgrp, rglength;
Packit 6ef888
	uint64_t rgaddr;
Packit 6ef888
Packit 6ef888
	sdp->new_rgrps = 0;
Packit 6ef888
	dev = &sdp->device;
Packit 6ef888
Packit 6ef888
	/* If this is a new file system, compute the length and number */
Packit 6ef888
	/* of rgs based on the size of the device.                     */
Packit 6ef888
	/* If we have existing RGs (i.e. gfs2_grow) find the last one. */
Packit 6ef888
	if (!rgtree->osi_node) {
Packit 6ef888
		dev->length -= LGFS2_SB_ADDR(sdp) + 1;
Packit 6ef888
		nrgrp = how_many_rgrps(sdp, dev, rgsize_specified);
Packit 6ef888
		rglength = dev->length / nrgrp;
Packit 6ef888
		sdp->new_rgrps = nrgrp;
Packit 6ef888
	} else {
Packit 6ef888
		uint64_t old_length, new_chunk;
Packit 6ef888
Packit 6ef888
		printf("Existing resource groups:\n");
Packit 6ef888
		for (rgrp = 0, n = osi_first(rgtree); n; n = next, rgrp++) {
Packit 6ef888
			next = osi_next(n);
Packit 6ef888
			rl = (struct rgrp_tree *)n;
Packit 6ef888
Packit 6ef888
			printf("%d: start: %" PRIu64 " (0x%"
Packit 6ef888
				 PRIx64 "), length = %"PRIu64" (0x%"
Packit 6ef888
				 PRIx64 ")\n", rgrp + 1, rl->start, rl->start,
Packit 6ef888
				 rl->length, rl->length);
Packit 6ef888
			rlast = rl;
Packit 6ef888
		}
Packit 6ef888
		rlast->start = rlast->ri.ri_addr;
Packit 6ef888
		rglength = rgrp_size(rlast);
Packit 6ef888
		rlast->length = rglength;
Packit 6ef888
		old_length = rlast->ri.ri_addr + rglength;
Packit 6ef888
		new_chunk = dev->length - old_length;
Packit 6ef888
		sdp->new_rgrps = new_chunk / rglength;
Packit 6ef888
		nrgrp = rgrp + sdp->new_rgrps;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (rgrp < nrgrp)
Packit 6ef888
		printf("\nNew resource groups:\n");
Packit 6ef888
	for (; rgrp < nrgrp; rgrp++) {
Packit 6ef888
		if (rgrp) {
Packit 6ef888
			rgaddr = rlast->start + rlast->length;
Packit 6ef888
			rl = rgrp_insert(rgtree, rgaddr);
Packit 6ef888
			rl->length = rglength;
Packit 6ef888
		} else {
Packit 6ef888
			rgaddr = LGFS2_SB_ADDR(sdp) + 1;
Packit 6ef888
			rl = rgrp_insert(rgtree, rgaddr);
Packit 6ef888
			rl->length = dev->length -
Packit 6ef888
				(nrgrp - 1) * (dev->length / nrgrp);
Packit 6ef888
		}
Packit 6ef888
		rl->start = rgaddr;
Packit 6ef888
		/* printf("%d: start: %" PRIu64 " (0x%"
Packit 6ef888
			 PRIx64 "), length = %"PRIu64" (0x%"
Packit 6ef888
			 PRIx64 ")\n", rgrp + 1, rl->start, rl->start,
Packit 6ef888
			 rl->length, rl->length);*/
Packit 6ef888
		rlast = rl;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	sdp->rgrps = nrgrp;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * gfs2_rindex_calculate - calculate what the rindex should look like
Packit 6ef888
 *                          in a perfect world (trust_lvl == open_minded)
Packit 6ef888
 *
Packit 6ef888
 * Calculate what the rindex should look like, 
Packit 6ef888
 * so we can later check if all RG index entries are sane.
Packit 6ef888
 * This is a lot easier for gfs2 because we can just call the same libgfs2 
Packit 6ef888
 * functions used by mkfs.
Packit 6ef888
 *
Packit 6ef888
 * Returns: 0 on success, -1 on failure
Packit 6ef888
 * Sets:    sdp->rglist to a linked list of fsck_rgrp structs representing
Packit 6ef888
 *          what we think the rindex should really look like.
Packit 6ef888
 */
Packit 6ef888
static int gfs2_rindex_calculate(struct gfs2_sbd *sdp, int *num_rgs)
Packit 6ef888
{
Packit 6ef888
	uint64_t num_rgrps = 0;
Packit 6ef888
Packit 6ef888
	/* ----------------------------------------------------------------- */
Packit 6ef888
	/* Calculate how many RGs there are supposed to be based on the      */
Packit 6ef888
	/* rindex filesize.  Remember that our trust level is open-minded    */
Packit 6ef888
	/* here.  If the filesize of the rindex file is not a multiple of    */
Packit 6ef888
	/* our rindex structures, then something's wrong and we can't trust  */
Packit 6ef888
	/* the index.                                                        */
Packit 6ef888
	/* ----------------------------------------------------------------- */
Packit 6ef888
	*num_rgs = sdp->md.riinode->i_di.di_size / sizeof(struct gfs2_rindex);
Packit 6ef888
Packit 6ef888
	sdp->rgcalc.osi_node = NULL;
Packit 6ef888
	fix_device_geometry(sdp);
Packit 6ef888
Packit 6ef888
	/* Try all possible rgrp sizes: 2048, 1024, 512, 256, 128, 64, 32 */
Packit 6ef888
	for (sdp->rgsize = GFS2_DEFAULT_RGSIZE; sdp->rgsize >= 32;
Packit 6ef888
	     sdp->rgsize /= 2) {
Packit 6ef888
		num_rgrps = how_many_rgrps(sdp, &sdp->device, TRUE);
Packit 6ef888
		if (num_rgrps == *num_rgs) {
Packit 6ef888
			log_info(_("rgsize must be: %lld (0x%llx)\n"),
Packit 6ef888
				 (unsigned long long)sdp->rgsize,
Packit 6ef888
				 (unsigned long long)sdp->rgsize);
Packit 6ef888
			break;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	/* Compute the default resource group layout as mkfs would have done */
Packit 6ef888
	compute_rgrp_layout(sdp, &sdp->rgcalc, TRUE);
Packit 6ef888
	if (build_rgrps(sdp, FALSE)) { /* FALSE = calc but don't write to disk. */
Packit 6ef888
		fprintf(stderr, _("Failed to build resource groups\n"));
Packit 6ef888
		exit(-1);
Packit 6ef888
	}
Packit 6ef888
	log_debug( _("fs_total_size = 0x%llx blocks.\n"),
Packit 6ef888
		  (unsigned long long)sdp->device.length);
Packit 6ef888
	log_warn( _("L3: number of rgs in the index = %d.\n"), *num_rgs);
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * rewrite_rg_block - rewrite ("fix") a buffer with rg or bitmap data
Packit 6ef888
 * returns: 0 if the rg was repaired, otherwise 1
Packit 6ef888
 */
Packit 6ef888
static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_tree *rg,
Packit 6ef888
			    uint64_t errblock)
Packit 6ef888
{
Packit 6ef888
	int x = errblock - rg->ri.ri_addr;
Packit 6ef888
	const char *typedesc = x ? "GFS2_METATYPE_RB" : "GFS2_METATYPE_RG";
Packit 6ef888
Packit 6ef888
	log_err( _("Block #%lld (0x%llx) (%d of %d) is not %s.\n"),
Packit 6ef888
		 (unsigned long long)rg->ri.ri_addr + x,
Packit 6ef888
		 (unsigned long long)rg->ri.ri_addr + x,
Packit 6ef888
		 (int)x+1, (int)rg->ri.ri_length, typedesc);
Packit 6ef888
	if (query( _("Fix the Resource Group? (y/n)"))) {
Packit 6ef888
		log_err( _("Attempting to repair the rgrp.\n"));
Packit 6ef888
		rg->bits[x].bi_bh = bread(sdp, rg->ri.ri_addr + x);
Packit 6ef888
		if (x) {
Packit 6ef888
			struct gfs2_meta_header mh;
Packit 6ef888
Packit 6ef888
			mh.mh_magic = GFS2_MAGIC;
Packit 6ef888
			mh.mh_type = GFS2_METATYPE_RB;
Packit 6ef888
			mh.mh_format = GFS2_FORMAT_RB;
Packit 6ef888
			gfs2_meta_header_out(&mh, rg->bits[x].bi_bh->b_data);
Packit 6ef888
		} else {
Packit 6ef888
			if (sdp->gfs1)
Packit 6ef888
				memset(&rg->rg, 0, sizeof(struct gfs_rgrp));
Packit 6ef888
			else
Packit 6ef888
				memset(&rg->rg, 0, sizeof(struct gfs2_rgrp));
Packit 6ef888
			rg->rg.rg_header.mh_magic = GFS2_MAGIC;
Packit 6ef888
			rg->rg.rg_header.mh_type = GFS2_METATYPE_RG;
Packit 6ef888
			rg->rg.rg_header.mh_format = GFS2_FORMAT_RG;
Packit 6ef888
			rg->rg.rg_free = rg->ri.ri_data;
Packit 6ef888
			if (sdp->gfs1)
Packit 6ef888
				gfs_rgrp_out((struct gfs_rgrp *)&rg->rg, rg->bits[x].bi_bh);
Packit 6ef888
			else
Packit 6ef888
				gfs2_rgrp_out(&rg->rg, rg->bits[x].bi_bh->b_data);
Packit 6ef888
		}
Packit 6ef888
		bmodified(rg->bits[x].bi_bh);
Packit 6ef888
		brelse(rg->bits[x].bi_bh);
Packit 6ef888
		rg->bits[x].bi_bh = NULL;
Packit 6ef888
		return 0;
Packit 6ef888
	}
Packit 6ef888
	return 1;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * expect_rindex_sanity - the rindex file seems trustworthy, so use those
Packit 6ef888
 *                        values as our expected values and assume the
Packit 6ef888
 *                        damage is only to the rgrps themselves.
Packit 6ef888
 */
Packit 6ef888
static int expect_rindex_sanity(struct gfs2_sbd *sdp, int *num_rgs)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n, *next = NULL;
Packit 6ef888
	struct rgrp_tree *rgd, *exp;
Packit 6ef888
Packit 6ef888
	*num_rgs = sdp->md.riinode->i_di.di_size / sizeof(struct gfs2_rindex) ;
Packit 6ef888
	for (n = osi_first(&sdp->rgtree); n; n = next) {
Packit 6ef888
		next = osi_next(n);
Packit 6ef888
		rgd = (struct rgrp_tree *)n;
Packit 6ef888
		exp = rgrp_insert(&sdp->rgcalc, rgd->ri.ri_addr);
Packit 6ef888
		if (exp == NULL) {
Packit 6ef888
			fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
Packit 6ef888
			exit(-1);
Packit 6ef888
		}
Packit 6ef888
		exp->start = rgd->start;
Packit 6ef888
		exp->length = rgd->length;
Packit 6ef888
		memcpy(&exp->ri, &rgd->ri, sizeof(exp->ri));
Packit 6ef888
		memcpy(&exp->rg, &rgd->rg, sizeof(exp->rg));
Packit 6ef888
		exp->bits = NULL;
Packit 6ef888
		gfs2_compute_bitstructs(sdp->sd_sb.sb_bsize, exp);
Packit 6ef888
	}
Packit 6ef888
	sdp->rgrps = *num_rgs;
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * rg_repair - try to repair a damaged rg index (rindex)
Packit 6ef888
 * trust_lvl - This is how much we trust the rindex file.
Packit 6ef888
 *             blind_faith means we take the rindex at face value.
Packit 6ef888
 *             open_minded means it might be okay, but we should verify it.
Packit 6ef888
 *             distrust means it's not to be trusted, so we should go to
Packit 6ef888
 *             greater lengths to build it from scratch.
Packit 6ef888
 *             indignation means we have corruption, but the file system
Packit 6ef888
 *             was converted from GFS via gfs2_convert, and its rgrps are
Packit 6ef888
 *             not on nice boundaries thanks to previous gfs_grow ops. Lovely.
Packit 6ef888
 */
Packit 6ef888
int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n, *next = NULL, *e, *enext;
Packit 6ef888
	int error, discrepancies, percent;
Packit 6ef888
	int calc_rg_count = 0, rg;
Packit 6ef888
	struct gfs2_rindex buf;
Packit 6ef888
Packit 6ef888
	if (trust_lvl == blind_faith)
Packit 6ef888
		return 0;
Packit 6ef888
	if (trust_lvl == ye_of_little_faith) { /* if rindex seems sane */
Packit 6ef888
		/* Don't free previous incarnations in memory, if any.
Packit 6ef888
		 * We need them to copy in the next function:
Packit 6ef888
		 * gfs2_rgrp_free(&sdp->rglist); */
Packit 6ef888
		if (!(*sane)) {
Packit 6ef888
			log_err(_("The rindex file does not meet our "
Packit 6ef888
				  "expectations.\n"));
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
		error = expect_rindex_sanity(sdp, &calc_rg_count);
Packit 6ef888
		if (error) {
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgcalc);
Packit 6ef888
			return error;
Packit 6ef888
		}
Packit 6ef888
	} else if (trust_lvl == open_minded) { /* If we can't trust RG index */
Packit 6ef888
		/* Free previous incarnations in memory, if any. */
Packit 6ef888
		gfs2_rgrp_free(&sdp->rgtree);
Packit 6ef888
Packit 6ef888
		/* Calculate our own RG index for comparison */
Packit 6ef888
		error = gfs2_rindex_calculate(sdp, &calc_rg_count);
Packit 6ef888
		if (error) { /* If calculated RGs don't match the fs */
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgcalc);
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
	} else if (trust_lvl == distrust) { /* If we can't trust RG index */
Packit 6ef888
		/* Free previous incarnations in memory, if any. */
Packit 6ef888
		gfs2_rgrp_free(&sdp->rgtree);
Packit 6ef888
Packit 6ef888
		error = gfs2_rindex_rebuild(sdp, &calc_rg_count, 0);
Packit 6ef888
		if (error) {
Packit 6ef888
			log_crit( _("Error rebuilding rgrp list.\n"));
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgcalc);
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
	} else if (trust_lvl == indignation) { /* If we can't trust anything */
Packit 6ef888
		/* Free previous incarnations in memory, if any. */
Packit 6ef888
		gfs2_rgrp_free(&sdp->rgtree);
Packit 6ef888
Packit 6ef888
		error = gfs2_rindex_rebuild(sdp, &calc_rg_count, 1);
Packit 6ef888
		if (error) {
Packit 6ef888
			log_crit( _("Error rebuilding rgrp list.\n"));
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgcalc);
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	/* Read in the rindex */
Packit 6ef888
	sdp->rgtree.osi_node = NULL; /* Just to be safe */
Packit 6ef888
	rindex_read(sdp, 0, &sdp->rgrps, sane);
Packit 6ef888
	if (sdp->md.riinode->i_di.di_size % sizeof(struct gfs2_rindex)) {
Packit 6ef888
		log_warn( _("WARNING: rindex file has an invalid size.\n"));
Packit 6ef888
		if (!query( _("Truncate the rindex size? (y/n)"))) {
Packit 6ef888
			log_err(_("The rindex was not repaired.\n"));
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgcalc);
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgtree);
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
		sdp->md.riinode->i_di.di_size /= sizeof(struct gfs2_rindex);
Packit 6ef888
		sdp->md.riinode->i_di.di_size *= sizeof(struct gfs2_rindex);
Packit 6ef888
		bmodified(sdp->md.riinode->i_bh);
Packit 6ef888
		log_err(_("Changing rindex size to %lld.\n"),
Packit 6ef888
			(unsigned long long)sdp->md.riinode->i_di.di_size);
Packit 6ef888
	}
Packit 6ef888
	log_warn( _("L%d: number of rgs expected     = %lld.\n"), trust_lvl + 1,
Packit 6ef888
		 (unsigned long long)sdp->rgrps);
Packit 6ef888
	if (calc_rg_count != sdp->rgrps) {
Packit 6ef888
		int most_that_fit;
Packit 6ef888
Packit 6ef888
		log_warn( _("L%d: They don't match; either (1) the fs was "
Packit 6ef888
			    "extended, (2) an odd\n"), trust_lvl + 1);
Packit 6ef888
		log_warn( _("L%d: rgrp size was used, or (3) we have a corrupt "
Packit 6ef888
			    "rg index.\n"), trust_lvl + 1);
Packit 6ef888
		/* If the trust level is open_minded, we would have calculated
Packit 6ef888
		   the rindex based on the device size. If it's not the same
Packit 6ef888
		   number, don't trust it. Complain about the discrepancy,
Packit 6ef888
		   then try again with a little more distrust. */
Packit 6ef888
		if ((trust_lvl < distrust) ||
Packit 6ef888
		    !query( _("Attempt to use what rgrps we can? (y/n)"))) {
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgcalc);
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgtree);
Packit 6ef888
			log_err(_("The rindex was not repaired.\n"));
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
		/* We cannot grow rindex at this point. Since pass1 has not
Packit 6ef888
		   yet run, we can't allocate blocks. Therefore we must use
Packit 6ef888
		   whatever will fix in the space given. */
Packit 6ef888
		most_that_fit = sdp->md.riinode->i_di.di_size /
Packit 6ef888
			sizeof(struct gfs2_rindex);
Packit 6ef888
		log_debug(_("The most we can fit is %d rgrps\n"),
Packit 6ef888
			  most_that_fit);
Packit 6ef888
		if (most_that_fit < calc_rg_count)
Packit 6ef888
			calc_rg_count = most_that_fit;
Packit 6ef888
		log_err(_("Attempting to fix rindex with %d rgrps.\n"),
Packit 6ef888
			calc_rg_count);
Packit 6ef888
	}
Packit 6ef888
	/* ------------------------------------------------------------- */
Packit 6ef888
	/* Now compare the rindex to what we think it should be.         */
Packit 6ef888
	/* See how far off our expected values are.  If too much, abort. */
Packit 6ef888
	/* The theory is: if we calculated the index to have 32 RGs and  */
Packit 6ef888
	/* we have a large number that are completely wrong, we should   */
Packit 6ef888
	/* abandon this method of recovery and try a better one.         */
Packit 6ef888
	/* ------------------------------------------------------------- */
Packit 6ef888
	discrepancies = 0;
Packit 6ef888
	for (rg = 0, n = osi_first(&sdp->rgtree), e = osi_first(&sdp->rgcalc);
Packit 6ef888
	     n && e && !fsck_abort && rg < calc_rg_count; rg++) {
Packit 6ef888
		struct rgrp_tree *expected, *actual;
Packit 6ef888
Packit 6ef888
		next = osi_next(n);
Packit 6ef888
		enext = osi_next(e);
Packit 6ef888
Packit 6ef888
		expected = (struct rgrp_tree *)e;
Packit 6ef888
		actual = (struct rgrp_tree *)n;
Packit 6ef888
		if (actual->ri.ri_addr < expected->ri.ri_addr) {
Packit 6ef888
			n = next;
Packit 6ef888
			discrepancies++;
Packit 6ef888
			log_info(_("%d addr: 0x%llx < 0x%llx * mismatch\n"),
Packit 6ef888
				 rg + 1, actual->ri.ri_addr,
Packit 6ef888
				 expected->ri.ri_addr);
Packit 6ef888
			continue;
Packit 6ef888
		} else if (expected->ri.ri_addr < actual->ri.ri_addr) {
Packit 6ef888
			e = enext;
Packit 6ef888
			discrepancies++;
Packit 6ef888
			log_info(_("%d addr: 0x%llx > 0x%llx * mismatch\n"),
Packit 6ef888
				 rg + 1, actual->ri.ri_addr,
Packit 6ef888
				 expected->ri.ri_addr);
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
		if (!ri_equal(actual->ri, expected->ri, ri_length) ||
Packit 6ef888
		    !ri_equal(actual->ri, expected->ri, ri_data0) ||
Packit 6ef888
		    !ri_equal(actual->ri, expected->ri, ri_data) ||
Packit 6ef888
		    !ri_equal(actual->ri, expected->ri, ri_bitbytes)) {
Packit 6ef888
			discrepancies++;
Packit 6ef888
			log_info(_("%d addr: 0x%llx 0x%llx * has mismatch\n"),
Packit 6ef888
				 rg + 1, actual->ri.ri_addr,
Packit 6ef888
				 expected->ri.ri_addr);
Packit 6ef888
		}
Packit 6ef888
		n = next;
Packit 6ef888
		e = enext;
Packit 6ef888
	}
Packit 6ef888
	if (rg) {
Packit 6ef888
		/* Check to see if more than 2% of the rgrps are wrong.  */
Packit 6ef888
		percent = (discrepancies * 100) / rg;
Packit 6ef888
		if (percent > BAD_RG_PERCENT_TOLERANCE) {
Packit 6ef888
			log_warn( _("Level %d didn't work.  Too many "
Packit 6ef888
				    "discrepancies.\n"), trust_lvl + 1);
Packit 6ef888
			log_warn( _("%d out of %d rgrps (%d percent) did not "
Packit 6ef888
				    "match what was expected.\n"),
Packit 6ef888
				  discrepancies, rg, percent);
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgcalc);
Packit 6ef888
			gfs2_rgrp_free(&sdp->rgtree);
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	log_debug("Calculated %d rgrps: Total: %d Match: %d Mismatch: %d\n",
Packit 6ef888
		  calc_rg_count, rg, rg - discrepancies, discrepancies);
Packit 6ef888
	/* ------------------------------------------------------------- */
Packit 6ef888
	/* Now compare the rindex to what we think it should be.         */
Packit 6ef888
	/* Our rindex should be pretty predictable unless we've grown    */
Packit 6ef888
	/* so look for index problems first before looking at the rgs.   */
Packit 6ef888
	/* ------------------------------------------------------------- */
Packit 6ef888
	for (rg = 0, n = osi_first(&sdp->rgtree), e = osi_first(&sdp->rgcalc);
Packit 6ef888
	     e && !fsck_abort && rg < calc_rg_count; rg++) {
Packit 6ef888
		struct rgrp_tree *expected, *actual;
Packit 6ef888
Packit 6ef888
		if (n)
Packit 6ef888
			next = osi_next(n);
Packit 6ef888
		enext = osi_next(e);
Packit 6ef888
		expected = (struct rgrp_tree *)e;
Packit 6ef888
		actual = (struct rgrp_tree *)n;
Packit 6ef888
Packit 6ef888
		/* If the next "actual" rgrp in memory is too far away,
Packit 6ef888
		   fill in a new one with the expected value. -or-
Packit 6ef888
		   If we ran out of actual rindex entries due to rindex
Packit 6ef888
		   damage, fill in a new one with the expected values. */
Packit 6ef888
		if (!n || /* end of actual rindex */
Packit 6ef888
		    expected->ri.ri_addr < actual->ri.ri_addr) {
Packit 6ef888
			log_err( _("Entry missing from rindex: 0x%llx\n"),
Packit 6ef888
				 (unsigned long long)expected->ri.ri_addr);
Packit 6ef888
			actual = rgrp_insert(&sdp->rgtree,
Packit 6ef888
					     expected->ri.ri_addr);
Packit 6ef888
			if (!actual) {
Packit 6ef888
				log_err(_("Out of memory!\n"));
Packit 6ef888
				break;
Packit 6ef888
			}
Packit 6ef888
			rindex_modified = 1;
Packit 6ef888
			next = n; /* Ensure that the old actual gets checked
Packit 6ef888
				     against a new expected, since we added */
Packit 6ef888
		} else {
Packit 6ef888
			ri_compare(rg, actual->ri, expected->ri, ri_addr,
Packit 6ef888
				   "llx", unsigned long long);
Packit 6ef888
			ri_compare(rg, actual->ri, expected->ri, ri_length,
Packit 6ef888
				   "lx", unsigned long);
Packit 6ef888
			ri_compare(rg, actual->ri, expected->ri, ri_data0,
Packit 6ef888
				   "llx", unsigned long long);
Packit 6ef888
			ri_compare(rg, actual->ri, expected->ri, ri_data,
Packit 6ef888
				   "lx", unsigned long);
Packit 6ef888
			ri_compare(rg, actual->ri, expected->ri, ri_bitbytes,
Packit 6ef888
				   "lx", unsigned long);
Packit 6ef888
		}
Packit 6ef888
		/* If we modified the index, write it back to disk. */
Packit 6ef888
		if (rindex_modified) {
Packit 6ef888
			if (query( _("Fix the index? (y/n)"))) {
Packit 6ef888
				gfs2_rindex_out(&expected->ri, (char *)&buf;;
Packit 6ef888
				gfs2_writei(sdp->md.riinode, (char *)&buf,
Packit 6ef888
					    rg * sizeof(struct gfs2_rindex),
Packit 6ef888
					    sizeof(struct gfs2_rindex));
Packit 6ef888
				actual->ri.ri_addr = expected->ri.ri_addr;
Packit 6ef888
				actual->ri.ri_length = expected->ri.ri_length;
Packit 6ef888
				actual->ri.ri_data0 = expected->ri.ri_data0;
Packit 6ef888
				actual->ri.ri_data = expected->ri.ri_data;
Packit 6ef888
				actual->ri.ri_bitbytes =
Packit 6ef888
					expected->ri.ri_bitbytes;
Packit 6ef888
				/* If our rindex was hosed, ri_length is bad */
Packit 6ef888
				/* Therefore, gfs2_compute_bitstructs might  */
Packit 6ef888
				/* have malloced the wrong length for bitmap */
Packit 6ef888
				/* buffers.  So we have to redo it.          */
Packit 6ef888
				if (actual->bits) {
Packit 6ef888
					free(actual->bits);
Packit 6ef888
					actual->bits = NULL;
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
			else
Packit 6ef888
				log_err( _("rindex not fixed.\n"));
Packit 6ef888
			gfs2_compute_bitstructs(sdp->sd_sb.sb_bsize, actual);
Packit 6ef888
			rindex_modified = FALSE;
Packit 6ef888
		}
Packit 6ef888
		e = enext;
Packit 6ef888
		if (n)
Packit 6ef888
			n = next;
Packit 6ef888
	}
Packit 6ef888
	/* ------------------------------------------------------------- */
Packit 6ef888
	/* Read the real RGs and check their integrity.                  */
Packit 6ef888
	/* Now we can somewhat trust the rindex and the RG addresses,    */
Packit 6ef888
	/* so let's read them in, check them and optionally fix them.    */
Packit 6ef888
	/* ------------------------------------------------------------- */
Packit 6ef888
	for (rg = 0, n = osi_first(&sdp->rgtree); n && !fsck_abort &&
Packit 6ef888
		     rg < calc_rg_count; n = next, rg++) {
Packit 6ef888
		struct rgrp_tree *rgd;
Packit 6ef888
		uint64_t prev_err = 0, errblock;
Packit 6ef888
		int i;
Packit 6ef888
Packit 6ef888
		next = osi_next(n);
Packit 6ef888
		/* Now we try repeatedly to read in the rg.  For every block */
Packit 6ef888
		/* we encounter that has errors, repair it and try again.    */
Packit 6ef888
		i = 0;
Packit 6ef888
		do {
Packit 6ef888
			rgd = (struct rgrp_tree *)n;
Packit 6ef888
			errblock = gfs2_rgrp_read(sdp, rgd);
Packit 6ef888
			if (errblock) {
Packit 6ef888
				if (errblock == prev_err)
Packit 6ef888
					break;
Packit 6ef888
				prev_err = errblock;
Packit 6ef888
				rewrite_rg_block(sdp, rgd, errblock);
Packit 6ef888
			} else {
Packit 6ef888
				gfs2_rgrp_relse(rgd);
Packit 6ef888
				break;
Packit 6ef888
			}
Packit 6ef888
			i++;
Packit 6ef888
		} while (i < rgd->ri.ri_length);
Packit 6ef888
	}
Packit 6ef888
	*rg_count = rg;
Packit 6ef888
	gfs2_rgrp_free(&sdp->rgcalc);
Packit 6ef888
	gfs2_rgrp_free(&sdp->rgtree);
Packit 6ef888
	/* We shouldn't need to worry about getting the user's permission to
Packit 6ef888
	   make changes here. If b_modified is true, they already gave their
Packit 6ef888
	   permission. */
Packit 6ef888
	if (sdp->md.riinode->i_bh->b_modified) {
Packit 6ef888
		log_debug("Syncing rindex inode changes to disk.\n");
Packit 6ef888
		gfs2_dinode_out(&sdp->md.riinode->i_di, sdp->md.riinode->i_bh->b_data);
Packit 6ef888
		bwrite(sdp->md.riinode->i_bh);
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}