Blame gfs2/fsck/initialize.c

Packit 6ef888
#include "clusterautoconfig.h"
Packit 6ef888
Packit 6ef888
#include <stdio.h>
Packit 6ef888
#include <stdint.h>
Packit 6ef888
#include <inttypes.h>
Packit 6ef888
#include <stdlib.h>
Packit 6ef888
#include <sys/types.h>
Packit 6ef888
#include <sys/stat.h>
Packit 6ef888
#include <fcntl.h>
Packit 6ef888
#include <string.h>
Packit 6ef888
#include <unistd.h>
Packit 6ef888
#include <libintl.h>
Packit 6ef888
#include <errno.h>
Packit 6ef888
#include <time.h>
Packit 6ef888
Packit 6ef888
#define _(String) gettext(String)
Packit 6ef888
Packit 6ef888
#include <logging.h>
Packit 6ef888
#include "libgfs2.h"
Packit 6ef888
#include "fsck.h"
Packit 6ef888
#include "util.h"
Packit 6ef888
#include "fs_recovery.h"
Packit 6ef888
#include "metawalk.h"
Packit 6ef888
#include "inode_hash.h"
Packit 6ef888
Packit 6ef888
#define CLEAR_POINTER(x) \
Packit 6ef888
	if (x) { \
Packit 6ef888
		free(x); \
Packit 6ef888
		x = NULL; \
Packit 6ef888
	}
Packit 6ef888
#define HIGHEST_BLOCK 0xffffffffffffffff
Packit 6ef888
Packit 6ef888
static int was_mounted_ro = 0;
Packit 6ef888
static uint64_t possible_root = HIGHEST_BLOCK;
Packit 6ef888
static struct master_dir fix_md;
Packit 6ef888
static unsigned long long blks_2free = 0;
Packit 6ef888
extern int sb_fixed;
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * block_mounters
Packit 6ef888
 *
Packit 6ef888
 * Change the lock protocol so nobody can mount the fs
Packit 6ef888
 *
Packit 6ef888
 */
