[Ocfs2-tools-commits] zab commits r416 - in trunk/fsck.ocfs2: . include

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Thu Nov 18 17:20:17 CST 2004


Author: zab
Date: 2004-11-18 17:20:16 -0600 (Thu, 18 Nov 2004)
New Revision: 416

Added:
   trunk/fsck.ocfs2/extent.c
   trunk/fsck.ocfs2/include/extent.h
Modified:
   trunk/fsck.ocfs2/Makefile
   trunk/fsck.ocfs2/fsck.c
   trunk/fsck.ocfs2/include/fsck.h
   trunk/fsck.ocfs2/include/util.h
   trunk/fsck.ocfs2/pass0.c
   trunk/fsck.ocfs2/pass1.c
   trunk/fsck.ocfs2/util.c
Log:
o get rid of the ill-concieved "found" and "dup" block bitmaps
o track clusters that should be allocated explicitly in their own bitmap
o add extent.c for verifying and truncating extent trees
o be sure to track all the clusters in a group, not just the referenced blocks
o use first_cluster_group properly
o clean up the cluster bit calcs when syncing bitmaps
o check the extent block chain allocator in pass 0
o add a stub for handling local allocators in the future


Modified: trunk/fsck.ocfs2/Makefile
===================================================================
--- trunk/fsck.ocfs2/Makefile	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/Makefile	2004-11-18 23:20:16 UTC (rev 416)
@@ -22,6 +22,7 @@
 CFILES =	fsck.c		\
 		dirblocks.c 	\
 		dirparents.c 	\
+		extent.c 	\
 		icount.c 	\
 		journal.c 	\
 		pass0.c 	\
@@ -36,6 +37,7 @@
 HFILES = 	include/fsck.h		\
 		include/dirblocks.h	\
 		include/dirparents.h	\
+		include/extent.h	\
 		include/icount.h	\
 		include/journal.h	\
 		include/pass0.h		\

