Blame gfs2/fsck/initialize.c

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