[Ocfs2-tools-commits] zab commits r455 - trunk/fsck.ocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Fri Dec 3 16:54:37 CST 2004
Author: zab
Date: 2004-12-03 16:54:35 -0600 (Fri, 03 Dec 2004)
New Revision: 455
Modified:
trunk/fsck.ocfs2/pass1.c
Log:
o verify and ask to repair ocfs2_local_alloc
o sync up an active local alloc with what is used
o make sure to reserve the bits covered by active allocs in the global bitmap
Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c 2004-12-03 20:10:17 UTC (rev 454)
+++ trunk/fsck.ocfs2/pass1.c 2004-12-03 22:54:35 UTC (rev 455)
@@ -55,6 +55,7 @@
#include <time.h>
#include "ocfs2.h"
+#include "bitops.h"
#include "dirblocks.h"
#include "dirparents.h"
@@ -163,6 +164,142 @@
return;
}
+static errcode_t verify_local_alloc(o2fsck_state *ost, ocfs2_dinode *di)
+{
+ ocfs2_local_alloc *la = &di->id2.i_lab;
+ uint32_t max;
+ int broken = 0, changed = 0, clear = 0;
+ errcode_t ret = 0;
+
+ verbosef("la_bm_off %u size %u total %u used %u\n", la->la_bm_off,
+ la->la_size, di->id1.bitmap1.i_total,
+ di->id1.bitmap1.i_used);
+
+ max = ocfs2_local_alloc_size(ost->ost_fs->fs_blocksize);
+
+ if (la->la_size > max) {
+ broken = 1;
+ if (prompt(ost, PY, 0, "Local alloc inode %"PRIu64" claims to "
+ "have %u bytes of bitmap data but %u bytes is the "
+ "maximum allowed. Set the inode's count to the "
+ "maximum?", di->i_blkno, la->la_size, max)) {
+
+ la->la_size = max;
+ changed = 1;
+ }
+ }
+
+ if (di->id1.bitmap1.i_total == 0) {
+ /* ok, it's not used. we don't mark these errors as
+ * 'broken' as the kernel shouldn't care.. right? */
+ if (di->id1.bitmap1.i_used != 0) {
+ if (prompt(ost, PY, 0, "Local alloc inode %"PRIu64" "
+ "isn't in use bit its i_used isn't 0. Set it to "
+ "0?", di->i_blkno)) {
+
+ di->id1.bitmap1.i_used = 0;
+ changed = 1;
+ }
+ }
+
+ if (la->la_bm_off != 0) {
+ if (prompt(ost, PY, 0, "Local alloc inode %"PRIu64" "
+ "isn't in use bit its i_bm_off isn't 0. Set it "
+ "to 0?", di->i_blkno)) {
+
+ la->la_bm_off = 0;
+ changed = 1;
+ }
+ }
+
+ goto out;
+ }
+
+ if (la->la_bm_off >= ost->ost_fs->fs_clusters) {
+ broken = 1;
+ if (prompt(ost, PY, 0, "Local alloc inode %"PRIu64" claims to "
+ "contain a bitmap that starts at cluster %u but "
+ "the volume contains %u clusters. Mark the local "
+ "alloc bitmap as unused?", di->i_blkno,
+ la->la_bm_off, ost->ost_fs->fs_clusters)) {
+ clear = 1;
+ }
+ }
+
+ if (di->id1.bitmap1.i_total > la->la_size * 8) {
+ broken = 1;
+ if (prompt(ost, PY, 0, "Local alloc inode %"PRIu64" claims to "
+ "have a bitmap with %u bits but the inode can only "
+ "fit %u bits. Clamp the bitmap size to this "
+ "maxmum?", di->i_blkno, di->id1.bitmap1.i_total,
+ la->la_size * 8)) {
+
+ di->id1.bitmap1.i_total = la->la_size * 8;
+ changed = 1;
+ }
+ }
+
+ if (la->la_bm_off + di->id1.bitmap1.i_total >
+ ost->ost_fs->fs_clusters) {
+ broken = 1;
+ if (prompt(ost, PY, 0, "Local alloc inode %"PRIu64" claims to "
+ "have a bitmap that covers clusters numbered %u "
+ "through %u but %u is the last valid cluster. "
+ "Mark the local bitmap as unused?",
+ di->i_blkno,
+ la->la_bm_off,
+ la->la_bm_off + di->id1.bitmap1.i_total - 1,
+ ost->ost_fs->fs_clusters - 1)) {
+ clear = 1;
+ }
+ /* we can't possibly check _used if bm/off and total are
+ * so busted */
+ goto out;
+ }
+
+ if (di->id1.bitmap1.i_used > di->id1.bitmap1.i_total) {
+ broken = 1;
+ if (prompt(ost, PY, 0, "Local alloc inode %"PRIu64" claims to "
+ "contain a bitmap with %u bits and %u used. Set "
+ "i_used down to %u?", di->i_blkno,
+ di->id1.bitmap1.i_total, di->id1.bitmap1.i_used,
+ di->id1.bitmap1.i_total)) {
+
+ di->id1.bitmap1.i_used = di->id1.bitmap1.i_total;
+ changed = 1;
+ }
+ }
+
+out:
+ if (broken && !clear &&
+ prompt(ost, PY, 0, "Local alloc inode %"PRIu64" contained errors. "
+ "Mark it as unused instead of trying to correct its "
+ "bitmap?", di->i_blkno)) {
+ clear = 1;
+ }
+
+ if (clear) {
+ di->id1.bitmap1.i_total = 0;
+ di->id1.bitmap1.i_used = 0;
+ la->la_bm_off = 0;
+ memset(la->la_bitmap, 0,
+ ocfs2_local_alloc_size(ost->ost_fs->fs_blocksize));
+ changed = 1;
+ }
+
+ if (changed) {
+ ret = ocfs2_write_inode(ost->ost_fs, di->i_blkno, (char *)di);
+ if (ret) {
+ com_err(whoami, ret, "while writing local alloc inode "
+ "%"PRIu64, di->i_blkno);
+ ost->ost_write_error = 1;
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
/* Check the basics of the ocfs2_dinode itself. If we find problems
* we clear the VALID flag and the caller will see that and update
* inode allocations and write the inode to disk.
@@ -256,6 +393,9 @@
/* i_size? what other sanity testing for devices? */
}
+ if (di->i_flags & OCFS2_LOCAL_ALLOC_FL)
+ verify_local_alloc(ost, di);
+
out:
/* XXX when we clear we need to also free whatever blocks may have
* hung off this inode that haven't already been reserved. we want
@@ -438,15 +578,6 @@
return 0;
}
-/* XXX do something with these */
-static errcode_t handle_local_alloc(o2fsck_state *ost, ocfs2_dinode *di)
-{
- 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;
-}
static void o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
uint64_t blkno, ocfs2_dinode *di)
@@ -459,7 +590,7 @@
vb.vb_di = di;
if (di->i_flags & OCFS2_LOCAL_ALLOC_FL)
- ret = handle_local_alloc(ost, di);
+ ret = 0;
else if (di->i_flags & OCFS2_CHAIN_FL)
ret = ocfs2_chain_iterate(fs, blkno, check_gd_block, &vb);
else {
@@ -525,6 +656,171 @@
}
}
+static void sync_local_bitmap(o2fsck_state *ost, ocfs2_dinode *di,
+ ocfs2_local_alloc *la, uint64_t start,
+ uint64_t end)
+{
+ uint64_t pos, alloc;
+ errcode_t ret;
+ int bmap, last_bmap, changed = 0;
+ uint16_t used = 0;
+
+ /* it's pretty lame that we dup this and the loop in
+ * write_cluster_alloc but they're pretty different bitmaps.. */
+
+ for(last_bmap = 0, pos = start ; pos < end;
+ last_bmap = bmap + 1, pos = alloc + 1) {
+
+ ret = ocfs2_bitmap_find_next_set(ost->ost_allocated_clusters,
+ pos, &alloc);
+ if (ret == OCFS2_ET_BIT_NOT_FOUND)
+ alloc = end;
+
+ bmap = ocfs2_find_next_bit_set(la->la_bitmap,
+ di->id1.bitmap1.i_total,
+ last_bmap);
+
+ verbosef("last_bmap %u pos %"PRIu64" -> bmap %u alloc "
+ "%"PRIu64"\n", last_bmap, pos, bmap, alloc);
+
+ if (bmap == alloc - la->la_bm_off) {
+ if (alloc != end)
+ used++;
+ continue;
+ }
+
+ /* XXX specifically for each bit? */
+ if (!changed &&
+ !prompt(ost, PY, 0, "Local alloc inode %"PRIu64" has bits "
+ "in its bitmap which don't match what is used in "
+ "the file system. Sync its bitmap up with what "
+ "is in use?", di->i_blkno))
+ break;
+
+ changed = 1;
+
+ /* the local bitmap is missing something that is in use */
+ if (bmap > alloc - la->la_bm_off) {
+ bmap = alloc - la->la_bm_off;
+ ocfs2_set_bit(bmap, la->la_bitmap);
+ used++;
+ }
+
+ /* the local bitmap has some set that aren't in use */
+ for ( ; bmap < alloc - la->la_bm_off; bmap++)
+ ocfs2_clear_bit(bmap, la->la_bitmap);
+
+ }
+
+ if (di->id1.bitmap1.i_used != used) {
+ if (prompt(ost, PY, 0, "Local alloc inode %"PRIu64" now has "
+ "%u bits set in its bitmap but it thinks there are "
+ "%u set. Fix the record of set bits to match "
+ "how many are really set in the bitmap?",
+ di->i_blkno, used, di->id1.bitmap1.i_used)) {
+
+ di->id1.bitmap1.i_used = used;
+ changed = 1;
+ }
+ }
+
+ if (changed) {
+ ret = ocfs2_write_inode(ost->ost_fs, di->i_blkno, (char *)di);
+ if (ret) {
+ com_err(whoami, ret, "while writing local alloc inode "
+ "%"PRIu64, di->i_blkno);
+ ost->ost_write_error = 1;
+ ret = 0;
+ }
+ }
+
+ /* the kernel is going to trust this local alloc so we need to
+ * make sure that its space is reserved in the cluster bitmap */
+ for(pos = start ; pos < end; pos = alloc + 1) {
+ ret = ocfs2_bitmap_find_next_set(ost->ost_allocated_clusters,
+ pos, &alloc);
+ if (ret == OCFS2_ET_BIT_NOT_FOUND)
+ alloc = end;
+ for ( ; pos < alloc; pos++) {
+ verbosef("reserving bit %"PRIu64" in the global "
+ "bitmap for local alloc %"PRIu64"\n",
+ pos, di->i_blkno);
+ ocfs2_bitmap_set(ost->ost_allocated_clusters, pos,
+ NULL);
+ }
+ }
+}
+
+/* if we have valid local allocs we have two jobs:
+ * - make sure the bitmap in the local alloc reflects what is used on disk
+ * - make sure the cluster bitmap has all the bits in the local alloc set
+ */
+static void write_local_allocs(o2fsck_state *ost)
+{
+ uint16_t node, max_nodes;
+ max_nodes = OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes;
+ char *buf = NULL;
+ errcode_t ret;
+ uint64_t blkno, start, end;
+ ocfs2_dinode *di;
+ ocfs2_local_alloc *la = &di->id2.i_lab;
+
+ ret = ocfs2_malloc_block(ost->ost_fs->fs_io, &buf);
+ if (ret) {
+ com_err(whoami, ret, "while allocating an inode buffer to "
+ "use when verifying local alloc inode bitmaps.");
+ goto out;
+ }
+
+ di = (ocfs2_dinode *)buf;
+
+ for (node = 0; node < max_nodes; node++) {
+ ret = ocfs2_lookup_system_inode(ost->ost_fs,
+ LOCAL_ALLOC_SYSTEM_INODE,
+ node, &blkno);
+ if (ret) {
+ com_err(whoami, ret, "while looking up local alloc "
+ "inode %"PRIu64" to verify its bitmap",
+ blkno);
+ goto out;
+ }
+
+ ret = ocfs2_read_inode(ost->ost_fs, blkno, buf);
+ if (ret) {
+ com_err(whoami, ret, "while reading local alloc "
+ "inode %"PRIu64" to verify its bitmap",
+ blkno);
+ goto out;
+ }
+
+ if (di->id1.bitmap1.i_total == 0)
+ continue;
+
+ la = &di->id2.i_lab;
+
+ /* make sure we don't try to work with a crazy bitmap. It
+ * can only be this crazy if the user wouldn't let us fix
+ * it up.. just ignore it */
+ if (la->la_size >
+ ocfs2_local_alloc_size(ost->ost_fs->fs_blocksize) ||
+ di->id1.bitmap1.i_used > di->id1.bitmap1.i_total ||
+ di->id1.bitmap1.i_total > la->la_size * 8)
+ continue;
+
+ start = la->la_bm_off;
+ end = la->la_bm_off + di->id1.bitmap1.i_total;
+
+ if (start >= ost->ost_fs->fs_clusters ||
+ end < start ||
+ end > ost->ost_fs->fs_clusters)
+ continue;
+
+ sync_local_bitmap(ost, di, la, start, end);
+ }
+out:
+ return;
+}
+
/* once we've iterated all the inodes we should have the current working
* set of which blocks we think are in use. we use this to derive the set
* of clusters that should be allocated in the cluster chain allocators. we
@@ -742,6 +1038,7 @@
update_inode_alloc(ost, di, blkno, valid);
}
+ write_local_allocs(ost);
write_cluster_alloc(ost);
write_inode_alloc(ost);
More information about the Ocfs2-tools-commits
mailing list