Added: trunk/fsck.ocfs2/extent.c
===================================================================
--- trunk/fsck.ocfs2/extent.c	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/extent.c	2004-11-18 23:20:16 UTC (rev 416)
@@ -0,0 +1,326 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2,  as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * --
+ *
+ * o2fsck_check_extents(), the only function this file exports, is called
+ * by pass 0 to verify the extent trees that hang off of inodes.
+ *
+ * XXX
+ * 	test reasonable/dup block references
+ * 	fix up the i_ fields that depend on the extent trees
+ *
+ *	this could be much more clever when it finds an extent block that is
+ *	self-consistent but in a crazy part of the file system that would lead
+ *	us to not trust it.  it should first try and follow the suballoc bits
+ *	back to a possibly orphaned desc.  failing that it should record the
+ *	reference/block and continue on.  once it has parsed the rest of eb and
+ *	fleshed out the bits of the extent block allocators it could go back
+ *	and allocate a new block and copy the orphan into it.
+ */
+#include <string.h>
+#include <inttypes.h>
+
+#include "ocfs2.h"
+
+#include "extent.h"
+#include "fsck.h"
+#include "problem.h"
+#include "util.h"
+
+static char *whoami = "extent.c";
+
+struct extent_info {
+	uint64_t	ei_max_size;
+	uint64_t	ei_clusters;
+	uint64_t	ei_last_eb_blk;
+	uint16_t	ei_expected_depth;
+	unsigned	ei_expect_depth:1;
+};
+
+static errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
+			  ocfs2_dinode *di, ocfs2_extent_list *el,
+			  uint16_t max_recs, int *changed);
+
+static errcode_t check_eb(o2fsck_state *ost, struct extent_info *ei,
+			  ocfs2_dinode *di, uint64_t blkno, int *is_valid)
+{
+	int changed = 0;
+	char *buf = NULL;
+	ocfs2_extent_block *eb;
+	errcode_t ret;
+
+	/* XXX test that the block isn't already used */
+
+	/* we only consider an extent block invalid if we were able to read 
+	 * it and it didn't have a extent block signature */ 
+	*is_valid = 1;
+
+	ret = ocfs2_malloc_block(ost->ost_fs->fs_io, &buf);
+	if (ret) {
+		com_err(whoami, ret, "while allocating a block-sized buffer "
+			"for an extent block");
+		goto out;
+	}
+
+	ret = ocfs2_read_extent_block_nocheck(ost->ost_fs, blkno, buf);
+	if (ret) {
+		com_err(whoami, ret, "reading extent block at %"PRIu64" in "
+			"inode %"PRIu64" for verification", blkno, 
+			di->i_blkno);
+		if (ret == OCFS2_ET_BAD_EXTENT_BLOCK_MAGIC)
+			*is_valid = 0;
+		goto out;
+	}
+
+	eb = (ocfs2_extent_block *)buf;
+
+	if (eb->h_blkno != blkno &&
+	    prompt(ost, PY, "An extent block at %"PRIu64" in inode %"PRIu64" "
+		   "claims to be located at block %"PRIu64".  Update the "
+		   "extent block's location?", blkno, di->i_blkno,
+		   eb->h_blkno)) {
+		eb->h_blkno = blkno;
+		changed = 1;
+	}
+
+	/* XXX worry about suballoc node/bit */
+	/* XXX worry about next_leaf_blk */
+
+	check_el(ost, ei, di, &eb->h_list,
+		 ocfs2_extent_recs_per_eb(ost->ost_fs->fs_blocksize), 
+		 &changed);
+
+	if (changed) {
+		ret = ocfs2_write_extent_block(ost->ost_fs, blkno, buf);
+		if (ret) {
+			com_err(whoami, ret, "while writing an updated extent "
+				"block at %"PRIu64" for inode %"PRIu64,
+				blkno, di->i_blkno);
+			goto out;
+		}
+	}
+
+out:
+	if (buf)
+		ocfs2_free(&buf);
+	return 0;
+}
+
+/* the caller will check if er->e_blkno is out of range to determine if it
+ * should try removing the record */
+static errcode_t check_er(o2fsck_state *ost, struct extent_info *ei,
+			  ocfs2_dinode *di, ocfs2_extent_list *el,
+			  ocfs2_extent_rec *er, int *changed)
+{
+	errcode_t ret = 0;
+	uint64_t first_block;
+	uint32_t last_cluster;
+
+	verbosef("cpos %u clusters %u blkno %"PRIu64"\n", er->e_cpos,
+		 er->e_clusters, er->e_blkno);
+
+	if (ocfs2_block_out_of_range(ost->ost_fs, er->e_blkno))
+		goto out;
+
+	if (el->l_tree_depth) {
+		int is_valid = 0;
+		/* we only expect a given depth when we descend to extent blocks
+		 * from a previous depth.  these start at 0 when the inode
+		 * is checked */
+		ei->ei_expect_depth = 1;
+		ei->ei_expected_depth = el->l_tree_depth - 1;
+		check_eb(ost, ei, di, er->e_blkno, &is_valid);
+		if (!is_valid && 
+		    prompt(ost, PY, "The extent record for cluster offset "
+			   "%"PRIu32" in inode %"PRIu64" refers to an invalid "
+			   "extent block at %"PRIu64".  Clear the reference "
+			   "to this invalid block?", er->e_cpos, di->i_blkno,
+			   er->e_blkno)) {
+
+			er->e_blkno = 0;
+			*changed = 1;
+		}
+		ret = 0;
+		goto out;
+	}
+
+	first_block = ocfs2_blocks_to_clusters(ost->ost_fs, er->e_blkno);
+	first_block = ocfs2_clusters_to_blocks(ost->ost_fs, first_block);
+
+	if (first_block != er->e_blkno &&
+	    prompt(ost, PY, "The extent record for cluster offset %"PRIu32" "
+		   "in inode %"PRIu64" refers to block %"PRIu64" which isn't "
+		   "aligned with the start of a cluster.  Point the extent "
+		   "record at block %"PRIu64" which starts this cluster?",
+		   er->e_cpos, di->i_blkno, er->e_blkno, first_block)) {
+
+		er->e_blkno = first_block;
+		*changed = 1;
+	}
+
+	/* imagine blkno 0, 1 er_clusters.  last_cluster is 1 and 
+	 * fs_clusters is 1, which is ok.. */
+	last_cluster = ocfs2_blocks_to_clusters(ost->ost_fs, er->e_blkno) +
+		       er->e_clusters;
+
+	if (last_cluster > ost->ost_fs->fs_clusters &&
+	    prompt(ost, PY, "The extent record for cluster offset %"PRIu32" "
+		   "in inode %"PRIu64" refers to an extent that goes beyond "
+		   "the end of the volume.  Truncate the extent by %"PRIu32" "
+		   "clusters to fit it in the volume?", er->e_cpos, 
+		   di->i_blkno, last_cluster - ost->ost_fs->fs_clusters)) {
+
+		er->e_clusters -= last_cluster - ost->ost_fs->fs_clusters;
+		*changed = 1;
+	}
+	
+	/* XXX offer to remove leaf records with er_clusters set to 0? */
+
+	/* XXX check that the blocks that are referenced aren't already 
+	 * used */
+
+out:
+	return ret;
+}
+
+static errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
+			  ocfs2_dinode *di, ocfs2_extent_list *el,
+			  uint16_t max_recs, int *changed)
+{
+	int trust_next_free = 1;
+	ocfs2_extent_rec *er;
+	uint64_t max_size;
+	uint16_t i;
+	size_t cpy;
+
+	verbosef("depth %u count %u next_free %u\n", el->l_tree_depth,
+		 el->l_count, el->l_next_free_rec);
+
+	if (ei->ei_expect_depth && 
+	    el->l_tree_depth != ei->ei_expected_depth &&
+	    prompt(ost, PY, "Extent list in inode %"PRIu64" is recorded as "
+		   "being at depth %u but we expect it to be at depth %u. "
+		   "update the list?", di->i_blkno, el->l_tree_depth,
+		   ei->ei_expected_depth)) {
+
+		el->l_tree_depth = ei->ei_expected_depth;
+		*changed = 1;
+	}
+
+	if (el->l_count > max_recs &&
+	    prompt(ost, PY, "Extent list in inode %"PRIu64" claims to have %u "
+		   "records, but the maximum is %u. Fix the list's count?",
+		   di->i_blkno, el->l_count, max_recs)) {
+
+		el->l_count = max_recs;
+		*changed = 1;
+	}
+
+	if (max_recs > el->l_count)
+		max_recs = el->l_count;
+
+	if (el->l_next_free_rec > max_recs) {
+		if (prompt(ost, PY, "Extent list in inode %"PRIu64" claims %u "
+			   "as the next free chain record, but fsck believes "
+			   "the largest valid value is %u.  Clamp the next "
+			   "record value?", di->i_blkno, el->l_next_free_rec,
+			   max_recs)) {
+
+			el->l_next_free_rec = el->l_count;
+			*changed = 1;
+		} else {
+			trust_next_free = 0;
+		}
+	}
+
+	if (trust_next_free)
+		max_recs = el->l_next_free_rec;
+
+	for (i = 0; i < max_recs; i++) {
+		er = &el->l_recs[i];
+
+		/* returns immediately if blkno is out of range.
+		 * descends into eb.  checks that data er doesn't
+		 * reference past the volume or anything crazy. */
+		check_er(ost, ei, di, el, er, changed);
+
+		/* offer to remove records that point to nowhere */
+		if (ocfs2_block_out_of_range(ost->ost_fs, er->e_blkno) && 
+		    prompt(ost, PY, "Extent record %u in inode %"PRIu64" "
+			   "refers to a block that is out of range.  Remove "
+			   "this record from the extent list?", i,
+			   di->i_blkno)) {
+
+			if (!trust_next_free) {
+				printf("Can't remove the record becuase "
+				       "next_free_rec hasn't been fixed\n");
+				continue;
+			}
+			cpy = (max_recs - i - 1) * sizeof(*er);
+			/* shift the remaining recs into this ones place */
+			if (cpy != 0) {
+				memcpy(er, er + 1, cpy);
+				memset(&el->l_recs[max_recs - 1], 0, 
+				       sizeof(*er));
+				i--;
+			}
+			el->l_next_free_rec--;
+			max_recs--;
+			*changed = 1;
+			continue;
+		}
+
+
+		/* we've already accounted for the extent block as part of
+		 * the extent block chain groups */
+		if (el->l_tree_depth)
+			continue;
+
+		/* mark the data clusters as used */
+		o2fsck_mark_clusters_allocated(ost,
+			ocfs2_blocks_to_clusters(ost->ost_fs, er->e_blkno),
+			er->e_clusters);
+
+		ei->ei_clusters += er->e_clusters;
+
+		max_size = (er->e_cpos + er->e_clusters) <<
+			   OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_clustersize_bits;
+		if (max_size > ei->ei_max_size)
+			ei->ei_max_size = max_size;
+	}
+
+	return 0;
+}
+
+errcode_t o2fsck_check_extents(o2fsck_state *ost, ocfs2_dinode *di)
+{
+	errcode_t ret;
+	struct extent_info ei = {0, };
+	int changed = 0;
+	
+	ret = check_el(ost, &ei, di, &di->id2.i_list, 
+	         ocfs2_extent_recs_per_inode(ost->ost_fs->fs_blocksize),
+		 &changed);
+
+	if (changed)
+		o2fsck_write_inode(ost, di->i_blkno, di);
+
+	return ret;
+}	

