Page MenuHomeClusterLabs Projects

pass5.c
No OneTemporary

/******************************************************************************
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
** of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <stdlib.h>
#include "libgfs2.h"
#include "fsck.h"
#include "fs_bits.h"
#include "util.h"
int convert_mark(enum gfs2_mark_block mark, uint32_t *count)
{
switch(mark) {
case gfs2_meta_inval:
/* Convert invalid metadata to free blocks */
case gfs2_block_free:
count[0]++;
return GFS2_BLKST_FREE;
case gfs2_block_used:
count[2]++;
return GFS2_BLKST_USED;
case gfs2_inode_dir:
case gfs2_inode_file:
case gfs2_inode_lnk:
case gfs2_inode_blk:
case gfs2_inode_chr:
case gfs2_inode_fifo:
case gfs2_inode_sock:
count[1]++;
return GFS2_BLKST_DINODE;
case gfs2_indir_blk:
case gfs2_leaf_blk:
case gfs2_journal_blk:
case gfs2_meta_other:
case gfs2_meta_eattr:
count[2]++;
return GFS2_BLKST_USED;
default:
log_err("Invalid state %d found\n", mark);
return -1;
}
return -1;
}
int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int buflen,
uint64_t *rg_block, uint64_t rg_data, uint32_t *count)
{
unsigned char *byte, *end;
unsigned int bit;
unsigned char rg_status, block_status;
struct gfs2_block_query q;
uint64_t block;
/* FIXME verify cast */
byte = (unsigned char *) buffer;
bit = 0;
end = (unsigned char *) buffer + buflen;
while(byte < end) {
rg_status = ((*byte >> bit) & GFS2_BIT_MASK);
block = rg_data + *rg_block;
warm_fuzzy_stuff(block);
gfs2_block_check(bl, block, &q);
block_status = convert_mark(q.block_type, count);
if (rg_status != block_status) {
const char *blockstatus[] = {"Free", "Data", "Invalid", "inode"};
log_err("Ondisk and fsck bitmaps differ at"
" block %"PRIu64" (0x%" PRIx64 ") \n", block, block);
log_err("Ondisk status is %u (%s) but FSCK thinks it should be ",
rg_status, blockstatus[rg_status]);
log_err("%u (%s)\n", block_status, blockstatus[block_status]);
log_err("Metadata type is %u (%s)\n", q.block_type,
block_type_string(&q));
if(query(&opts, "Fix bitmap for block %"
PRIu64" (0x%" PRIx64 ") ? (y/n) ", block, block)) {
if(gfs2_set_bitmap(sbp, block, block_status))
log_err("Failed.\n");
else
log_err("Succeeded.\n");
} else
log_err("Bitmap at block %"PRIu64" (0x%" PRIx64
") left inconsistent\n", block, block);
}
(*rg_block)++;
bit += GFS2_BIT_SIZE;
if (bit >= 8){
bit = 0;
byte++;
}
}
return 0;
}
enum update_flags update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp,
uint32_t *count)
{
uint32_t i;
struct gfs2_bitmap *bits;
uint64_t rg_block = 0;
int update = 0;
for(i = 0; i < rgp->ri.ri_length; i++) {
bits = &rgp->bits[i];
/* update the bitmaps */
check_block_status(sbp, rgp->bh[i]->b_data + bits->bi_offset,
bits->bi_len, &rg_block, rgp->ri.ri_data0, count);
}
/* actually adjust counters and write out to disk */
if(rgp->rg.rg_free != count[0]) {
log_err("RG #%" PRIu64 " (0x%" PRIx64
") free count inconsistent: is %u should be %u\n",
rgp->ri.ri_addr, rgp->ri.ri_addr, rgp->rg.rg_free, count[0]);
rgp->rg.rg_free = count[0];
update = 1;
}
if(rgp->rg.rg_dinodes != count[1]) {
log_err("Inode count inconsistent: is %u should be %u\n",
rgp->rg.rg_dinodes, count[1]);
rgp->rg.rg_dinodes = count[1];
update = 1;
}
if((rgp->ri.ri_data - count[0] - count[1]) != count[2]) {
/* FIXME not sure how to handle this case ATM - it
* means that the total number of blocks we've counted
* exceeds the blocks in the rg */
log_err("Internal fsck error - AAHHH!\n");
exit(1);
}
if(update) {
if(query(&opts, "Update resource group counts? (y/n) ")) {
log_warn("Resource group counts updated\n");
/* write out the rgrp */
gfs2_rgrp_out(&rgp->rg, rgp->bh[0]->b_data);
return updated;
} else
log_err("Resource group counts left inconsistent\n");
}
return not_updated;
}
/**
* pass5 - check resource groups
*
* fix free block maps
* fix used inode maps
*/
int pass5(struct gfs2_sbd *sbp)
{
osi_list_t *tmp;
struct rgrp_list *rgp = NULL;
uint32_t count[3];
uint64_t rg_count = 0;
/* Reconcile RG bitmaps with fsck bitmap */
for(tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next){
enum update_flags f;
log_info("Verifying Resource Group #%" PRIu64 "\n", rg_count);
memset(count, 0, sizeof(count));
rgp = osi_list_entry(tmp, struct rgrp_list, list);
if(gfs2_rgrp_read(sbp, rgp)){
stack;
return -1;
}
rg_count++;
/* Compare the bitmaps and report the differences */
f = update_rgrp(sbp, rgp, count);
gfs2_rgrp_relse(rgp, f);
}
/* Fix up superblock info based on this - don't think there's
* anything to do here... */
return 0;
}

File Metadata

Mime Type
text/x-c
Expires
Mon, Feb 24, 6:57 PM (7 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464410
Default Alt Text
pass5.c (5 KB)

Event Timeline