[Ocfs2-tools-commits] zab commits r267 - in trunk/fsck.ocfs2: .
include
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon Sep 27 18:42:33 CDT 2004
Author: zab
Date: 2004-09-27 18:42:30 -0500 (Mon, 27 Sep 2004)
New Revision: 267
Modified:
trunk/fsck.ocfs2/icount.c
trunk/fsck.ocfs2/include/icount.h
trunk/fsck.ocfs2/pass1.c
Log:
Do more while iterating the blocks on an inode.
o Make icount_update failure fatal
o don't bother checking the inode signatures
o track icount for all inodes
o really check that the root dir is in fact a dir before claiming it isn't
o record the number of and furthest blocks while iterating
o check for zero lengh directories
o make sure i_size and i_clusters matches what we found iterating
Modified: trunk/fsck.ocfs2/icount.c
===================================================================
--- trunk/fsck.ocfs2/icount.c 2004-09-27 17:22:24 UTC (rev 266)
+++ trunk/fsck.ocfs2/icount.c 2004-09-27 23:42:30 UTC (rev 267)
@@ -34,6 +34,7 @@
#include "fsck.h"
#include "icount.h"
+#include "util.h"
typedef struct _icount_node {
struct rb_node in_node;
@@ -83,7 +84,7 @@
return NULL;
}
-errcode_t o2fsck_icount_update(o2fsck_icount *icount, uint64_t blkno,
+void o2fsck_icount_update(o2fsck_icount *icount, uint64_t blkno,
uint16_t count)
{
icount_node *in;
@@ -105,13 +106,13 @@
} else if (count > 2){
in = calloc(1, sizeof(*in));
if (in == NULL)
- return OCFS2_ET_NO_MEMORY;
+ fatal_error(OCFS2_ET_NO_MEMORY,
+ "while allocating to track icount");
in->in_blkno = blkno;
in->in_icount = count;
icount_insert(icount, in);
}
- return 0;
}
errcode_t o2fsck_icount_new(ocfs2_filesys *fs, o2fsck_icount **ret)
Modified: trunk/fsck.ocfs2/include/icount.h
===================================================================
--- trunk/fsck.ocfs2/include/icount.h 2004-09-27 17:22:24 UTC (rev 266)
+++ trunk/fsck.ocfs2/include/icount.h 2004-09-27 23:42:30 UTC (rev 267)
@@ -31,7 +31,7 @@
struct rb_root ic_multiple_tree;
} o2fsck_icount;
-errcode_t o2fsck_icount_update(o2fsck_icount *icount, uint64_t blkno,
+void o2fsck_icount_update(o2fsck_icount *icount, uint64_t blkno,
uint16_t count);
errcode_t o2fsck_icount_new(ocfs2_filesys *fs, o2fsck_icount **ret);
void o2fsck_icount_free(o2fsck_icount *icount);
Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c 2004-09-27 17:22:24 UTC (rev 266)
+++ trunk/fsck.ocfs2/pass1.c 2004-09-27 23:42:30 UTC (rev 267)
@@ -25,6 +25,7 @@
*/
#include <string.h>
#include <inttypes.h>
+#include <time.h>
#include "ocfs2.h"
@@ -65,23 +66,26 @@
/* what's our deletion story? i_links_count, dtime, etc.. */
- /* XXX it seems these are expected sometimes? */
+#if 0 /* XXX we don't care about the signature on inodes? */
if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
strlen(OCFS2_INODE_SIGNATURE))) {
goto bad;
}
- if (!(di->i_flags & OCFS2_VALID_FL)) {
- goto bad;
- }
+#endif
+ if (di->i_links_count)
+ o2fsck_icount_update(ost->ost_icount_in_inodes, di->i_blkno,
+ di->i_links_count);
+
/* offer to clear a non-directory root inode so that
* pass3:check_root() can re-create it */
- if ((di->i_blkno == fs->fs_root_blkno) &&
+ if ((di->i_blkno == fs->fs_root_blkno) && !S_ISDIR(di->i_mode) &&
should_fix(ost, FIX_DEFYES, "Root inode isn't a directory.")) {
di->i_dtime = 0ULL;
di->i_links_count = 0ULL;
- o2fsck_icount_update(ost->ost_icount_in_inodes, di->i_blkno,
- di->i_links_count);
+ o2fsck_icount_update(ost->ost_icount_in_inodes,
+ di->i_blkno, di->i_links_count);
+
o2fsck_write_inode(fs, blkno, di);
}
@@ -123,7 +127,10 @@
struct verifying_blocks {
unsigned vb_mark_dir_blocks;
- uint64_t vb_blocks;
+ uint64_t vb_num_blocks;
+ uint64_t vb_last_block;
+ int vb_clear;
+ int vb_errors;
o2fsck_state *vb_ost;
ocfs2_dinode *vb_di;
};
@@ -135,48 +142,135 @@
{
struct verifying_blocks *vb = priv_data;
ocfs2_dinode *di = vb->vb_di;
+ o2fsck_state *ost = vb->vb_ost;
int was_set;
+
+ /* someday we may want to worry about holes in files here */
- ocfs2_bitmap_set(vb->vb_ost->ost_found_blocks, blkno, &was_set);
+ if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) || (blkno > fs->fs_blocks)) {
+ vb->vb_errors++;
+#if 0 /* ext2 does this by returning a value to libext2 which clears the
+ block from the inode's allocation */
+ if (should_fix(ost, FIX_DEFYES,
+ "inode %"PRIu64" references bad physical block"
+ " %"PRIu64" at logical block %"PRIu64
+ ", should it be cleared?",
+ di->i_blkno, bklno, bcount)) {
+ }
+#endif
+ }
+
+ /* XXX this logic should be more sophisticated. It's not really clear
+ * what ext2 is trying to do in theirs. */
+ if (vb->vb_errors == 12) {
+ if (should_fix(ost, FIX_DEFYES,
+ "inode %"PRIu64" has seen many errors, should it "
+ "be cleared?", di->i_blkno)) {
+ vb->vb_clear = 1;
+ return OCFS2_BLOCK_ABORT;
+ }
+ }
+
+ ocfs2_bitmap_set(ost->ost_found_blocks, blkno, &was_set);
if (was_set) {
fprintf(stderr, "duplicate block %"PRIu64"?\n", blkno);
- ocfs2_bitmap_set(vb->vb_ost->ost_dup_blocks, blkno, NULL);
+ ocfs2_bitmap_set(ost->ost_dup_blocks, blkno, NULL);
}
if (S_ISDIR(di->i_mode)) {
- /* do we want libocfs2 to record directory blocks or should
- * we? */
+#if 0
+ o2fsck_add_dir_block(di, blkno, bcount);
+#endif
}
- vb->vb_blocks++;
+ vb->vb_num_blocks++;
+ if (bcount > vb->vb_last_block)
+ vb->vb_last_block = bcount;
+
return 0;
}
-static errcode_t o2fsck_verify_inode_data(ocfs2_filesys *fs, o2fsck_state *ost,
- uint64_t blkno, ocfs2_dinode *di)
+/* XXX maybe this should be a helper in libocfs2? */
+static uint64_t clusters_holding_blocks(ocfs2_filesys *fs, uint64_t num_blocks)
{
+ int c_to_b_bits = OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits -
+ OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+
+ return (num_blocks + ((1 << c_to_b_bits) - 1)) >> c_to_b_bits;
+}
+
+static void o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
+ uint64_t blkno, ocfs2_dinode *di)
+{
struct verifying_blocks vb = {0, };
+ uint64_t expected = 0;
errcode_t ret;
vb.vb_ost = ost;
vb.vb_di = di;
+ /* XXX it isn't enough to just walk the blocks. We want to mark
+ * metadata blocks in the extents as used and otherwise validate them
+ * while we're at it. */
+
ret = ocfs2_block_iterate(fs, blkno, 0, verify_block, &vb);
+ if (ret == OCFS2_ET_INODE_CANNOT_BE_ITERATED) {
+ /* XXX I don't understand this. just check the inode
+ * fields as though there were no blocks? */
+ ret = 0;
+ }
if (ret) {
- com_err(whoami, ret, "walking data blocks");
- goto out;
+ fatal_error(ret, "while iterating over the blocks for inode "
+ "%"PRIu64, di->i_blkno);
}
-#if 0 /* hmm. */
- if (vb.vb_blocks != di->i_blocks) {
- fprintf(stderr, "inode %llu claimed %llu blocks, found"
- " %llu blocks.\n", di->i_ino, di->i_blocks,
- vb.vb_blocks);
+ if (S_ISDIR(di->i_mode) && vb.vb_num_blocks == 0) {
+ if (should_fix(ost, FIX_DEFYES,
+ "inode %"PRIu64" is a zero length directory, "
+ "clear it?", di->i_blkno)) {
+ vb.vb_clear = 1;
+ }
}
-#endif
-out:
- return ret;
+ /*
+ * XXX we should have a helper that clears an inode and backs it out of
+ * any book-keeping that it might have been included in, as though it
+ * was never seen. the alternative is to restart pass1 which seems
+ * goofy.
+ */
+ if (vb.vb_clear) {
+ di->i_links_count = 0;
+ o2fsck_icount_update(ost->ost_icount_in_inodes,
+ di->i_blkno, di->i_links_count);
+ di->i_dtime = time(0);
+ o2fsck_write_inode(fs, di->i_blkno, di);
+ /* XXX clear valid flag and stuff? */
+ }
+
+ if (vb.vb_num_blocks > 0)
+ expected = (vb.vb_last_block + 1) * fs->fs_blocksize;
+
+ /* i_size is checked for symlinks elsewhere */
+ if (!S_ISLNK(di->i_mode) && di->i_size != expected &&
+ should_fix(ost, FIX_DEFYES, "inode %"PRIu64" has a size of "
+ "%"PRIu64" but has %"PRIu64" bytes of actual data. "
+ " Correct the file size?", di->i_blkno, di->i_size,
+ expected)) {
+ di->i_size = expected;
+ o2fsck_write_inode(fs, blkno, di);
+ }
+
+ if (vb.vb_num_blocks > 0)
+ expected = clusters_holding_blocks(fs, vb.vb_last_block + 1);
+
+ if (di->i_clusters < expected &&
+ should_fix(ost, FIX_DEFYES, "inode %"PRIu64" has %"PRIu64" "
+ "clusters but its blocks fit in %"PRIu64" clusters. "
+ " Correct the number of clusters?", di->i_blkno,
+ di->i_clusters, expected)) {
+ di->i_clusters = expected;
+ o2fsck_write_inode(fs, blkno, di);
+ }
}
errcode_t o2fsck_pass1(o2fsck_state *ost)
@@ -217,11 +311,16 @@
}
if (blkno == 0)
break;
+ /* scanners have to skip over uninitialized inodes */
+ if (!(di->i_flags & OCFS2_VALID_FL))
+ continue;
o2fsck_verify_inode_fields(fs, ost, blkno, di);
+
/* XXX be able to mark the blocks in the inode as
* bad if the inode was bad */
- o2fsck_verify_inode_data(fs, ost, blkno, di);
+
+ o2fsck_check_blocks(fs, ost, blkno, di);
}
out_close_scan:
More information about the Ocfs2-tools-commits
mailing list