Modified: trunk/fsck.ocfs2/fsck.c
===================================================================
--- trunk/fsck.ocfs2/fsck.c	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/fsck.c	2004-11-18 23:20:16 UTC (rev 416)
@@ -22,9 +22,10 @@
  * more details.
  *
  * journal.c: try and replay the journal for each node
- * pass0.c: make sure the inode allocators are consistent
- * pass1.c: walk allocated inodes and verify them
- *          reflect valid inodes in the inode allocator bitmaps
+ * pass0.c: make sure all the chain allocators are consistent
+ * pass1.c: walk allocated inodes and verify them, including their extents
+ *          reflect valid inodes in the inode chain allocators
+ *          reflect allocated clusters in the cluster chain allocator
  * pass2.c: verify directory entries, record some linkage metadata
  * pass3.c: make sure all dirs are reachable
  * pass4.c: resolve inode's link counts, move disconnected inodes to lost+found
@@ -35,8 +36,8 @@
  *   _should not_ write to the file system unless it has asked prompt() to do
  *   so.  It should also not exit if prompt() returns 0.  prompt() should give
  *   as much detail as possible as it becomes an error log.
- * - to make life simpler, memory allocation is a fatal error.  We shouldn't
- *   have unreasonable memory demands in relation to the size of the fs.
+ * - to make life simpler, memory allocation is a fatal error.  We should
+ *   have reasonable memory demands in relation to the size of the fs.
  * - I'm still of mixed opinions about IO errors.  thoughts?
  */
 #include <getopt.h>