Packit 6ef888
static int block_mounters(struct gfs2_sbd *sdp, int block_em)
Packit 6ef888
{
Packit 6ef888
	if (block_em) {
Packit 6ef888
		/* verify it starts with lock_ */
Packit 6ef888
		if (!strncmp(sdp->sd_sb.sb_lockproto, "lock_", 5)) {
Packit 6ef888
			/* Change lock_ to fsck_ */
Packit 6ef888
			memcpy(sdp->sd_sb.sb_lockproto, "fsck_", 5);
Packit 6ef888
		}
Packit 6ef888
		/* FIXME: Need to do other verification in the else
Packit 6ef888
		 * case */
Packit 6ef888
	} else {
Packit 6ef888
		/* verify it starts with fsck_ */
Packit 6ef888
		/* verify it starts with lock_ */
Packit 6ef888
		if (!strncmp(sdp->sd_sb.sb_lockproto, "fsck_", 5)) {
Packit 6ef888
			/* Change fsck_ to lock_ */
Packit 6ef888
			memcpy(sdp->sd_sb.sb_lockproto, "lock_", 5);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (lgfs2_sb_write(&sdp->sd_sb, sdp->device_fd, sdp->bsize)) {
Packit 6ef888
		stack;
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static void gfs2_dup_free(void)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n;
Packit 6ef888
	struct duptree *dt;
Packit 6ef888
Packit 6ef888
	while ((n = osi_first(&dup_blocks))) {
Packit 6ef888
		dt = (struct duptree *)n;
Packit 6ef888
		dup_delete(dt);
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static void gfs2_dirtree_free(void)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n;
Packit 6ef888
	struct dir_info *dt;
Packit 6ef888
Packit 6ef888
	while ((n = osi_first(&dirtree))) {
Packit 6ef888
		dt = (struct dir_info *)n;
Packit 6ef888
		dirtree_delete(dt);
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static void gfs2_inodetree_free(void)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n;
Packit 6ef888
	struct inode_info *dt;
Packit 6ef888
Packit 6ef888
	while ((n = osi_first(&inodetree))) {
Packit 6ef888
		dt = (struct inode_info *)n;
Packit 6ef888
		inodetree_delete(dt);
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * empty_super_block - free all structures in the super block
Packit 6ef888
 * sdp: the in-core super block
Packit 6ef888
 *
Packit 6ef888
 * This function frees all allocated structures within the
Packit 6ef888
 * super block.  It does not free the super block itself.
Packit 6ef888
 *
Packit 6ef888
 * Returns: Nothing
Packit 6ef888
 */
Packit 6ef888
static void empty_super_block(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	log_info( _("Freeing buffers.\n"));
Packit 6ef888
	gfs2_rgrp_free(&sdp->rgtree);
Packit 6ef888
Packit 6ef888
	gfs2_inodetree_free();
Packit 6ef888
	gfs2_dirtree_free();
Packit 6ef888
	gfs2_dup_free();
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * set_block_ranges
Packit 6ef888
 * @sdp: superblock
Packit 6ef888
 *
Packit 6ef888
 * Uses info in rgrps and jindex to determine boundaries of the
Packit 6ef888
 * file system.
Packit 6ef888
 *
Packit 6ef888
 * Returns: 0 on success, -1 on failure
Packit 6ef888
 */
Packit 6ef888
static int set_block_ranges(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n, *next = NULL;
Packit 6ef888
	struct rgrp_tree *rgd;
Packit 6ef888
	struct gfs2_rindex *ri;
Packit 6ef888
	char buf[sdp->sd_sb.sb_bsize];
Packit 6ef888
	uint64_t rmax = 0;
Packit 6ef888
	uint64_t rmin = 0;
Packit 6ef888
	int error;
Packit 6ef888
Packit 6ef888
	log_info( _("Setting block ranges..."));
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
		ri = &rgd->ri;
Packit 6ef888
		if (ri->ri_data0 + ri->ri_data &&
Packit 6ef888
		    ri->ri_data0 + ri->ri_data - 1 > rmax)
Packit 6ef888
			rmax = ri->ri_data0 + ri->ri_data - 1;
Packit 6ef888
		if (!rmin || ri->ri_data0 < rmin)
Packit 6ef888
			rmin = ri->ri_data0;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	last_fs_block = rmax;
Packit 6ef888
	if (last_fs_block > 0xffffffff && sizeof(unsigned long) <= 4) {
Packit 6ef888
		log_crit( _("This file system is too big for this computer to handle.\n"));
Packit 6ef888
		log_crit( _("Last fs block = 0x%llx, but sizeof(unsigned long) is %zu bytes.\n"),
Packit 6ef888
			 (unsigned long long)last_fs_block,
Packit 6ef888
			 sizeof(unsigned long));
Packit 6ef888
		goto fail;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	last_data_block = rmax;
Packit 6ef888
	first_data_block = rmin;
Packit 6ef888
Packit 6ef888
	if (fsck_lseek(sdp->device_fd, (last_fs_block * sdp->sd_sb.sb_bsize))){
Packit 6ef888
		log_crit( _("Can't seek to last block in file system: %llu"
Packit 6ef888
			 " (0x%llx)\n"), (unsigned long long)last_fs_block,
Packit 6ef888
			 (unsigned long long)last_fs_block);
Packit 6ef888
		goto fail;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	memset(buf, 0, sdp->sd_sb.sb_bsize);
Packit 6ef888
	error = read(sdp->device_fd, buf, sdp->sd_sb.sb_bsize);
Packit 6ef888
	if (error != sdp->sd_sb.sb_bsize){
Packit 6ef888
		log_crit( _("Can't read last block in file system (error %u), "
Packit 6ef888
			 "last_fs_block: %llu (0x%llx)\n"), error,
Packit 6ef888
			 (unsigned long long)last_fs_block,
Packit 6ef888
			 (unsigned long long)last_fs_block);
Packit 6ef888
		goto fail;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	log_info(_("0x%llx to 0x%llx\n"), (unsigned long long)first_data_block,
Packit 6ef888
		 (unsigned long long)last_data_block);
Packit 6ef888
	return 0;
Packit 6ef888
Packit 6ef888
 fail:
Packit 6ef888
	log_info( _("Error\n"));
Packit 6ef888
	return -1;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * check_rgrp_integrity - verify a rgrp free block count against the bitmap
Packit 6ef888
 */
Packit 6ef888
static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
Packit 6ef888
				 int *fixit, int *this_rg_fixed,
Packit 6ef888
				 int *this_rg_bad, int *this_rg_cleaned)
Packit 6ef888
{
Packit 6ef888
	uint32_t rg_free, rg_reclaimed, rg_unlinked, rg_usedmeta, rg_useddi;
Packit 6ef888
	int rgb, x, y, off, bytes_to_check, total_bytes_to_check, asked = 0;
Packit 6ef888
	unsigned int state;
Packit 6ef888
	struct gfs_rgrp *gfs1rg = (struct gfs_rgrp *)&rgd->rg;
Packit 6ef888
	uint64_t diblock;
Packit 6ef888
	struct gfs2_buffer_head *bh;
Packit 6ef888
Packit 6ef888
	rg_free = rg_reclaimed = rg_unlinked = rg_usedmeta = rg_useddi = 0;
Packit 6ef888
	total_bytes_to_check = rgd->ri.ri_bitbytes;
Packit 6ef888
Packit 6ef888
	*this_rg_fixed = *this_rg_bad = *this_rg_cleaned = 0;
Packit 6ef888
Packit 6ef888
	diblock = rgd->ri.ri_data0;
Packit 6ef888
	for (rgb = 0; rgb < rgd->ri.ri_length; rgb++){
Packit 6ef888
		/* Count up the free blocks in the bitmap */
Packit 6ef888
		off = (rgb) ? sizeof(struct gfs2_meta_header) :
Packit 6ef888
			sizeof(struct gfs2_rgrp);
Packit 6ef888
		if (total_bytes_to_check <= sdp->bsize - off)
Packit 6ef888
			bytes_to_check = total_bytes_to_check;
Packit 6ef888
		else
Packit 6ef888
			bytes_to_check = sdp->bsize - off;
Packit 6ef888
		total_bytes_to_check -= bytes_to_check;
Packit 6ef888
		for (x = 0; x < bytes_to_check; x++) {
Packit 6ef888
			unsigned char *byte;
Packit 6ef888
Packit 6ef888
			byte = (unsigned char *)&rgd->bits[rgb].bi_bh->b_data[off + x];
Packit 6ef888
			if (*byte == 0x55) {
Packit 6ef888
				diblock += GFS2_NBBY;
Packit 6ef888
				continue;
Packit 6ef888
			}
Packit 6ef888
			if (*byte == 0x00) {
Packit 6ef888
				diblock += GFS2_NBBY;
Packit 6ef888
				rg_free += GFS2_NBBY;
Packit 6ef888
				continue;
Packit 6ef888
			}
Packit 6ef888
			for (y = 0; y < GFS2_NBBY; y++) {
Packit 6ef888
				state = (*byte >>
Packit 6ef888
					 (GFS2_BIT_SIZE * y)) & GFS2_BIT_MASK;
Packit 6ef888
				if (state == GFS2_BLKST_USED) {
Packit 6ef888
					diblock++;
Packit 6ef888
					continue;
Packit 6ef888
				}
Packit 6ef888
				if (state == GFS2_BLKST_DINODE) {
Packit 6ef888
					if (sdp->gfs1) {
Packit 6ef888
						bh = bread(sdp, diblock);
Packit 6ef888
						if (!gfs2_check_meta(bh,
Packit 6ef888
							GFS2_METATYPE_DI))
Packit 6ef888
							rg_useddi++;
Packit 6ef888
						else
Packit 6ef888
							rg_usedmeta++;
Packit 6ef888
						brelse(bh);
Packit 6ef888
					}
Packit 6ef888
					diblock++;
Packit 6ef888
					continue;
Packit 6ef888
				}
Packit 6ef888
				if (state == GFS2_BLKST_FREE) {
Packit 6ef888
					diblock++;
Packit 6ef888
					rg_free++;
Packit 6ef888
					continue;
Packit 6ef888
				}
Packit 6ef888
				/* GFS2_BLKST_UNLINKED */
Packit 6ef888
				if (sdp->gfs1)
Packit 6ef888
					log_info(_("Free metadata block 0x%llx"
Packit 6ef888
						   " found.\n"),
Packit 6ef888
						 (unsigned long long)diblock);
Packit 6ef888
				else
Packit 6ef888
					log_info(_("Unlinked dinode 0x%llx "
Packit 6ef888
						   "found.\n"),
Packit 6ef888
						 (unsigned long long)diblock);
Packit 6ef888
				if (!asked) {
Packit 6ef888
					char msg[256];
Packit 6ef888
Packit 6ef888
					asked = 1;
Packit 6ef888
					sprintf(msg,
Packit 6ef888
						_("Okay to reclaim free "
Packit 6ef888
						  "metadata in resource group "
Packit 6ef888
						  "%lld (0x%llx)? (y/n)"),
Packit 6ef888
						(unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
						(unsigned long long)rgd->ri.ri_addr);
Packit 6ef888
					if (query("%s", msg))
Packit 6ef888
						*fixit = 1;
Packit 6ef888
				}
Packit 6ef888
				if (!(*fixit)) {
Packit 6ef888
					rg_unlinked++;
Packit 6ef888
					diblock++;
Packit 6ef888
					continue;
Packit 6ef888
				}
Packit 6ef888
				*byte &= ~(GFS2_BIT_MASK <<
Packit 6ef888
					   (GFS2_BIT_SIZE * y));
Packit 6ef888
				bmodified(rgd->bits[rgb].bi_bh);
Packit 6ef888
				rg_reclaimed++;
Packit 6ef888
				rg_free++;
Packit 6ef888
				rgd->rg.rg_free++;
Packit 6ef888
				if (sdp->gfs1 && gfs1rg->rg_freemeta)
Packit 6ef888
					gfs1rg->rg_freemeta--;
Packit 6ef888
				log_info(_("Free metadata block %lld (0x%llx) "
Packit 6ef888
					   "reclaimed.\n"),
Packit 6ef888
					 (unsigned long long)diblock,
Packit 6ef888
					 (unsigned long long)diblock);
Packit 6ef888
				bh = bread(sdp, diblock);
Packit 6ef888
				if (!gfs2_check_meta(bh, GFS2_METATYPE_DI)) {
Packit 6ef888
					struct gfs2_inode *ip =
Packit 6ef888
						fsck_inode_get(sdp, rgd, bh);
Packit 6ef888
					if (ip->i_di.di_blocks > 1) {
Packit 6ef888
						blks_2free +=
Packit 6ef888
							ip->i_di.di_blocks - 1;
Packit 6ef888
						log_info(_("%lld blocks "
Packit 6ef888
							   "(total) may need "
Packit 6ef888
							   "to be freed in "
Packit 6ef888
							   "pass 5.\n"),
Packit 6ef888
							 blks_2free);
Packit 6ef888
					}
Packit 6ef888
					fsck_inode_put(&ip);
Packit 6ef888
				}
Packit 6ef888
				brelse(bh);
Packit 6ef888
				diblock++;
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	/* The unlinked blocks we reclaim shouldn't be considered errors,
Packit 6ef888
	   since we're just reclaiming them as a courtesy. If we already
Packit 6ef888
	   got permission to reclaim them, we adjust the rgrp counts
Packit 6ef888
	   accordingly. That way, only "real" rgrp count inconsistencies
Packit 6ef888
	   will be reported. */
Packit 6ef888
	if (rg_reclaimed && *fixit) {
Packit 6ef888
		if (sdp->gfs1)
Packit 6ef888
			gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg, rgd->bits[0].bi_bh);
Packit 6ef888
		else
Packit 6ef888
			gfs2_rgrp_out(&rgd->rg, rgd->bits[0].bi_bh->b_data);
Packit 6ef888
		bmodified(rgd->bits[0].bi_bh);
Packit 6ef888
		*this_rg_cleaned = 1;
Packit 6ef888
		log_info( _("The rgrp at %lld (0x%llx) was cleaned of %d "
Packit 6ef888
			    "free metadata blocks.\n"),
Packit 6ef888
			  (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			  (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			  rg_reclaimed);
Packit 6ef888
	}
Packit 6ef888
	if (rgd->rg.rg_free != rg_free) {
Packit 6ef888
		*this_rg_bad = 1;
Packit 6ef888
		*this_rg_cleaned = 0;
Packit 6ef888
		log_err( _("Error: resource group %lld (0x%llx): "
Packit 6ef888
			   "free space (%d) does not match bitmap (%d)\n"),
Packit 6ef888
			 (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			 (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			 rgd->rg.rg_free, rg_free);
Packit 6ef888
		if (query( _("Fix the rgrp free blocks count? (y/n)"))) {
Packit 6ef888
			rgd->rg.rg_free = rg_free;
Packit 6ef888
			if (sdp->gfs1)
Packit 6ef888
				gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg, rgd->bits[0].bi_bh);
Packit 6ef888
			else
Packit 6ef888
				gfs2_rgrp_out(&rgd->rg, rgd->bits[0].bi_bh->b_data);
Packit 6ef888
			bmodified(rgd->bits[0].bi_bh);
Packit 6ef888
			*this_rg_fixed = 1;
Packit 6ef888
			log_err( _("The rgrp was fixed.\n"));
Packit 6ef888
		} else
Packit 6ef888
			log_err( _("The rgrp was not fixed.\n"));
Packit 6ef888
	}
Packit 6ef888
	if (!sdp->gfs1)
Packit 6ef888
		return;
Packit 6ef888
Packit 6ef888
	if (gfs1rg->rg_freemeta != rg_unlinked) {
Packit 6ef888
		*this_rg_bad = 1;
Packit 6ef888
		*this_rg_cleaned = 0;
Packit 6ef888
		log_err( _("Error: resource group %lld (0x%llx): "
Packit 6ef888
			   "free meta  (%d) does not match bitmap (%d)\n"),
Packit 6ef888
			 (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			 (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			 gfs1rg->rg_freemeta, rg_unlinked);
Packit 6ef888
		if (query( _("Fix the rgrp free meta blocks count? (y/n)"))) {
Packit 6ef888
			gfs1rg->rg_freemeta = rg_unlinked;
Packit 6ef888
			gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg, rgd->bits[0].bi_bh);
Packit 6ef888
			*this_rg_fixed = 1;
Packit 6ef888
			log_err( _("The rgrp was fixed.\n"));
Packit 6ef888
		} else
Packit 6ef888
			log_err( _("The rgrp was not fixed.\n"));
Packit 6ef888
	}
Packit 6ef888
	if (gfs1rg->rg_useddi != rg_useddi) {
Packit 6ef888
		*this_rg_bad = 1;
Packit 6ef888
		*this_rg_cleaned = 0;
Packit 6ef888
		log_err( _("Error: resource group %lld (0x%llx): used dinode "
Packit 6ef888
			   "count (%d) does not match bitmap (%d)\n"),
Packit 6ef888
			 (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			 (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			 gfs1rg->rg_useddi, rg_useddi);
Packit 6ef888
		if (query( _("Fix the rgrp used dinode block count? (y/n)"))) {
Packit 6ef888
			gfs1rg->rg_useddi = rg_useddi;
Packit 6ef888
			gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg,
Packit 6ef888
				     rgd->bits[0].bi_bh);
Packit 6ef888
			*this_rg_fixed = 1;
Packit 6ef888
			log_err( _("The rgrp was fixed.\n"));
Packit 6ef888
		} else
Packit 6ef888
			log_err( _("The rgrp was not fixed.\n"));
Packit 6ef888
	}
Packit 6ef888
	if (gfs1rg->rg_usedmeta != rg_usedmeta) {
Packit 6ef888
		*this_rg_bad = 1;
Packit 6ef888
		*this_rg_cleaned = 0;
Packit 6ef888
		log_err( _("Error: resource group %lld (0x%llx): used "
Packit 6ef888
			   "metadata (%d) does not match bitmap (%d)\n"),
Packit 6ef888
			 (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			 (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			 gfs1rg->rg_usedmeta, rg_usedmeta);
Packit 6ef888
		if (query( _("Fix the rgrp used meta blocks count? (y/n)"))) {
Packit 6ef888
			gfs1rg->rg_usedmeta = rg_usedmeta;
Packit 6ef888
			gfs_rgrp_out((struct gfs_rgrp *)&rgd->rg,
Packit 6ef888
				     rgd->bits[0].bi_bh);
Packit 6ef888
			*this_rg_fixed = 1;
Packit 6ef888
			log_err( _("The rgrp was fixed.\n"));
Packit 6ef888
		} else
Packit 6ef888
			log_err( _("The rgrp was not fixed.\n"));
Packit 6ef888
	}
Packit 6ef888
	/*
Packit 6ef888
	else {
Packit 6ef888
		log_debug( _("Resource group %lld (0x%llx) free space "
Packit 6ef888
			     "is consistent: free: %d reclaimed: %d\n"),
Packit 6ef888
			   (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			   (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
			   rg_free, rg_reclaimed);
Packit 6ef888
	}*/
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * check_rgrps_integrity - verify rgrp consistency
Packit 6ef888
 * Note: We consider an rgrp "cleaned" if the unlinked meta blocks are
Packit 6ef888
 *       cleaned, so not quite "bad" and not quite "good" but rewritten anyway.
Packit 6ef888
 *
Packit 6ef888
 * Returns: 0 on success, 1 if errors were detected
Packit 6ef888
 */
Packit 6ef888
static void check_rgrps_integrity(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *n, *next = NULL;
Packit 6ef888
	int rgs_good = 0, rgs_bad = 0, rgs_fixed = 0, rgs_cleaned = 0;
Packit 6ef888
	int was_bad = 0, was_fixed = 0, was_cleaned = 0;
Packit 6ef888
	struct rgrp_tree *rgd;
Packit 6ef888
	int reclaim_unlinked = 0;
Packit 6ef888
Packit 6ef888
	log_info( _("Checking the integrity of all resource groups.\n"));
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 (fsck_abort)
Packit 6ef888
			return;
Packit 6ef888
		check_rgrp_integrity(sdp, rgd, &reclaim_unlinked,
Packit 6ef888
				     &was_fixed, &was_bad, &was_cleaned);
Packit 6ef888
		if (was_fixed)
Packit 6ef888
			rgs_fixed++;
Packit 6ef888
		if (was_cleaned)
Packit 6ef888
			rgs_cleaned++;
Packit 6ef888
		else if (was_bad)
Packit 6ef888
			rgs_bad++;
Packit 6ef888
		else
Packit 6ef888
			rgs_good++;
Packit 6ef888
	}
Packit 6ef888
	if (rgs_bad || rgs_cleaned) {
Packit 6ef888
		log_err( _("RGs: Consistent: %d   Cleaned: %d   Inconsistent: "
Packit 6ef888
			   "%d   Fixed: %d   Total: %d\n"),
Packit 6ef888
			 rgs_good, rgs_cleaned, rgs_bad, rgs_fixed,
Packit 6ef888
			 rgs_good + rgs_bad + rgs_cleaned);
Packit 6ef888
		if (rgs_cleaned && blks_2free)
Packit 6ef888
			log_err(_("%lld blocks may need to be freed in pass 5 "
Packit 6ef888
				  "due to the cleaned resource groups.\n"),
Packit 6ef888
				blks_2free);
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * rebuild_master - rebuild a destroyed master directory
Packit 6ef888
 */
Packit 6ef888
static int rebuild_master(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	struct gfs2_inum inum;
Packit 6ef888
	struct gfs2_buffer_head *bh = NULL;
Packit 6ef888
	int err = 0;
Packit 6ef888
Packit 6ef888
	log_err(_("The system master directory seems to be destroyed.\n"));
Packit 6ef888
	if (!query(_("Okay to rebuild it? (y/n)"))) {
Packit 6ef888
		log_err(_("System master not rebuilt; aborting.\n"));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	log_err(_("Trying to rebuild the master directory.\n"));
Packit 6ef888
	inum.no_formal_ino = sdp->md.next_inum++;
Packit 6ef888
	inum.no_addr = sdp->sd_sb.sb_master_dir.no_addr;
Packit 6ef888
	err = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
Packit 6ef888
	if (err != 0)
Packit 6ef888
		return -1;
Packit 6ef888
	sdp->master_dir = lgfs2_inode_get(sdp, bh);
Packit 6ef888
	if (sdp->master_dir == NULL) {
Packit 6ef888
		log_crit(_("Error reading master: %s\n"), strerror(errno));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	sdp->master_dir->bh_owned = 1;
Packit 6ef888
Packit 6ef888
	if (fix_md.jiinode) {
Packit 6ef888
		inum.no_formal_ino = sdp->md.next_inum++;
Packit 6ef888
		inum.no_addr = fix_md.jiinode->i_di.di_num.no_addr;
Packit 6ef888
		err = dir_add(sdp->master_dir, "jindex", 6, &inum,
Packit 6ef888
		              IF2DT(S_IFDIR | 0700));
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d adding jindex directory\n"), errno);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
		sdp->master_dir->i_di.di_nlink++;
Packit 6ef888
	} else {
Packit 6ef888
		err = build_jindex(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d building jindex\n"), err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (fix_md.pinode) {
Packit 6ef888
		inum.no_formal_ino = sdp->md.next_inum++;
Packit 6ef888
		inum.no_addr = fix_md.pinode->i_di.di_num.no_addr;
Packit 6ef888
		err = dir_add(sdp->master_dir, "per_node", 8, &inum,
Packit 6ef888
			IF2DT(S_IFDIR | 0700));
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d adding per_node directory\n"),
Packit 6ef888
				 errno);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
		sdp->master_dir->i_di.di_nlink++;
Packit 6ef888
	} else {
Packit 6ef888
		err = build_per_node(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d building per_node directory\n"),
Packit 6ef888
			         err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (fix_md.inum) {
Packit 6ef888
		inum.no_formal_ino = sdp->md.next_inum++;
Packit 6ef888
		inum.no_addr = fix_md.inum->i_di.di_num.no_addr;
Packit 6ef888
		err = dir_add(sdp->master_dir, "inum", 4, &inum,
Packit 6ef888
			IF2DT(S_IFREG | 0600));
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d adding inum inode\n"), errno);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	} else {
Packit 6ef888
		err = build_inum(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d building inum inode\n"), err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
		gfs2_lookupi(sdp->master_dir, "inum", 4, &sdp->md.inum);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (fix_md.statfs) {
Packit 6ef888
		inum.no_formal_ino = sdp->md.next_inum++;
Packit 6ef888
		inum.no_addr = fix_md.statfs->i_di.di_num.no_addr;
Packit 6ef888
		err = dir_add(sdp->master_dir, "statfs", 6, &inum,
Packit 6ef888
			      IF2DT(S_IFREG | 0600));
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d adding statfs inode\n"), errno);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	} else {
Packit 6ef888
		err = build_statfs(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d building statfs inode\n"), err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
		gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (fix_md.riinode) {
Packit 6ef888
		inum.no_formal_ino = sdp->md.next_inum++;
Packit 6ef888
		inum.no_addr = fix_md.riinode->i_di.di_num.no_addr;
Packit 6ef888
		err = dir_add(sdp->master_dir, "rindex", 6, &inum,
Packit 6ef888
			IF2DT(S_IFREG | 0600));
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d adding rindex inode\n"), errno);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	} else {
Packit 6ef888
		err = build_rindex(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d building rindex inode\n"), err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (fix_md.qinode) {
Packit 6ef888
		inum.no_formal_ino = sdp->md.next_inum++;
Packit 6ef888
		inum.no_addr = fix_md.qinode->i_di.di_num.no_addr;
Packit 6ef888
		err = dir_add(sdp->master_dir, "quota", 5, &inum,
Packit 6ef888
			IF2DT(S_IFREG | 0600));
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d adding quota inode\n"), errno);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	} else {
Packit 6ef888
		err = build_quota(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d building quota inode\n"), err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	log_err(_("Master directory rebuilt.\n"));
Packit 6ef888
	inode_put(&sdp->md.inum);
Packit 6ef888
	inode_put(&sdp->md.statfs);
Packit 6ef888
	inode_put(&sdp->master_dir);
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * lookup_per_node - Make sure the per_node directory is read in
Packit 6ef888
 *
Packit 6ef888
 * This function is used to read in the per_node directory.  It is called
Packit 6ef888
 * twice.  The first call tries to read in the dinode early on.  That ensures
Packit 6ef888
 * that if any journals are missing, we can figure out the number of journals
Packit 6ef888
 * from per_node.  However, we unfortunately can't rebuild per_node at that
Packit 6ef888
 * point in time because our resource groups aren't read in yet.
Packit 6ef888
 * The second time it's called is much later when we can rebuild it.
Packit 6ef888
 *
Packit 6ef888
 * allow_rebuild: 0 if rebuilds are not allowed
Packit 6ef888
 *                1 if rebuilds are allowed
Packit 6ef888
 */
Packit 6ef888
static void lookup_per_node(struct gfs2_sbd *sdp, int allow_rebuild)
Packit 6ef888
{
Packit 6ef888
	if (sdp->md.pinode)
Packit 6ef888
		return;
Packit 6ef888
Packit 6ef888
	gfs2_lookupi(sdp->master_dir, "per_node", 8, &sdp->md.pinode);
Packit 6ef888
	if (sdp->md.pinode)
Packit 6ef888
		return;
Packit 6ef888
	if (!allow_rebuild) {
Packit 6ef888
		log_err( _("The gfs2 system per_node directory "
Packit 6ef888
			   "inode is missing, so we might not be \nable to "
Packit 6ef888
			   "rebuild missing journals this run.\n"));
Packit 6ef888
		return;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (query( _("The gfs2 system per_node directory "
Packit 6ef888
		     "inode is missing. Okay to rebuild it? (y/n) "))) {
Packit 6ef888
		int err;
Packit 6ef888
Packit 6ef888
		err = build_per_node(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d rebuilding per_node directory\n"),
Packit 6ef888
				 err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	gfs2_lookupi(sdp->master_dir, "per_node", 8, &sdp->md.pinode);
Packit 6ef888
	if (!sdp->md.pinode) {
Packit 6ef888
		log_err( _("Unable to rebuild per_node; aborting.\n"));
Packit 6ef888
		exit(FSCK_ERROR);
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * fetch_rgrps - fetch the resource groups from disk, and check their integrity
Packit 6ef888
 */
Packit 6ef888
static int fetch_rgrps(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	enum rgindex_trust_level trust_lvl;
Packit 6ef888
	int rgcount, sane = 1;
Packit 6ef888
Packit 6ef888
	const char *level_desc[] = {
Packit 6ef888
		_("Checking if all rgrp and rindex values are good"),
Packit 6ef888
		_("Checking if rindex values may be easily repaired"),
Packit 6ef888
		_("Calculating where the rgrps should be if evenly spaced"),
Packit 6ef888
		_("Trying to rebuild rindex assuming evenly spaced rgrps"),
Packit 6ef888
		_("Trying to rebuild rindex assuming unevenly spaced rgrps"),
Packit 6ef888
	};
Packit 6ef888
	const char *fail_desc[] = {
Packit 6ef888
		_("Some damage was found; we need to take remedial measures"),
Packit 6ef888
		_("rindex is unevenly spaced: either gfs1-style or corrupt"),
Packit 6ef888
		_("rindex calculations don't match: uneven rgrp boundaries"),
Packit 6ef888
		_("Too many rgrp misses: rgrps must be unevenly spaced"),
Packit 6ef888
		_("Too much damage found: we cannot rebuild this rindex"),
Packit 6ef888
	};
Packit 6ef888
	/*******************************************************************
Packit 6ef888
	 ********  Validate and read in resource group information  ********
Packit 6ef888
	 *******************************************************************/
Packit 6ef888
	log_notice(_("Validating resource group index.\n"));
Packit 6ef888
	for (trust_lvl = blind_faith; trust_lvl <= indignation; trust_lvl++) {
Packit 6ef888
		int ret = 0;
Packit 6ef888
Packit 6ef888
		log_notice(_("Level %d resource group check: %s.\n"), trust_lvl + 1,
Packit 6ef888
			  level_desc[trust_lvl]);
Packit 6ef888
		if ((rg_repair(sdp, trust_lvl, &rgcount, &sane) == 0) &&
Packit 6ef888
		    ((ret = ri_update(sdp, 0, &rgcount, &sane)) == 0)) {
Packit 6ef888
			log_notice(_("(level %d passed)\n"), trust_lvl + 1);
Packit 6ef888
			break;
Packit 6ef888
		} else {
Packit 6ef888
			if (ret == -1)
Packit 6ef888
				log_err( _("(level %d failed: %s)\n"),
Packit 6ef888
					 trust_lvl + 1, fail_desc[trust_lvl]);
Packit 6ef888
			else
Packit 6ef888
				log_err( _("(level %d failed at block %lld "
Packit 6ef888
					   "(0x%llx): %s)\n"), trust_lvl + 1,
Packit 6ef888
					 (unsigned long long)ret,
Packit 6ef888
					 (unsigned long long)ret,
Packit 6ef888
					 fail_desc[trust_lvl]);
Packit 6ef888
		}
Packit 6ef888
		if (fsck_abort)
Packit 6ef888
			break;
Packit 6ef888
	}
Packit 6ef888
	if (trust_lvl > indignation) {
Packit 6ef888
		log_err( _("Resource group recovery impossible; I can't fix "
Packit 6ef888
			   "this file system.\n"));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	log_info( _("%u resource groups found.\n"), rgcount);
Packit 6ef888
Packit 6ef888
	check_rgrps_integrity(sdp);
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * init_system_inodes
Packit 6ef888
 *
Packit 6ef888
 * Returns: 0 on success, -1 on failure
Packit 6ef888
 */
Packit 6ef888
static int init_system_inodes(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	uint64_t inumbuf = 0;
Packit 6ef888
	char *buf;
Packit 6ef888
	struct gfs2_statfs_change sc;
Packit 6ef888
	int err;
Packit 6ef888
Packit 6ef888
	/*******************************************************************
Packit 6ef888
	 ******************  Initialize important inodes  ******************
Packit 6ef888
	 *******************************************************************/
Packit 6ef888
Packit 6ef888
	log_info( _("Initializing special inodes...\n"));
Packit 6ef888
Packit 6ef888
	/* Get root dinode */
Packit 6ef888
	sdp->md.rooti = lgfs2_inode_read(sdp, sdp->sd_sb.sb_root_dir.no_addr);
Packit 6ef888
	if (sdp->md.rooti == NULL)
Packit 6ef888
		return -1;
Packit 6ef888
Packit 6ef888
	/*******************************************************************
Packit 6ef888
	 *****************  Initialize more system inodes  *****************
Packit 6ef888
	 *******************************************************************/
Packit 6ef888
	if (!sdp->gfs1) {
Packit 6ef888
		/* Look for "inum" entry in master dinode */
Packit 6ef888
		gfs2_lookupi(sdp->master_dir, "inum", 4, &sdp->md.inum);
Packit 6ef888
		if (!sdp->md.inum) {
Packit 6ef888
			if (!query( _("The gfs2 system inum inode is missing. "
Packit 6ef888
				      "Okay to rebuild it? (y/n) "))) {
Packit 6ef888
				log_err( _("fsck.gfs2 cannot continue without "
Packit 6ef888
					   "a valid inum file; aborting.\n"));
Packit 6ef888
				goto fail;
Packit 6ef888
			}
Packit 6ef888
			err = build_inum(sdp);
Packit 6ef888
			if (err) {
Packit 6ef888
				log_crit(_("Error %d rebuilding inum inode\n"),
Packit 6ef888
					 err);
Packit 6ef888
				exit(FSCK_ERROR);
Packit 6ef888
			}
Packit 6ef888
			gfs2_lookupi(sdp->master_dir, "inum", 4,
Packit 6ef888
				     &sdp->md.inum);
Packit 6ef888
			if (!sdp->md.inum) {
Packit 6ef888
				log_crit(_("System inum inode was not rebuilt."
Packit 6ef888
					   " Aborting.\n"));
Packit 6ef888
				goto fail;
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		/* Read inum entry into buffer */
Packit 6ef888
		err = gfs2_readi(sdp->md.inum, &inumbuf, 0,
Packit 6ef888
				 sdp->md.inum->i_di.di_size);
Packit 6ef888
		if (err != sdp->md.inum->i_di.di_size) {
Packit 6ef888
			log_crit(_("Error %d reading system inum inode. "
Packit 6ef888
				   "Aborting.\n"), err);
Packit 6ef888
			goto fail;
Packit 6ef888
		}
Packit 6ef888
		/* call gfs2_inum_range_in() to retrieve range */
Packit 6ef888
		sdp->md.next_inum = be64_to_cpu(inumbuf);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (sdp->gfs1) {
Packit 6ef888
		/* In gfs1, the license_di is always 3 blocks after the jindex_di */
Packit 6ef888
		if ((sbd1->sb_license_di.no_addr != sbd1->sb_jindex_di.no_addr + 3) ||
Packit 6ef888
		    (sbd1->sb_license_di.no_formal_ino != sbd1->sb_jindex_di.no_addr + 3)) {
Packit 6ef888
			if (!query( _("The gfs system statfs inode pointer is incorrect. "
Packit 6ef888
				      "Okay to correct? (y/n) "))) {
Packit 6ef888
				log_err( _("fsck.gfs2 cannot continue without a valid "
Packit 6ef888
					   "statfs file; aborting.\n"));
Packit 6ef888
				goto fail;
Packit 6ef888
			}
Packit 6ef888
			sbd1->sb_license_di.no_addr = sbd1->sb_license_di.no_formal_ino
Packit 6ef888
				= sbd1->sb_jindex_di.no_addr + 3;
Packit 6ef888
		}
Packit 6ef888
Packit 6ef888
		sdp->md.statfs = lgfs2_inode_read(sdp, sbd1->sb_license_di.no_addr);
Packit 6ef888
		if (sdp->md.statfs == NULL) {
Packit 6ef888
			log_crit(_("Error reading statfs inode: %s\n"), strerror(errno));
Packit 6ef888
			goto fail;
Packit 6ef888
		}
Packit 6ef888
	} else
Packit 6ef888
		gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
Packit 6ef888
	if (!sdp->gfs1 && !sdp->md.statfs) {
Packit 6ef888
		if (!query( _("The gfs2 system statfs inode is missing. "
Packit 6ef888
			      "Okay to rebuild it? (y/n) "))) {
Packit 6ef888
			log_err( _("fsck.gfs2 cannot continue without a valid "
Packit 6ef888
				   "statfs file; aborting.\n"));
Packit 6ef888
			goto fail;
Packit 6ef888
		}
Packit 6ef888
		err = build_statfs(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d rebuilding statfs inode\n"), err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
		gfs2_lookupi(sdp->master_dir, "statfs", 6, &sdp->md.statfs);
Packit 6ef888
		if (!sdp->md.statfs) {
Packit 6ef888
			log_err( _("Rebuild of statfs system file failed."));
Packit 6ef888
			log_err( _("fsck.gfs2 cannot continue without "
Packit 6ef888
				   "a valid statfs file; aborting.\n"));
Packit 6ef888
			goto fail;
Packit 6ef888
		}
Packit 6ef888
		do_init_statfs(sdp);
Packit 6ef888
	}
Packit 6ef888
	if (sdp->md.statfs->i_di.di_size) {
Packit 6ef888
		buf = malloc(sdp->md.statfs->i_di.di_size);
Packit 6ef888
		if (buf) {
Packit 6ef888
			err = gfs2_readi(sdp->md.statfs, buf, 0,
Packit 6ef888
					 sdp->md.statfs->i_di.di_size);
Packit 6ef888
			if (err != sdp->md.statfs->i_di.di_size) {
Packit 6ef888
				log_crit(_("Error %d reading statfs file. "
Packit 6ef888
					   "Aborting.\n"), err);
Packit 6ef888
				free(buf);
Packit 6ef888
				goto fail;
Packit 6ef888
			}
Packit 6ef888
			/* call gfs2_inum_range_in() to retrieve range */
Packit 6ef888
			gfs2_statfs_change_in(&sc, buf);
Packit 6ef888
			free(buf);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (sdp->gfs1) {
Packit 6ef888
		/* In gfs1, the quota_di is always 2 blocks after the jindex_di */
Packit 6ef888
		if ((sbd1->sb_quota_di.no_addr != sbd1->sb_jindex_di.no_addr + 2) ||
Packit 6ef888
		    (sbd1->sb_quota_di.no_formal_ino != sbd1->sb_jindex_di.no_addr + 2)) {
Packit 6ef888
			if (!query( _("The gfs system quota inode pointer is incorrect. "
Packit 6ef888
				      " Okay to correct? (y/n) "))) {
Packit 6ef888
				log_err( _("fsck.gfs2 cannot continue without a valid "
Packit 6ef888
					   "quota file; aborting.\n"));
Packit 6ef888
				goto fail;
Packit 6ef888
			}
Packit 6ef888
			sbd1->sb_quota_di.no_addr = sbd1->sb_quota_di.no_formal_ino
Packit 6ef888
				= sbd1->sb_jindex_di.no_addr + 2;
Packit 6ef888
		}
Packit 6ef888
Packit 6ef888
		sdp->md.qinode = lgfs2_inode_read(sdp, sbd1->sb_quota_di.no_addr);
Packit 6ef888
		if (sdp->md.qinode == NULL) {
Packit 6ef888
			log_crit(_("Error reading quota inode: %s\n"), strerror(errno));
Packit 6ef888
			goto fail;
Packit 6ef888
		}
Packit 6ef888
	} else
Packit 6ef888
		gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
Packit 6ef888
	if (!sdp->gfs1 && !sdp->md.qinode) {
Packit 6ef888
		if (!query( _("The gfs2 system quota inode is missing. "
Packit 6ef888
			      "Okay to rebuild it? (y/n) "))) {
Packit 6ef888
			log_crit(_("System quota inode was not "
Packit 6ef888
				   "rebuilt.  Aborting.\n"));
Packit 6ef888
			goto fail;
Packit 6ef888
		}
Packit 6ef888
		err = build_quota(sdp);
Packit 6ef888
		if (err) {
Packit 6ef888
			log_crit(_("Error %d rebuilding quota inode\n"), err);
Packit 6ef888
			exit(FSCK_ERROR);
Packit 6ef888
		}
Packit 6ef888
		gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
Packit 6ef888
		if (!sdp->md.qinode) {
Packit 6ef888
			log_crit(_("Unable to rebuild system quota file "
Packit 6ef888
				   "inode.  Aborting.\n"));
Packit 6ef888
			goto fail;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	/* Try to lookup the per_node inode.  If it was missing, it is now
Packit 6ef888
	   safe to rebuild it. */
Packit 6ef888
	if (!sdp->gfs1)
Packit 6ef888
		lookup_per_node(sdp, 1);
Packit 6ef888
Packit 6ef888
	/*******************************************************************
Packit 6ef888
	 *******  Now, set boundary fields in the super block  *************
Packit 6ef888
	 *******************************************************************/
Packit 6ef888
	if (set_block_ranges(sdp)){
Packit 6ef888
		log_err( _("Unable to determine the boundaries of the"
Packit 6ef888
			" file system.\n"));
Packit 6ef888
		goto fail;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	return 0;
Packit 6ef888
 fail:
Packit 6ef888
	empty_super_block(sdp);
Packit 6ef888
Packit 6ef888
	return -1;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * is_journal_copy - Is this a "real" dinode or a copy inside a journal?
Packit 6ef888
 * A real dinode will be located at the block number in its no_addr.
Packit 6ef888
 * A journal-copy will be at a different block (inside the journal).
Packit 6ef888
 */
Packit 6ef888
static int is_journal_copy(struct gfs2_inode *ip, struct gfs2_buffer_head *bh)
Packit 6ef888
{
Packit 6ef888
	if (ip->i_di.di_num.no_addr == bh->b_blocknr)
Packit 6ef888
		return 0;
Packit 6ef888
	return 1; /* journal copy */
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * peruse_system_dinode - process a system dinode
Packit 6ef888
 *
Packit 6ef888
 * This function looks at a system dinode and tries to figure out which
Packit 6ef888
 * dinode it is: statfs, inum, per_node, master, etc.  Some of them we
Packit 6ef888
 * can deduce from the contents.  For example, di_size will be a multiple
Packit 6ef888
 * of 96 for the rindex.  di_size will be 8 for inum, 24 for statfs, etc.
Packit 6ef888
 * the per_node directory will have a ".." entry that will lead us to
Packit 6ef888
 * the master dinode if it's been destroyed.
Packit 6ef888
 */
Packit 6ef888
static void peruse_system_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
Packit 6ef888
				 struct gfs2_buffer_head *bh)
Packit 6ef888
{
Packit 6ef888
	struct gfs2_inode *ip, *child_ip;
Packit 6ef888
	struct gfs2_inum inum;
Packit 6ef888
	int error;
Packit 6ef888
Packit 6ef888
	if (di->di_num.no_formal_ino == 2) {
Packit 6ef888
		if (sdp->sd_sb.sb_master_dir.no_addr)
Packit 6ef888
			return;
Packit 6ef888
		log_warn(_("Found system master directory at: 0x%llx.\n"),
Packit 6ef888
			 di->di_num.no_addr);
Packit 6ef888
		sdp->sd_sb.sb_master_dir.no_addr = di->di_num.no_addr;
Packit 6ef888
		return;
Packit 6ef888
	}
Packit 6ef888
	ip = lgfs2_inode_read(sdp, di->di_num.no_addr);
Packit 6ef888
	if (ip == NULL) {
Packit 6ef888
		log_crit(_("Error reading inode: %s\n"), strerror(errno));
Packit 6ef888
		return;
Packit 6ef888
	}
Packit 6ef888
	if ((!sdp->gfs1 && di->di_num.no_formal_ino == 3) ||
Packit 6ef888
	    (sdp->gfs1 && (di->di_flags & GFS2_DIF_JDATA) &&
Packit 6ef888
	     (di->di_size % sizeof(struct gfs_jindex) == 0))) {
Packit 6ef888
		if (fix_md.jiinode || is_journal_copy(ip, bh))
Packit 6ef888
			goto out_discard_ip;
Packit 6ef888
		log_warn(_("Found system jindex file at: 0x%llx\n"),
Packit 6ef888
			 di->di_num.no_addr);
Packit 6ef888
		fix_md.jiinode = ip;
Packit 6ef888
	} else if (!sdp->gfs1 && is_dir(di, sdp->gfs1)) {
Packit 6ef888
		/* Check for a jindex dir entry. Only one system dir has a
Packit 6ef888
		   jindex: master */
Packit 6ef888
		gfs2_lookupi(ip, "jindex", 6, &child_ip);
Packit 6ef888
		if (child_ip) {
Packit 6ef888
			if (fix_md.jiinode || is_journal_copy(ip, bh)) {
Packit 6ef888
				inode_put(&child_ip);
Packit 6ef888
				goto out_discard_ip;
Packit 6ef888
			}
Packit 6ef888
			fix_md.jiinode = child_ip;
Packit 6ef888
			sdp->sd_sb.sb_master_dir.no_addr = di->di_num.no_addr;
Packit 6ef888
			log_warn(_("Found system master directory at: "
Packit 6ef888
				   "0x%llx\n"), di->di_num.no_addr);
Packit 6ef888
			return;
Packit 6ef888
		}
Packit 6ef888
Packit 6ef888
		/* Check for a statfs_change0 dir entry. Only one system dir
Packit 6ef888
		   has a statfs_change: per_node, and its .. will be master. */
Packit 6ef888
		gfs2_lookupi(ip, "statfs_change0", 14, &child_ip);
Packit 6ef888
		if (child_ip) {
Packit 6ef888
			inode_put(&child_ip);
Packit 6ef888
			if (fix_md.pinode || is_journal_copy(ip, bh))
Packit 6ef888
				goto out_discard_ip;
Packit 6ef888
			log_warn(_("Found system per_node directory at: "
Packit 6ef888
				   "0x%llx\n"), ip->i_di.di_num.no_addr);
Packit 6ef888
			fix_md.pinode = ip;
Packit 6ef888
			error = dir_search(ip, "..", 2, NULL, &inum);
Packit 6ef888
			if (!error && inum.no_addr) {
Packit 6ef888
				sdp->sd_sb.sb_master_dir.no_addr =
Packit 6ef888
					inum.no_addr;
Packit 6ef888
				log_warn(_("From per_node\'s \'..\' I "
Packit 6ef888
					   "backtracked the master directory "
Packit 6ef888
					   "to: 0x%llx\n"), inum.no_addr);
Packit 6ef888
			}
Packit 6ef888
			return;
Packit 6ef888
		}
Packit 6ef888
		log_debug(_("Unknown system directory at block 0x%llx\n"),
Packit 6ef888
			  di->di_num.no_addr);
Packit 6ef888
		goto out_discard_ip;
Packit 6ef888
	} else if (!sdp->gfs1 && di->di_size == 8) {
Packit 6ef888
		if (fix_md.inum || is_journal_copy(ip, bh))
Packit 6ef888
			goto out_discard_ip;
Packit 6ef888
		fix_md.inum = ip;
Packit 6ef888
		log_warn(_("Found system inum file at: 0x%llx\n"),
Packit 6ef888
			 di->di_num.no_addr);
Packit 6ef888
	} else if (di->di_size == 24) {
Packit 6ef888
		if (fix_md.statfs || is_journal_copy(ip, bh))
Packit 6ef888
			goto out_discard_ip;
Packit 6ef888
		fix_md.statfs = ip;
Packit 6ef888
		log_warn(_("Found system statfs file at: 0x%llx\n"),
Packit 6ef888
			 di->di_num.no_addr);
Packit 6ef888
	} else if ((di->di_size % 96) == 0) {
Packit 6ef888
		if (fix_md.riinode || is_journal_copy(ip, bh))
Packit 6ef888
			goto out_discard_ip;
Packit 6ef888
		fix_md.riinode = ip;
Packit 6ef888
		log_warn(_("Found system rindex file at: 0x%llx\n"),
Packit 6ef888
			 di->di_num.no_addr);
Packit 6ef888
	} else if (!fix_md.qinode && di->di_size >= 176 &&
Packit 6ef888
		   di->di_num.no_formal_ino >= 12 &&
Packit 6ef888
		   di->di_num.no_formal_ino <= 100) {
Packit 6ef888
		if (is_journal_copy(ip, bh))
Packit 6ef888
			goto out_discard_ip;
Packit 6ef888
		fix_md.qinode = ip;
Packit 6ef888
		log_warn(_("Found system quota file at: 0x%llx\n"),
Packit 6ef888
			 di->di_num.no_addr);
Packit 6ef888
	} else {
Packit 6ef888
out_discard_ip:
Packit 6ef888
		inode_put(&ip);
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * peruse_user_dinode - process a user dinode trying to find the root directory
Packit 6ef888
 *
Packit 6ef888
 */
Packit 6ef888
static void peruse_user_dinode(struct gfs2_sbd *sdp, struct gfs2_dinode *di,
Packit 6ef888
			       struct gfs2_buffer_head *bh)
Packit 6ef888
{
Packit 6ef888
	struct gfs2_inode *ip, *parent_ip;
Packit 6ef888
	struct gfs2_inum inum;
Packit 6ef888
	int error;
Packit 6ef888
Packit 6ef888
	if (sdp->sd_sb.sb_root_dir.no_addr) /* if we know the root dinode */
Packit 6ef888
		return;             /* we don't need to find the root */
Packit 6ef888
	if (!is_dir(di, sdp->gfs1))  /* if this isn't a directory */
Packit 6ef888
		return;             /* it can't lead us to the root anyway */
Packit 6ef888
Packit 6ef888
	if (di->di_num.no_formal_ino == 1) {
Packit 6ef888
		struct gfs2_buffer_head *root_bh;
Packit 6ef888
Packit 6ef888
		if (di->di_num.no_addr == bh->b_blocknr) {
Packit 6ef888
			log_warn(_("Found the root directory at: 0x%llx.\n"),
Packit 6ef888
				 di->di_num.no_addr);
Packit 6ef888
			sdp->sd_sb.sb_root_dir.no_addr = di->di_num.no_addr;
Packit 6ef888
			return;
Packit 6ef888
		}
Packit 6ef888
		log_warn(_("The root dinode should be at block 0x%llx but it "
Packit 6ef888
			   "seems to be destroyed.\n"),
Packit 6ef888
			 (unsigned long long)di->di_num.no_addr);
Packit 6ef888
		log_warn(_("Found a copy of the root directory in a journal "
Packit 6ef888
			   "at block: 0x%llx.\n"),
Packit 6ef888
			 (unsigned long long)bh->b_blocknr);
Packit 6ef888
		if (!query(_("Do you want to replace the root dinode from the "
Packit 6ef888
			     "copy? (y/n)"))) {
Packit 6ef888
			log_err(_("Damaged root dinode not fixed.\n"));
Packit 6ef888
			return;
Packit 6ef888
		}
Packit 6ef888
		root_bh = bread(sdp, di->di_num.no_addr);
Packit 6ef888
		memcpy(root_bh->b_data, bh->b_data, sdp->bsize);
Packit 6ef888
		bmodified(root_bh);
Packit 6ef888
		brelse(root_bh);
Packit 6ef888
		log_warn(_("Root directory copied from the journal.\n"));
Packit 6ef888
		return;
Packit 6ef888
	}
Packit 6ef888
	ip = lgfs2_inode_read(sdp, di->di_num.no_addr);
Packit 6ef888
	if (ip == NULL) {
Packit 6ef888
		log_crit(_("Error reading inode: %s\n"), strerror(errno));
Packit 6ef888
		return;
Packit 6ef888
	}
Packit 6ef888
	while (ip) {
Packit 6ef888
		gfs2_lookupi(ip, "..", 2, &parent_ip);
Packit 6ef888
		if (parent_ip && parent_ip->i_di.di_num.no_addr ==
Packit 6ef888
		    ip->i_di.di_num.no_addr) {
Packit 6ef888
			log_warn(_("Found the root directory at: 0x%llx\n"),
Packit 6ef888
				 ip->i_di.di_num.no_addr);
Packit 6ef888
			sdp->sd_sb.sb_root_dir.no_addr =
Packit 6ef888
				ip->i_di.di_num.no_addr;
Packit 6ef888
			inode_put(&parent_ip);
Packit 6ef888
			inode_put(&ip);
Packit 6ef888
			return;
Packit 6ef888
		}
Packit 6ef888
		if (!parent_ip)
Packit 6ef888
			break;
Packit 6ef888
		inode_put(&ip);
Packit 6ef888
		ip = parent_ip;
Packit 6ef888
	}
Packit 6ef888
	error = dir_search(ip, "..", 2, NULL, &inum);
Packit 6ef888
	if (!error && inum.no_addr && inum.no_addr < possible_root) {
Packit 6ef888
			possible_root = inum.no_addr;
Packit 6ef888
			log_debug(_("Found a possible root at: 0x%llx\n"),
Packit 6ef888
				  (unsigned long long)possible_root);
Packit 6ef888
	}
Packit 6ef888
	inode_put(&ip);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * find_rgs_for_bsize - check a range of blocks for rgrps to determine bsize.
Packit 6ef888
 * Assumes: device is open.
Packit 6ef888
 */
Packit 6ef888
static int find_rgs_for_bsize(struct gfs2_sbd *sdp, uint64_t startblock,
Packit 6ef888
			      uint32_t *known_bsize)
Packit 6ef888
{
Packit 6ef888
	uint64_t blk, max_rg_size, rb_addr;
Packit 6ef888
	struct gfs2_buffer_head *bh, *rb_bh;
Packit 6ef888
	uint32_t bsize, bsize2;
Packit 6ef888
	uint32_t chk;
Packit 6ef888
	char *p;
Packit 6ef888
	int found_rg;
Packit 6ef888
	struct gfs2_meta_header mh;
Packit 6ef888
Packit 6ef888
	sdp->bsize = GFS2_DEFAULT_BSIZE;
Packit 6ef888
	max_rg_size = 524288;
Packit 6ef888
	/* Max RG size is 2GB. Max block size is 4K. 2G / 4K blks = 524288,
Packit 6ef888
	   So this is traversing 2GB in 4K block increments. */
Packit 6ef888
	for (blk = startblock; blk < startblock + max_rg_size; blk++) {
Packit 6ef888
		bh = bread(sdp, blk);
Packit 6ef888
		found_rg = 0;
Packit 6ef888
		for (bsize = 0; bsize < GFS2_DEFAULT_BSIZE;
Packit 6ef888
		     bsize += GFS2_BASIC_BLOCK) {
Packit 6ef888
			p = bh->b_data + bsize;
Packit 6ef888
			chk = ((struct gfs2_meta_header *)p)->mh_magic;
Packit 6ef888
			if (be32_to_cpu(chk) != GFS2_MAGIC)
Packit 6ef888
				continue;
Packit 6ef888
			chk = ((struct gfs2_meta_header *)p)->mh_type;
Packit 6ef888
			if (be32_to_cpu(chk) == GFS2_METATYPE_RG) {
Packit 6ef888
				found_rg = 1;
Packit 6ef888
				break;
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		if (!found_rg)
Packit 6ef888
			continue;
Packit 6ef888
		/* Try all the block sizes in 512 byte multiples */
Packit 6ef888
		for (bsize2 = GFS2_BASIC_BLOCK; bsize2 <= GFS2_DEFAULT_BSIZE;
Packit 6ef888
		     bsize2 += GFS2_BASIC_BLOCK) {
Packit 6ef888
			rb_addr = (bh->b_blocknr *
Packit 6ef888
				   (GFS2_DEFAULT_BSIZE / bsize2)) +
Packit 6ef888
				(bsize / bsize2) + 1;
Packit 6ef888
			sdp->bsize = bsize2; /* temporarily */
Packit 6ef888
			rb_bh = bread(sdp, rb_addr);
Packit 6ef888
			gfs2_meta_header_in(&mh, rb_bh->b_data);
Packit 6ef888
			brelse(rb_bh);
Packit 6ef888
			if (mh.mh_magic == GFS2_MAGIC &&
Packit 6ef888
			    mh.mh_type == GFS2_METATYPE_RB) {
Packit 6ef888
				log_debug(_("boff:%d bsize2:%d rg:0x%llx, "
Packit 6ef888
					    "rb:0x%llx\n"), bsize, bsize2,
Packit 6ef888
					  (unsigned long long)blk,
Packit 6ef888
					  (unsigned long long)rb_addr);
Packit 6ef888
				*known_bsize = bsize2;
Packit 6ef888
				break;
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		brelse(bh);
Packit 6ef888
		if (!(*known_bsize)) {
Packit 6ef888
			sdp->bsize = GFS2_DEFAULT_BSIZE;
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
Packit 6ef888
		sdp->bsize = *known_bsize;
Packit 6ef888
		log_warn(_("Block size determined to be: %d\n"), *known_bsize);
Packit 6ef888
		return 0;
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * peruse_metadata - check a range of blocks for metadata
Packit 6ef888
 * Assumes: device is open.
Packit 6ef888
 */
Packit 6ef888
static int peruse_metadata(struct gfs2_sbd *sdp, uint64_t startblock)
Packit 6ef888
{
Packit 6ef888
	uint64_t blk, max_rg_size;
Packit 6ef888
	struct gfs2_buffer_head *bh;
Packit 6ef888
	struct gfs2_dinode di;
Packit 6ef888
Packit 6ef888
	max_rg_size = 2147483648ull / sdp->bsize;
Packit 6ef888
	/* Max RG size is 2GB. 2G / bsize. */
Packit 6ef888
	for (blk = startblock; blk < startblock + max_rg_size; blk++) {
Packit 6ef888
		bh = bread(sdp, blk);
Packit 6ef888
		if (gfs2_check_meta(bh, GFS2_METATYPE_DI)) {
Packit 6ef888
			brelse(bh);
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
		gfs2_dinode_in(&di, bh->b_data);
Packit 6ef888
		if (di.di_flags & GFS2_DIF_SYSTEM)
Packit 6ef888
			peruse_system_dinode(sdp, &di, bh);
Packit 6ef888
		else
Packit 6ef888
			peruse_user_dinode(sdp, &di, bh);
Packit 6ef888
		brelse(bh);
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * sb_repair - repair a damaged superblock
Packit 6ef888
 * Assumes: device is open.
Packit 6ef888
 *          The biggest RG size is 2GB
Packit 6ef888
 */
Packit 6ef888
static int sb_repair(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	uint64_t half;
Packit 6ef888
	uint32_t known_bsize = 0;
Packit 6ef888
	int error = 0;
Packit 6ef888
Packit 6ef888
	memset(&fix_md, 0, sizeof(fix_md));
Packit 6ef888
	/* Step 1 - First we need to determine the correct block size. */
Packit 6ef888
	sdp->bsize = GFS2_DEFAULT_BSIZE;
Packit 6ef888
	log_warn(_("Gathering information to repair the gfs2 superblock.  "
Packit 6ef888
		   "This may take some time.\n"));
Packit 6ef888
	error = find_rgs_for_bsize(sdp, (GFS2_SB_ADDR * GFS2_BASIC_BLOCK) /
Packit 6ef888
				   GFS2_DEFAULT_BSIZE, &known_bsize);
Packit 6ef888
	if (error)
Packit 6ef888
		return error;
Packit 6ef888
	if (!known_bsize) {
Packit 6ef888
		log_warn(_("Block size not apparent; checking elsewhere.\n"));
Packit 6ef888
		/* First, figure out the device size.  We need that so we can
Packit 6ef888
		   find a suitable start point to determine what's what. */
Packit 6ef888
		half = sdp->dinfo.size / 2; /* in bytes */
Packit 6ef888
		half /= sdp->bsize;
Packit 6ef888
		/* Start looking halfway through the device for gfs2
Packit 6ef888
		   structures.  If there aren't any at all, forget it. */
Packit 6ef888
		error = find_rgs_for_bsize(sdp, half, &known_bsize);
Packit 6ef888
		if (error)
Packit 6ef888
			return error;
Packit 6ef888
	}
Packit 6ef888
	if (!known_bsize) {
Packit 6ef888
		log_err(_("Unable to determine the block size; this "
Packit 6ef888
			  "does not look like a gfs2 file system.\n"));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	/* Step 2 - look for the sytem dinodes */
Packit 6ef888
	error = peruse_metadata(sdp, (GFS2_SB_ADDR * GFS2_BASIC_BLOCK) /
Packit 6ef888
				GFS2_DEFAULT_BSIZE);
Packit 6ef888
	if (error)
Packit 6ef888
		return error;
Packit 6ef888
	if (!sdp->sd_sb.sb_master_dir.no_addr) {
Packit 6ef888
		log_err(_("Unable to locate the system master  directory.\n"));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	if (!sdp->sd_sb.sb_root_dir.no_addr) {
Packit 6ef888
		struct gfs2_inum inum;
Packit 6ef888
Packit 6ef888
		log_err(_("Unable to locate the root directory.\n"));
Packit 6ef888
		if (possible_root == HIGHEST_BLOCK) {
Packit 6ef888
			/* Take advantage of the fact that mkfs.gfs2
Packit 6ef888
			   creates master immediately after root. */
Packit 6ef888
			log_err(_("Can't find any dinodes that might "
Packit 6ef888
				  "be the root; using master - 1.\n"));
Packit 6ef888
			possible_root = sdp->sd_sb.sb_master_dir.no_addr - 1;
Packit 6ef888
		}
Packit 6ef888
		log_err(_("Found a possible root at: 0x%llx\n"),
Packit 6ef888
			(unsigned long long)possible_root);
Packit 6ef888
		sdp->sd_sb.sb_root_dir.no_addr = possible_root;
Packit 6ef888
		sdp->md.rooti = lgfs2_inode_read(sdp, possible_root);
Packit 6ef888
		if (!sdp->md.rooti ||
Packit 6ef888
		    sdp->md.rooti->i_di.di_header.mh_magic != GFS2_MAGIC) {
Packit 6ef888
			struct gfs2_buffer_head *bh = NULL;
Packit 6ef888
Packit 6ef888
			log_err(_("The root dinode block is destroyed.\n"));
Packit 6ef888
			log_err(_("At this point I recommend "
Packit 6ef888
				  "reinitializing it.\n"
Packit 6ef888
				  "Hopefully everything will later "
Packit 6ef888
				  "be put into lost+found.\n"));
Packit 6ef888
			if (!query(_("Okay to reinitialize the root "
Packit 6ef888
				     "dinode? (y/n)"))) {
Packit 6ef888
				log_err(_("The root dinode was not "
Packit 6ef888
					  "reinitialized; aborting.\n"));
Packit 6ef888
				return -1;
Packit 6ef888
			}
Packit 6ef888
			inum.no_formal_ino = 1;
Packit 6ef888
			inum.no_addr = possible_root;
Packit 6ef888
			error = init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, 0, &inum);
Packit 6ef888
			if (error != 0)
Packit 6ef888
				return -1;
Packit 6ef888
			brelse(bh);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	/* Step 3 - Rebuild the lock protocol and file system table name */
Packit 6ef888
	if (query(_("Okay to fix the GFS2 superblock? (y/n)"))) {
Packit 6ef888
		struct gfs2_sb sb;
Packit 6ef888
		log_info(_("Found system master directory at: 0x%llx\n"),
Packit 6ef888
			 sdp->sd_sb.sb_master_dir.no_addr);
Packit 6ef888
		sdp->master_dir = lgfs2_inode_read(sdp,
Packit 6ef888
					     sdp->sd_sb.sb_master_dir.no_addr);
Packit 6ef888
		if (sdp->master_dir == NULL) {
Packit 6ef888
			log_crit(_("Error reading master inode: %s\n"), strerror(errno));
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
		sdp->master_dir->i_di.di_num.no_addr =
Packit 6ef888
			sdp->sd_sb.sb_master_dir.no_addr;
Packit 6ef888
		log_info(_("Found the root directory at: 0x%llx\n"),
Packit 6ef888
			 sdp->sd_sb.sb_root_dir.no_addr);
Packit 6ef888
		sdp->md.rooti = lgfs2_inode_read(sdp,
Packit 6ef888
					   sdp->sd_sb.sb_root_dir.no_addr);
Packit 6ef888
		if (sdp->md.rooti == NULL) {
Packit 6ef888
			log_crit(_("Error reading root inode: %s\n"), strerror(errno));
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
		lgfs2_sb_init(&sb, sdp->bsize);
Packit 6ef888
		strcpy(sb.sb_lockproto, GFS2_DEFAULT_LOCKPROTO);
Packit 6ef888
		strcpy(sb.sb_locktable, "unknown");
Packit 6ef888
		sb.sb_master_dir = sdp->master_dir->i_di.di_num;
Packit 6ef888
		sb.sb_root_dir = sdp->md.rooti->i_di.di_num;
Packit 6ef888
		lgfs2_sb_write(&sb, sdp->device_fd, sdp->bsize);
Packit 6ef888
		inode_put(&sdp->md.rooti);
Packit 6ef888
		inode_put(&sdp->master_dir);
Packit 6ef888
		sb_fixed = 1;
Packit 6ef888
	} else {
Packit 6ef888
		log_crit(_("GFS2 superblock not fixed; fsck cannot proceed "
Packit 6ef888
			   "without a valid superblock.\n"));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * fill_super_block
Packit 6ef888
 * @sdp:
Packit 6ef888
 *
Packit 6ef888
 * Returns: 0 on success, -1 on failure
Packit 6ef888
 */
Packit 6ef888
static int fill_super_block(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	int ret;
Packit 6ef888
Packit 6ef888
	sync();
Packit 6ef888
Packit 6ef888
	/********************************************************************
Packit 6ef888
	 ***************** First, initialize all lists **********************
Packit 6ef888
	 ********************************************************************/
Packit 6ef888
	log_info( _("Initializing lists...\n"));
Packit 6ef888
	sdp->rgtree.osi_node = NULL;
Packit 6ef888
Packit 6ef888
	/********************************************************************
Packit 6ef888
	 ************  next, read in on-disk SB and set constants  **********
Packit 6ef888
	 ********************************************************************/
Packit 6ef888
	sdp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
Packit 6ef888
	sdp->bsize = sdp->sd_sb.sb_bsize;
Packit 6ef888
Packit 6ef888
	if (sizeof(struct gfs2_sb) > sdp->sd_sb.sb_bsize){
Packit 6ef888
		log_crit( _("GFS superblock is larger than the blocksize!\n"));
Packit 6ef888
		log_debug("sizeof(struct gfs2_sb) > sdp->sd_sb.sb_bsize\n");
Packit Service 786bf1
		return FSCK_ERROR;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (compute_constants(sdp)) {
Packit 6ef888
		log_crit("%s\n", _("Failed to compute file system constants"));
Packit Service 786bf1
		return FSCK_ERROR;
Packit 6ef888
	}
Packit 6ef888
	ret = read_sb(sdp);
Packit 6ef888
	if (ret < 0) {
Packit 6ef888
		if (sb_repair(sdp) != 0)
Packit 6ef888
			return -1; /* unrepairable, so exit */
Packit 6ef888
		/* Now that we've tried to repair it, re-read it. */
Packit 6ef888
		ret = read_sb(sdp);
Packit 6ef888
		if (ret < 0)
Packit Service 786bf1
			return FSCK_ERROR;
Packit 6ef888
	}
Packit 6ef888
	if (sdp->gfs1)
Packit 6ef888
		sbd1 = (struct gfs_sb *)&sdp->sd_sb;
Packit Service 786bf1
	else if (sdp->sd_sb.sb_fs_format > FSCK_MAX_FORMAT) {
Packit Service 786bf1
		log_crit(_("Unsupported gfs2 format found: %"PRIu32"\n"), sdp->sd_sb.sb_fs_format);
Packit Service 786bf1
		log_crit(_("A newer fsck.gfs2 is required to check this file system.\n"));
Packit Service 786bf1
		return FSCK_USAGE;
Packit Service 786bf1
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static void gfs_log_header_out(struct gfs_log_header *head, char *buf)
Packit 6ef888
{
Packit 6ef888
        struct gfs_log_header *str = (struct gfs_log_header *) buf;
Packit 6ef888
Packit 6ef888
	str->lh_header.mh_magic = cpu_to_be32(head->lh_header.mh_magic);
Packit 6ef888
	str->lh_header.mh_type = cpu_to_be32(head->lh_header.mh_type);
Packit 6ef888
	str->lh_header.mh_format = cpu_to_be32(head->lh_header.mh_format);
Packit 6ef888
	str->lh_header.__pad0 = cpu_to_be32(head->lh_header.__pad0);
Packit 6ef888
Packit 6ef888
	str->lh_flags = cpu_to_be32(head->lh_flags);
Packit 6ef888
	str->lh_pad = cpu_to_be32(head->lh_pad);
Packit 6ef888
	str->lh_first = cpu_to_be64(head->lh_first);
Packit 6ef888
	str->lh_sequence = cpu_to_be64(head->lh_sequence);
Packit 6ef888
	str->lh_tail = cpu_to_be64(head->lh_tail);
Packit 6ef888
	str->lh_last_dump = cpu_to_be64(head->lh_last_dump);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * reconstruct_single_journal - write a fresh GFS1 journal
Packit 6ef888
 * @sdp: superblock
Packit 6ef888
 * @jnum: journal number
Packit 6ef888
 *
Packit 6ef888
 * This function will write a fresh journal over the top of
Packit 6ef888
 * the previous journal.  All journal information is lost.  This
Packit 6ef888
 * process is basically stolen from write_journals() in the mkfs code.
Packit 6ef888
 *
Packit 6ef888
 * Returns: -1 on error, 0 otherwise
Packit 6ef888
 */
Packit 6ef888
static int reconstruct_single_journal(struct gfs2_sbd *sdp, int jnum,
Packit 6ef888
				      uint32_t ji_nsegment)
Packit 6ef888
{
Packit 6ef888
	struct gfs_log_header lh;
Packit 6ef888
	uint32_t seg, sequence;
Packit 6ef888
	struct gfs2_buffer_head *bh;
Packit 6ef888
Packit 6ef888
	srandom(time(NULL));
Packit 6ef888
	sequence = ji_nsegment / (RAND_MAX + 1.0) * random();
Packit 6ef888
Packit 6ef888
	log_info(_("Clearing journal %d\n"), jnum);
Packit 6ef888
Packit 6ef888
	for (seg = 0; seg < ji_nsegment; seg++){
Packit 6ef888
		memset(&lh, 0, sizeof(struct gfs_log_header));
Packit 6ef888
Packit 6ef888
		lh.lh_header.mh_magic = GFS2_MAGIC;
Packit 6ef888
		lh.lh_header.mh_type = GFS2_METATYPE_LH;
Packit 6ef888
		lh.lh_header.mh_format = GFS2_FORMAT_LH;
Packit 6ef888
		lh.lh_header.__pad0 = 0x101674; /* mh_generation */
Packit 6ef888
		lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
Packit 6ef888
		lh.lh_first = sdp->md.journal[jnum]->i_di.di_num.no_addr +
Packit 6ef888
			(seg * sbd1->sb_seg_size);
Packit 6ef888
		lh.lh_sequence = sequence;
Packit 6ef888
Packit 6ef888
		bh = bget(sdp, lh.lh_first * sdp->bsize);
Packit 6ef888
		memset(bh->b_data, 0, sdp->bsize);
Packit 6ef888
		gfs_log_header_out(&lh, bh->b_data);
Packit 6ef888
		gfs_log_header_out(&lh, bh->b_data + GFS2_BASIC_BLOCK -
Packit 6ef888
				   sizeof(struct gfs_log_header));
Packit 6ef888
		brelse(bh);
Packit 6ef888
Packit 6ef888
		if (++sequence == ji_nsegment)
Packit 6ef888
			sequence = 0;
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int reset_journal_seg_size(unsigned int jsize, unsigned int nsegs,
Packit 6ef888
					     unsigned int bsize)
Packit 6ef888
{
Packit 6ef888
	unsigned int seg_size = jsize / (nsegs * bsize);
Packit 6ef888
	if (!seg_size)
Packit 6ef888
		seg_size = 16; /* The default with 128MB journal and 4K bsize */
Packit 6ef888
	if (seg_size != sbd1->sb_seg_size) {
Packit 6ef888
		sbd1->sb_seg_size = seg_size;
Packit 6ef888
		if (!query(_("Computed correct journal segment size to %u."
Packit 6ef888
			     " Reset it? (y/n) "), seg_size)) {
Packit 6ef888
			log_crit(_("Error: Cannot proceed without a valid journal"
Packit 6ef888
				   " segment size value.\n"));
Packit 6ef888
			return -1;
Packit 6ef888
		}
Packit 6ef888
		log_err(_("Resetting journal segment size to %u\n"), sbd1->sb_seg_size);
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int correct_journal_seg_size(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	int count;
Packit 6ef888
	struct gfs_jindex ji_0, ji_1;
Packit 6ef888
	char buf[sizeof(struct gfs_jindex)];
Packit 6ef888
	unsigned int jsize = GFS2_DEFAULT_JSIZE * 1024 * 1024;
Packit 6ef888
Packit 6ef888
	count = gfs2_readi(sdp->md.jiinode, buf, 0, sizeof(struct gfs_jindex));
Packit 6ef888
	if (count != sizeof(struct gfs_jindex)) {
Packit 6ef888
		log_crit(_("Error %d reading system journal index inode. "
Packit 6ef888
			   "Aborting\n"), count);
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	gfs_jindex_in(&ji_0, buf);
Packit 6ef888
Packit 6ef888
	if (sdp->md.journals == 1) {
Packit 6ef888
		if (sbd1->sb_seg_size == 0) {
Packit 6ef888
			if (!query(_("The gfs2 journal segment size is 0 and a"
Packit 6ef888
				     " correct value cannot be determined in a"
Packit 6ef888
				     " single-journal filesystem.\n"
Packit 6ef888
				     "Continue with default? (y/n) "))) {
Packit 6ef888
				log_crit(_("Error: Cannot proceed without a valid"
Packit 6ef888
					   " sb_seg_size value.\n"));
Packit 6ef888
				return -1;
Packit 6ef888
			}
Packit 6ef888
			goto out;
Packit 6ef888
		}
Packit 6ef888
		/* Don't mess with sb_seg_size because we don't know what
Packit 6ef888
		 * it needs to be
Packit 6ef888
		 */
Packit 6ef888
		return 0;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	count = gfs2_readi(sdp->md.jiinode, buf, sizeof(struct gfs_jindex),
Packit 6ef888
			   sizeof(struct gfs_jindex));
Packit 6ef888
	if (count != sizeof(struct gfs_jindex)) {
Packit 6ef888
		log_crit(_("Error %d reading system journal index inode. "
Packit 6ef888
			   "Aborting\n"), count);
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	gfs_jindex_in(&ji_1, buf);
Packit 6ef888
Packit 6ef888
	jsize = (ji_1.ji_addr - ji_0.ji_addr) * sbd1->sb_bsize;
Packit 6ef888
out:
Packit 6ef888
	return reset_journal_seg_size(jsize, ji_0.ji_nsegment, sbd1->sb_bsize);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/*
Packit 6ef888
 * reconstruct_journals - write fresh journals for GFS1 only
Packit 6ef888
 * sdp: the super block
Packit 6ef888
 *
Packit 6ef888
 * Returns: 0 on success, -1 on failure
Packit 6ef888
 */
Packit 6ef888
static int reconstruct_journals(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	int i, count;
Packit 6ef888
	struct gfs_jindex ji;
Packit 6ef888
	char buf[sizeof(struct gfs_jindex)];
Packit 6ef888
Packit 6ef888
	/* Ensure that sb_seg_size is valid */
Packit 6ef888
	if (correct_journal_seg_size(sdp)) {
Packit 6ef888
		log_crit(_("Failed to set correct journal segment size. Cannot continue\n"));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	log_err(_("Clearing GFS journals (this may take a while)\n"));
Packit 6ef888
	for (i = 0; i < sdp->md.journals; i++) {
Packit 6ef888
		count = gfs2_readi(sdp->md.jiinode, buf,
Packit 6ef888
				   i * sizeof(struct gfs_jindex),
Packit 6ef888
				   sizeof(struct gfs_jindex));
Packit 6ef888
		if (count != sizeof(struct gfs_jindex))
Packit 6ef888
			return 0;
Packit 6ef888
		gfs_jindex_in(&ji, buf);
Packit 6ef888
		if ((i % 2) == 0)
Packit 6ef888
			log_err(".");
Packit 6ef888
		if (reconstruct_single_journal(sdp, i, ji.ji_nsegment))
Packit 6ef888
			return -1;
Packit 6ef888
	}
Packit 6ef888
	log_err(_("\nJournals cleared.\n"));
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * init_rindex - read in the rindex file
Packit 6ef888
 */
Packit 6ef888
static int init_rindex(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	int err;
Packit 6ef888
Packit 6ef888
	if (sdp->gfs1)
Packit 6ef888
		sdp->md.riinode = lgfs2_inode_read(sdp, sbd1->sb_rindex_di.no_addr);
Packit 6ef888
	else
Packit 6ef888
		gfs2_lookupi(sdp->master_dir, "rindex", 6, &sdp->md.riinode);
Packit 6ef888
Packit 6ef888
	if (sdp->md.riinode)
Packit 6ef888
		return 0;
Packit 6ef888
Packit 6ef888
	if (!query( _("The gfs2 system rindex inode is missing. "
Packit 6ef888
		      "Okay to rebuild it? (y/n) "))) {
Packit 6ef888
		log_crit(_("Error: Cannot proceed without a valid rindex.\n"));
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	if ((err = build_rindex(sdp))) {
Packit 6ef888
		log_crit(_("Error %d rebuilding rindex\n"), err);
Packit 6ef888
		return -1;
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * initialize - initialize superblock pointer
Packit 6ef888
 *
Packit 6ef888
 */
Packit 6ef888
int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
Packit 6ef888
	       int *all_clean)
Packit 6ef888
{
Packit 6ef888
	int clean_journals = 0, open_flag;
Packit Service 786bf1
	int err;
Packit 6ef888
Packit 6ef888
	*all_clean = 0;
Packit 6ef888
Packit 6ef888
	if (opts.no)
Packit 6ef888
		open_flag = O_RDONLY;
Packit 6ef888
	else
Packit 6ef888
		open_flag = O_RDWR | O_EXCL;
Packit 6ef888
Packit 6ef888
	sdp->device_fd = open(opts.device, open_flag);
Packit 6ef888
	if (sdp->device_fd < 0) {
Packit 6ef888
		struct mntent *mnt;
Packit 6ef888
		if (open_flag == O_RDONLY || errno != EBUSY) {
Packit 6ef888
			log_crit( _("Unable to open device: %s\n"),
Packit 6ef888
				  opts.device);
Packit 6ef888
			return FSCK_USAGE;
Packit 6ef888
		}
Packit 6ef888
		/* We can't open it EXCL.  It may be already open rw (in which
Packit 6ef888
		   case we want to deny them access) or it may be mounted as
Packit 6ef888
		   the root file system at boot time (in which case we need to
Packit 6ef888
		   allow it.)
Packit 6ef888
		   If the device is busy, but not because it's mounted, fail.
Packit 6ef888
		   This protects against cases where the file system is LVM
Packit 6ef888
		   and perhaps mounted on a different node.
Packit 6ef888
		   Try opening without O_EXCL. */
Packit 6ef888
		sdp->device_fd = lgfs2_open_mnt_dev(opts.device, O_RDWR, &mnt;;
Packit 6ef888
		if (sdp->device_fd < 0)
Packit 6ef888
			goto mount_fail;
Packit 6ef888
		/* If the device is mounted, but not mounted RO, fail.  This
Packit 6ef888
		   protects them against cases where the file system is
Packit 6ef888
		   mounted RW, but still allows us to check our own root
Packit 6ef888
		   file system. */
Packit 6ef888
		if (!hasmntopt(mnt, MNTOPT_RO))
Packit 6ef888
			goto close_fail;
Packit 6ef888
		/* The device is mounted RO, so it's likely our own root
Packit 6ef888
		   file system.  We can only do so much to protect the users
Packit 6ef888
		   from themselves. */
Packit 6ef888
		was_mounted_ro = 1;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (lgfs2_get_dev_info(sdp->device_fd, &sdp->dinfo)) {
Packit 6ef888
		perror(opts.device);
Packit 6ef888
		return FSCK_ERROR;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	/* read in sb from disk */
Packit Service 786bf1
	err = fill_super_block(sdp);
Packit Service 786bf1
	if (err != FSCK_OK)
Packit Service 786bf1
		return err;
Packit 6ef888
Packit 6ef888
	/* Change lock protocol to be fsck_* instead of lock_* */
Packit 6ef888
	if (!opts.no && preen_is_safe(sdp, preen, force_check)) {
Packit 6ef888
		if (block_mounters(sdp, 1)) {
Packit 6ef888
			log_err( _("Unable to block other mounters\n"));
Packit 6ef888
			return FSCK_USAGE;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	/* Get master dinode */
Packit 6ef888
	if (sdp->gfs1)
Packit 6ef888
		sdp->master_dir = NULL;
Packit 6ef888
	else
Packit 6ef888
		sdp->master_dir = lgfs2_inode_read(sdp,
Packit 6ef888
					     sdp->sd_sb.sb_master_dir.no_addr);
Packit 6ef888
	if (!sdp->gfs1 &&
Packit 6ef888
	    (sdp->master_dir->i_di.di_header.mh_magic != GFS2_MAGIC ||
Packit 6ef888
	     sdp->master_dir->i_di.di_header.mh_type != GFS2_METATYPE_DI ||
Packit 6ef888
	     !sdp->master_dir->i_di.di_size)) {
Packit 6ef888
		inode_put(&sdp->master_dir);
Packit 6ef888
		rebuild_master(sdp);
Packit 6ef888
		sdp->master_dir = lgfs2_inode_read(sdp,
Packit 6ef888
					     sdp->sd_sb.sb_master_dir.no_addr);
Packit 6ef888
		if (sdp->master_dir == NULL) {
Packit 6ef888
			log_crit(_("Error reading master directory: %s\n"), strerror(errno));
Packit 6ef888
			return FSCK_ERROR;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	/* Look up the "per_node" inode.  If there are journals missing, we
Packit 6ef888
	   need to figure out what's missing from per_node. And we need all
Packit 6ef888
	   our journals to be there before we can replay them. */
Packit 6ef888
	if (!sdp->gfs1)
Packit 6ef888
		lookup_per_node(sdp, 0);
Packit 6ef888
Packit 6ef888
	/* We need rindex first in case jindex is missing and needs to read
Packit 6ef888
	   in the rgrps before rebuilding it. However, note that if the rindex
Packit 6ef888
	   is damaged, we need the journals to repair it. That's because the
Packit 6ef888
	   journals likely contain rgrps and bitmaps, which we need to ignore
Packit 6ef888
	   when we're trying to find the rgrps. */
Packit 6ef888
	if (init_rindex(sdp))
Packit 6ef888
		return FSCK_ERROR;
Packit 6ef888
Packit 6ef888
	if (fetch_rgrps(sdp))
Packit 6ef888
		return FSCK_ERROR;
Packit 6ef888
Packit 6ef888
	/* We need to read in jindex in order to replay the journals. If
Packit 6ef888
	   there's an error, we may proceed and let init_system_inodes
Packit 6ef888
	   try to rebuild it. */
Packit 6ef888
	if (init_jindex(sdp, 1) == 0) {
Packit 6ef888
		/* If GFS, rebuild the journals. If GFS2, replay them. We don't
Packit 6ef888
		   have the smarts to replay GFS1 journals (neither did
Packit 6ef888
		   gfs_fsck). */
Packit 6ef888
		if (sdp->gfs1) {
Packit 6ef888
			if (reconstruct_journals(sdp))
Packit 6ef888
				return FSCK_ERROR;
Packit 6ef888
		} else if (replay_journals(sdp, preen, force_check,
Packit 6ef888
					   &clean_journals)) {
Packit 6ef888
			if (!opts.no && preen_is_safe(sdp, preen, force_check))
Packit 6ef888
				block_mounters(sdp, 0);
Packit 6ef888
			stack;
Packit 6ef888
			return FSCK_ERROR;
Packit 6ef888
		}
Packit 6ef888
		if (sdp->md.journals == clean_journals)
Packit 6ef888
			*all_clean = 1;
Packit 6ef888
		else if (force_check || !preen)
Packit 6ef888
			log_notice( _("\nJournal recovery complete.\n"));
Packit 6ef888
Packit 6ef888
		if (!force_check && *all_clean && preen)
Packit 6ef888
			return FSCK_OK;
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (init_system_inodes(sdp))
Packit 6ef888
		return FSCK_ERROR;
Packit 6ef888
Packit 6ef888
	return FSCK_OK;
Packit 6ef888
Packit 6ef888
close_fail:
Packit 6ef888
	close(sdp->device_fd);
Packit 6ef888
mount_fail:
Packit 6ef888
	log_crit( _("Device %s is busy.\n"), opts.device);
Packit 6ef888
	return FSCK_USAGE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
void destroy(struct gfs2_sbd *sdp)
Packit 6ef888
{
Packit 6ef888
	if (!opts.no) {
Packit 6ef888
		if (block_mounters(sdp, 0)) {
Packit 6ef888
			log_warn( _("Unable to unblock other mounters - manual intervention required\n"));
Packit 6ef888
			log_warn( _("Use 'gfs2_tool sb <device> proto' to fix\n"));
Packit 6ef888
		}
Packit 6ef888
		log_info( _("Syncing the device.\n"));
Packit 6ef888
		fsync(sdp->device_fd);
Packit 6ef888
	}
Packit 6ef888
	empty_super_block(sdp);
Packit 6ef888
	close(sdp->device_fd);
Packit 6ef888
	if (was_mounted_ro && errors_corrected) {
Packit 6ef888
		sdp->device_fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
Packit 6ef888
		if (sdp->device_fd >= 0) {
Packit 6ef888
			if (write(sdp->device_fd, "2", 1) == 2) {
Packit 6ef888
				close(sdp->device_fd);
Packit 6ef888
				return;
Packit 6ef888
			}
Packit 6ef888
			close(sdp->device_fd);
Packit 6ef888
		}
Packit 6ef888
		log_warn(_("fsck.gfs2: Could not flush caches (non-fatal).\n"));
Packit 6ef888
	}
Packit 6ef888
}