@@ -121,20 +122,14 @@
 		return ret;
 	}
 
-	ret = ocfs2_block_bitmap_new(fs, "blocks off inodes",
-				     &ost->ost_found_blocks);
+	ret = ocfs2_block_bitmap_new(fs, "allocated clusters",
+				     &ost->ost_allocated_clusters);
 	if (ret) {
-		com_err(whoami, ret, "while allocating found blocks bitmap");
+		com_err(whoami, ret, "while allocating a bitmap to track "
+			"allocated clusters");
 		return ret;
 	}
 
-	ret = ocfs2_block_bitmap_new(fs, "duplicate blocks",
-				     &ost->ost_dup_blocks);
-	if (ret) {
-		com_err(whoami, ret, "while allocating duplicate block bitmap");
-		return ret;
-	}
-
 	ret = ocfs2_block_bitmap_new(fs, "directory inodes to rebuild",
 				     &ost->ost_rebuild_dirs);
 	if (ret) {
@@ -206,6 +201,17 @@
 	printf("\n");
 }
 
+static void mark_magical_clusters(o2fsck_state *ost)
+{
+	uint32_t cluster;
+
+	cluster = ocfs2_blocks_to_clusters(ost->ost_fs, 
+					   ost->ost_fs->fs_first_cg_blkno);
+
+	if (cluster != 0) 
+		o2fsck_mark_clusters_allocated(ost, 0, cluster);
+}
+
 int main(int argc, char **argv)
 {
 	char *filename;
@@ -330,9 +336,12 @@
 
 	exit_if_skipping(ost);
 
+#if 0
 	o2fsck_mark_block_used(ost, 0);
 	o2fsck_mark_block_used(ost, 1);
 	o2fsck_mark_block_used(ost, OCFS2_SUPER_BLOCK_BLKNO);
+#endif
+	mark_magical_clusters(ost);
 
 	/* XXX we don't use the bad blocks inode, do we? */
 

Added: trunk/fsck.ocfs2/include/extent.h
===================================================================
--- trunk/fsck.ocfs2/include/extent.h	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/include/extent.h	2004-11-18 23:20:16 UTC (rev 416)
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2002 Oracle Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#ifndef __O2FSCK_EXTENT_H__
+#define __O2FSCK_EXTENT_H__
+
+#include "fsck.h"
+
+errcode_t o2fsck_check_extents(o2fsck_state *ost, ocfs2_dinode *di);
+
+#endif /* __O2FSCK_EXTENT_H__ */
+

Modified: trunk/fsck.ocfs2/include/fsck.h
===================================================================
--- trunk/fsck.ocfs2/include/fsck.h	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/include/fsck.h	2004-11-18 23:20:16 UTC (rev 416)
@@ -37,8 +37,7 @@
 	ocfs2_bitmap	*ost_dir_inodes;
 	ocfs2_bitmap	*ost_reg_inodes;
 
-	ocfs2_bitmap	*ost_found_blocks;
-	ocfs2_bitmap	*ost_dup_blocks;
+	ocfs2_bitmap	*ost_allocated_clusters;
 
 	ocfs2_bitmap	*ost_rebuild_dirs;
 

Modified: trunk/fsck.ocfs2/include/util.h
===================================================================
--- trunk/fsck.ocfs2/include/util.h	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/include/util.h	2004-11-18 23:20:16 UTC (rev 416)
@@ -44,8 +44,8 @@
 } while (0)
 
 void o2fsck_write_inode(o2fsck_state *ost, uint64_t blkno, ocfs2_dinode *di);
-int o2fsck_mark_block_used(o2fsck_state *ost, uint64_t blkno);
-int o2fsck_test_block_used(o2fsck_state *ost, uint64_t blkno);
+void o2fsck_mark_cluster_allocated(o2fsck_state *ost, uint32_t cluster);
+void o2fsck_mark_clusters_allocated(o2fsck_state *ost, uint32_t cluster,
+				    uint32_t num);
 
 #endif /* __O2FSCK_UTIL_H__ */
-

Modified: trunk/fsck.ocfs2/pass0.c
===================================================================
--- trunk/fsck.ocfs2/pass0.c	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/pass0.c	2004-11-18 23:20:16 UTC (rev 416)
@@ -65,6 +65,7 @@
 	uint32_t	cs_free_bits;
 	uint32_t	cs_total_bits;
 	uint32_t	cs_chain_no;
+	uint16_t	cs_cpg;
 };
 
 static errcode_t check_group_desc(o2fsck_state *ost, ocfs2_dinode *di,
@@ -188,6 +189,7 @@
 		goto out;
 	}
 
+#if 0 /* XXX plausible + used test */
 	if (o2fsck_test_block_used(ost, blkno) &&
 	    prompt(ost, PY, "Chain %d in allocator at inode %"PRIu64" "
 			   "points to block %"PRIu64" which has already been "
@@ -198,6 +200,7 @@
 		cbr->cb_new_next_blkno = 1;
 		cbr->cb_next_blkno = 0;
 	}
+#endif
 
 	if (allowed) {
 		ocfs2_bitmap_test(allowed, blkno, &was_set);
@@ -243,6 +246,22 @@
 	return;
 }
 
+static void mark_group_used(o2fsck_state *ost, struct chain_state *cs,
+			    ocfs2_group_desc *bg, ocfs2_bitmap *allowed)
+{
+	uint16_t clusters = cs->cs_cpg;
+
+	if (allowed) {
+		ocfs2_bitmap_clear(allowed, bg->bg_blkno, NULL);
+		/* only mark the desc cluster as in use */
+		clusters = 1;
+	}
+
+	o2fsck_mark_clusters_allocated(ost, 
+		ocfs2_blocks_to_clusters(ost->ost_fs, bg->bg_blkno),
+		clusters);
+}
+
 /*
  * this function is pretty hairy.  for dynamic chain allocators
  * it is just walking the chains to verify the group descs
@@ -287,9 +306,7 @@
 		goto new_head;
 	}
 
-	if (allowed)
-		ocfs2_bitmap_clear(allowed, chain->c_blkno, NULL);
-	o2fsck_mark_block_used(ost, chain->c_blkno);
+	mark_group_used(ost, cs, bg1, allowed);
 
 	/* read in each group desc and check it.  In this loop bg1 is 
 	 * verified and in the chain.  it's bg2 that is considered.  if
@@ -305,10 +322,7 @@
 		}
 
 		if (!cbr.cb_new_next_blkno) {
-			if (allowed)
-				ocfs2_bitmap_clear(allowed, bg2->bg_blkno,
-						   NULL);
-			o2fsck_mark_block_used(ost, bg2->bg_blkno);
+			mark_group_used(ost, cs, bg2, allowed);
 			memcpy(buf1, buf2, ost->ost_fs->fs_blocksize);
 			continue;
 		}
@@ -427,6 +441,7 @@
 		/* reset for each run */
 		cs = (struct chain_state) {
 			.cs_chain_no = i,
+			.cs_cpg = cl->cl_cpg,
 		};
 		changed |= check_chain(ost, di, &cs, cr, buf1, buf2, allowed);
 
@@ -520,13 +535,12 @@
 
 	max_recs = ocfs2_chain_recs_per_inode(ost->ost_fs->fs_blocksize);
 
-	for (i = 0; i < cgs.cgs_cluster_groups; i++) {
-		if (i == 0)
-			blkno = OCFS2_SUPER_BLOCK_BLKNO + 1;
-		else
-			blkno = i * cgs.cgs_cpg * 
-				(ost->ost_fs->fs_clustersize /
-				 ost->ost_fs->fs_blocksize);
+	/* the first groups desc is specified in the super block, the 
+	 * rest are in the first cluster/block of the group */
+	for (i = 0, blkno = ost->ost_fs->fs_first_cg_blkno;
+	     i < cgs.cgs_cluster_groups; 
+	     i++, blkno = i * ocfs2_clusters_to_blocks(ost->ost_fs,
+						       cgs.cgs_cpg)) {
 
 		verbosef("looking for cluster bitmap desc at %"PRIu64"\n",
 			 blkno);
@@ -585,7 +599,7 @@
 
 	/* find the blocks that we think should have been in the chains
 	 * but which weren't found */
-	for (blkno = OCFS2_SUPER_BLOCK_BLKNO + 1;
+	for (blkno = ost->ost_fs->fs_first_cg_blkno;
 	     !ocfs2_bitmap_find_next_set(bitmap_descs, blkno, &blkno);
 	     blkno++) {
 
@@ -758,6 +772,37 @@
 		}
 	}
 
+	printf("Pass 0c: Checking extent block allocation chains\n");
+
+	for (i = 0; i < max_nodes; i++) {
+		ret = ocfs2_lookup_system_inode(fs, EXTENT_ALLOC_SYSTEM_INODE,
+						i, &blkno);
+		if (ret) {
+			com_err(whoami, ret, "while looking up the extent "
+				"allocator type %d for node %d\n", type, i);
+			goto out;
+		}
+
+		ret = ocfs2_read_inode(ost->ost_fs, blkno, (char *)di);
+		if (ret) {
+			com_err(whoami, ret, "reading inode alloc inode "
+				"%"PRIu64" for verification", blkno);
+			goto out;
+		}
+
+		verbosef("found extent alloc %"PRIu64" at block %"PRIu64"\n",
+			 di->i_blkno, blkno);
+
+		ret = verify_chain_alloc(ost, di,
+					 blocks + ost->ost_fs->fs_blocksize,
+					 blocks + 
+					 (ost->ost_fs->fs_blocksize * 2), NULL);
+
+		/* XXX maybe helped by the alternate super block */
+		if (ret)
+			goto out;
+	}
+
 out:
 	if (blocks)
 		ocfs2_free(&blocks);

Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/pass1.c	2004-11-18 23:20:16 UTC (rev 416)
@@ -46,8 +46,8 @@
  * XXX
  * 	check many, many, more i_ fields for each inode type
  * 	make sure the inode's dtime/count/valid match in update_inode_alloc
- * 	clean up the extent records that hang off inodes
  * 	more carefully track cluster use in conjunction with pass 0
+ * 	handle local alloc inodes for realsies
  */
 #include <string.h>
 #include <inttypes.h>
@@ -57,6 +57,7 @@
 
 #include "dirblocks.h"
 #include "dirparents.h"
+#include "extent.h"
 #include "icount.h"
 #include "fsck.h"
 #include "pass1.h"
@@ -93,8 +94,6 @@
 
 	max_nodes = OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes;
 
-	verbosef("updating inode %"PRIu64" alloc to %d\n", blkno, val);
-
 	for (node = ~0; node != max_nodes; node++, 
 					   ret = OCFS2_ET_INTERNAL_FAILURE) {
 
@@ -384,8 +383,6 @@
 		}
 	}
 
-	o2fsck_mark_block_used(ost, blkno);
-
 	if (S_ISDIR(di->i_mode)) {
 		verbosef("adding dir block %"PRIu64"\n", blkno);
 		o2fsck_add_dir_block(&ost->ost_dirblocks, di->i_blkno, blkno,
@@ -415,18 +412,13 @@
 	return 0;
 }
 
-static int check_extent_blocks(ocfs2_filesys *fs, ocfs2_extent_rec *rec,
-				int tree_depth, uint32_t ccount,
-				uint64_t ref_blkno, int ref_recno,
-				void *priv_data)
+/* XXX do something with these */
+static errcode_t handle_local_alloc(o2fsck_state *ost, ocfs2_dinode *di)
 {
-	struct verifying_blocks *vb = priv_data;
-
-	if (tree_depth > 0) {
-		verbosef("found extent block %"PRIu64"\n", rec->e_blkno);
-		o2fsck_mark_block_used(vb->vb_ost, rec->e_blkno);
-	}
-
+	ocfs2_local_alloc *lab = &di->id2.i_lab;
+	verbosef("la_bm_off %u size %u total %u used %u\n", lab->la_bm_off,
+		 lab->la_size, di->id1.bitmap1.i_total,
+		 di->id1.bitmap1.i_used);
 	return 0;
 }
 
@@ -441,15 +433,14 @@
 	vb.vb_di = di;
 
 	if (di->i_flags & OCFS2_LOCAL_ALLOC_FL)
-		ret = 0; /* nothing to iterate over in this case */
+		ret = handle_local_alloc(ost, di);
 	else if (di->i_flags & OCFS2_CHAIN_FL)
 		ret = ocfs2_chain_iterate(fs, blkno, check_gd_block, &vb);
 	else {
-		ret = ocfs2_extent_iterate(fs, blkno, 0, NULL,
-					   check_extent_blocks, &vb);
+		ret = o2fsck_check_extents(ost, di);
 		if (ret == 0)
-			ret = ocfs2_block_iterate(fs, blkno, 0,
-    					   verify_block, &vb);
+			ret = ocfs2_block_iterate(fs, blkno, 0, verify_block,
+						  &vb);
 	}
 
 	if (ret) {
@@ -558,44 +549,24 @@
 	 * indicates that the rest of the bits to the end of the bitmap
 	 * should be clear.
 	 */
-	last_cbit = 0;
-	blkno = 0;
-	cbit = 0;
-	for ( ; cbit < ost->ost_fs->fs_clusters; 
-	        blkno = ocfs2_clusters_to_blocks(ost->ost_fs, cbit + 1),
-		last_cbit = cbit + 1) {
+	for (last_cbit = 0, cbit = 0;
+	     cbit < ost->ost_fs->fs_clusters; 
+	     cbit++, last_cbit = cbit) {
 
-		verbosef("starting with blkno %"PRIu64"\n", blkno);
+		ret = ocfs2_bitmap_find_next_set(ost->ost_allocated_clusters,
+						 cbit, &cbit);
 
-		ret = ocfs2_bitmap_find_next_set(ost->ost_found_blocks, blkno,
-						 &blkno);
-
 		/* clear to the end */
 		if (ret == OCFS2_ET_BIT_NOT_FOUND)
 			cbit = ost->ost_fs->fs_clusters;
-		else {
-			uint64_t cgroup, cluster;
-			/* the libocfs2 bitmap interfaces names bit ranges
-			 * by the block the desc starts on.  so to find
-			 * a bit number for a given cluster we find the 
-			 * block offset of the start of the cluster group
-			 * and add the offset of the cluster in its cluster
-			 * group */
-			cluster = ocfs2_blocks_to_clusters(ost->ost_fs, blkno);
-			cgroup = cluster - (cluster % cgs.cgs_cpg);
-			cbit = ocfs2_clusters_to_blocks(ost->ost_fs, cgroup);
 
-			cbit += cluster % cgs.cgs_cpg;
-		}
-
 		ret = ocfs2_bitmap_find_next_set(ci->ci_chains, last_cbit, 
 						 &cbit_found);
 		if (ret == OCFS2_ET_BIT_NOT_FOUND)
 			cbit_found = ost->ost_fs->fs_clusters;
 
-		verbosef("blkno %"PRIu64" cbit %"PRIu64" last_cbit %"PRIu64" "
-			 "cbit_found %"PRIu64"\n", blkno, cbit, last_cbit,
-			 cbit_found);
+		verbosef("cbit %"PRIu64" last_cbit %"PRIu64" cbit_found "
+			 "%"PRIu64"\n", cbit, last_cbit, cbit_found);
 
 		if (cbit_found == cbit)
 			continue;
@@ -725,8 +696,6 @@
 
 		valid = 0;
 
-		o2fsck_mark_block_used(ost, blkno);
-
 		/* scanners have to skip over uninitialized inodes */
 		if (!memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
 		    strlen(OCFS2_INODE_SIGNATURE)) &&
@@ -739,15 +708,9 @@
 			valid = di->i_flags & OCFS2_VALID_FL;
 		}
 
-		verbosef("blkno %"PRIu64" ino %"PRIu64"\n", blkno,
-				di->i_blkno);
 		update_inode_alloc(ost, di, blkno, valid);
 	}
 
-	if (ocfs2_bitmap_get_set_bits(ost->ost_dup_blocks))
-		fatal_error(OCFS2_ET_INTERNAL_FAILURE, "duplicate blocks "
-				"found, need to learn to fix.");
-
 	write_cluster_alloc(ost);
 	write_inode_alloc(ost);
 

Modified: trunk/fsck.ocfs2/util.c
===================================================================
--- trunk/fsck.ocfs2/util.c	2004-11-18 23:08:23 UTC (rev 415)
+++ trunk/fsck.ocfs2/util.c	2004-11-18 23:20:16 UTC (rev 416)
@@ -51,22 +51,20 @@
 	}
 }
 
-int o2fsck_mark_block_used(o2fsck_state *ost, uint64_t blkno)
+void o2fsck_mark_cluster_allocated(o2fsck_state *ost, uint32_t cluster)
 {
 	int was_set;
 
-	ocfs2_bitmap_set(ost->ost_found_blocks, blkno, &was_set);
+	ocfs2_bitmap_set(ost->ost_allocated_clusters, cluster, &was_set);
 
 	if (was_set) /* XX can go away one all callers handle this */
 		com_err(__FUNCTION__, OCFS2_ET_INTERNAL_FAILURE,
-			"!! duplicate block %"PRIu64, blkno);
-
-	return was_set;
+			"!! duplicate cluster %"PRIu32, cluster);
 }
 
-int o2fsck_test_block_used(o2fsck_state *ost, uint64_t blkno)
+void o2fsck_mark_clusters_allocated(o2fsck_state *ost, uint32_t cluster,
+				    uint32_t num)
 {
-	int was_set;
-	ocfs2_bitmap_test(ost->ost_found_blocks, blkno, &was_set);
-	return was_set;
+	while(num--)
+		o2fsck_mark_cluster_allocated(ost, cluster++);
 }



More information about the Ocfs2-tools-commits mailing list