[Ocfs2-tools-commits] zab commits r341 - in trunk: fsck.ocfs2
libocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Thu Oct 21 17:55:40 CDT 2004
Author: zab
Date: 2004-10-21 17:55:38 -0500 (Thu, 21 Oct 2004)
New Revision: 341
Modified:
trunk/fsck.ocfs2/fsck.c
trunk/fsck.ocfs2/journal.c
trunk/libocfs2/ocfs2_err.et.in
Log:
o be a little more consistent with journal replay errors
Modified: trunk/fsck.ocfs2/fsck.c
===================================================================
--- trunk/fsck.ocfs2/fsck.c 2004-10-20 17:02:41 UTC (rev 340)
+++ trunk/fsck.ocfs2/fsck.c 2004-10-21 22:55:38 UTC (rev 341)
@@ -135,6 +135,26 @@
return 0;
}
+static void check_superblock(char *whoami, o2fsck_state *ost)
+{
+ ocfs2_super_block *sb = OCFS2_RAW_SB(ost->ost_fs->fs_super);
+
+ if (sb->s_max_nodes == 0) {
+ printf("The superblock max_nodes field is set to 0. fsck "
+ "doesn't know how to repair this.\n");
+ exit(FSCK_ERROR);
+ }
+
+ /* ocfs2_open() already checked _incompat and _ro_compat */
+ if (sb->s_feature_compat & ~OCFS2_FEATURE_COMPAT_SUPP) {
+ com_err(whoami, OCFS2_ET_UNSUPP_FEATURE,
+ "while checking _compat flags");
+ exit(FSCK_ERROR);
+ }
+
+ /* XXX do we want checking for different revisions of ocfs2? */
+}
+
static void exit_if_skipping(o2fsck_state *ost)
{
if (ost->ost_force)
@@ -253,19 +273,9 @@
return 1;
}
- /* XXX do we want checking for different revisions of ocfs2? */
- /* XXX should be verifying super-block bits here.
- * like s_max_nodes, journal recovery trusts it. */
+ check_superblock(argv[0], ost);
- /* ocfs2_open() already checked _incompat and _ro_compat */
- if (OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_feature_compat &
- ~OCFS2_FEATURE_COMPAT_SUPP) {
- com_err(argv[0], OCFS2_ET_UNSUPP_FEATURE,
- "while checking _compat flags");
- exit(FSCK_ERROR);
- }
-
exit_if_skipping(ost);
/* XXX we don't use the bad blocks inode, do we? */
@@ -276,7 +286,12 @@
printf(" number of clusters: %"PRIu32"\n", ost->ost_fs->fs_clusters);
printf(" bytes per cluster: %u\n", ost->ost_fs->fs_clustersize);
- o2fsck_replay_journals(ost);
+ ret = o2fsck_replay_journals(ost);
+ if (ret) {
+ printf("fsck encountered unrecoverable errors while replaying "
+ "the journals and will not continue\n");
+ exit(FSCK_ERROR);
+ }
ret = o2fsck_pass1(ost);
if (ret)
Modified: trunk/fsck.ocfs2/journal.c
===================================================================
--- trunk/fsck.ocfs2/journal.c 2004-10-20 17:02:41 UTC (rev 340)
+++ trunk/fsck.ocfs2/journal.c 2004-10-21 22:55:38 UTC (rev 341)
@@ -47,6 +47,7 @@
uint64_t ji_jsb_block;
ocfs2_cached_inode *ji_cinode;
+ unsigned ji_set_final_seq:1;
uint32_t ji_final_seq;
};
@@ -67,7 +68,8 @@
return diff >= 0;
}
-static void revoke_insert(struct rb_root *root, uint64_t block, uint32_t seq)
+static errcode_t revoke_insert(struct rb_root *root, uint64_t block,
+ uint32_t seq)
{
struct rb_node ** p = &root->rb_node;
struct rb_node * parent = NULL;
@@ -85,20 +87,21 @@
else {
if (seq_gt(seq, re->r_seq))
re->r_seq = seq;
- return;
+ return 0;
}
}
re = malloc(sizeof(struct revoke_entry));
if (re == NULL)
- fatal_error(OCFS2_ET_NO_MEMORY, "while allocating "
- "space for revoke entries");
+ return OCFS2_ET_NO_MEMORY;
re->r_block = block;
re->r_seq = seq;
rb_link_node(&re->r_node, parent, p);
rb_insert_color(&re->r_node, root);
+
+ return 0;
}
static int revoke_this_block(struct rb_root *root, uint64_t block,
@@ -140,27 +143,32 @@
}
}
-static void add_revoke_records(struct journal_info *ji, char *buf,
- size_t max, uint32_t seq)
+static errcode_t add_revoke_records(struct journal_info *ji, char *buf,
+ size_t max, uint32_t seq)
{
journal_revoke_header_t jr;
uint32_t *blkno; /* XXX 640k ought to be enough for everybody */
size_t i, num;
+ errcode_t err = 0;
memcpy(&jr, buf, sizeof(jr));
jr.r_count = be32_to_cpu(jr.r_count);
if (jr.r_count < sizeof(jr) || jr.r_count > max) {
- /* XXX abort replay? */
verbosef("corrupt r_count: %X", jr.r_count);
- return;
+ return OCFS2_ET_BAD_JOURNAL_REVOKE;
}
num = (jr.r_count - sizeof(jr)) / sizeof(blkno);
blkno = (uint32_t *)(buf + sizeof(jr));
- for (i = 0; i < num; i++, blkno++)
- revoke_insert(&ji->ji_revoke, be32_to_cpu(*blkno), seq);
+ for (i = 0; i < num; i++, blkno++) {
+ err = revoke_insert(&ji->ji_revoke, be32_to_cpu(*blkno), seq);
+ if (err)
+ break;
+ }
+
+ return err;
}
static uint64_t jwrap(journal_superblock_t *jsb, uint64_t block)
@@ -378,9 +386,10 @@
verbosef("done scanning with seq %"PRIu32"\n", next_seq);
- if (!recover)
+ if (!recover) {
+ ji->ji_set_final_seq = 1;
ji->ji_final_seq = next_seq;
- else if (ji->ji_final_seq != next_seq) {
+ } else if (ji->ji_final_seq != next_seq) {
err = OCFS2_ET_IO;
com_err(whoami, err, "while recovering the journal and found "
"that we arrived at seq %"PRIu32" instead of seq "
@@ -401,7 +410,7 @@
err = ocfs2_malloc_blocks(ost->ost_fs->fs_io, 1, &ji->ji_jsb);
if (err)
- fatal_error(err, "while allocating space for node %d's "
+ com_err(whoami, err, "while allocating space for node %d's "
"journal superblock", node);
err = ocfs2_lookup_system_inode(ost->ost_fs, JOURNAL_SYSTEM_INODE,
@@ -446,32 +455,47 @@
return err;
}
-/* XXX we should think harder about what behaviour we want here. Right now
- * this function always leaves with clean reset journals. Any errors in
- * the journal recovery process will trigger a full fsck.
+/* XXX For now this is very simple and paranoid. Any errors encountered
+ * are fatal and stop fsck. I propose:
+ *
+ * - Allocation errors are always fatal. If we can't allocate what little
+ * we need to replay the journals there's no way we will be able to
+ * perform a full fsck. Instead of wiping the journal we should leave
+ * the task to someone with enough mem (it won't be a lot, this is largely
+ * academic.)
+ *
+ * - block IO errors should only effect the bits of journal recovery
+ * they hit. The rest should be recovered and fsck can pick up
+ * the pieces. remapping around bad blocks, etc.
+ *
+ * - Missing journals, insane fields, etc, should be cleared and left
+ * for fsck to pick up.
+ *
* XXX pass fsck trigger back up, write dirty fs, always zap/write */
errcode_t o2fsck_replay_journals(o2fsck_state *ost)
{
errcode_t err = 0, ret = 0;
struct journal_info *jis, *ji;
+ journal_superblock_t *jsb;
char *buf = NULL;
int i, max_nodes;
max_nodes = OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_max_nodes;
- err = ocfs2_malloc_blocks(ost->ost_fs->fs_io, 1, &buf);
- if (err)
- fatal_error(err, "while allocating room to read journal "
+ ret = ocfs2_malloc_blocks(ost->ost_fs->fs_io, 1, &buf);
+ if (ret) {
+ com_err(whoami, ret, "while allocating room to read journal "
"blocks");
+ goto out;
+ }
- err = ocfs2_malloc0(sizeof(struct journal_info) * max_nodes, &jis);
- if (err)
- fatal_error(err, "while allocating an array of block numbers "
- "for journal replay");
+ ret = ocfs2_malloc0(sizeof(struct journal_info) * max_nodes, &jis);
+ if (ret) {
+ com_err(whoami, ret, "while allocating an array of block "
+ "numbers for journal replay");
+ goto out;
+ }
- /* we'll try loading and verifying them all first before proceeding
- * to replay them. This way we can make sure their blocks don't
- * overlap or anything crazy like that. */
for (i = 0; i < max_nodes ; i++) {
err = prep_journal_info(ost, i, &jis[i]);
if (err) {
@@ -482,9 +506,11 @@
err = walk_journal(ost, i, &jis[i], buf, 0);
if (err) {
ret = err;
+ continue;
}
}
+ /* only try to replay the journals if we prepared all of them */
for (i = 0, ji = jis; ret == 0 && i < max_nodes; i++, ji++) {
err = walk_journal(ost, i, ji, buf, 1);
if (err) {
@@ -492,32 +518,38 @@
continue;
}
- /* only write back the journal super block if we found out
- * where it was to begin with */
- if (ji->ji_jsb_block != 0) {
- journal_superblock_t *jsb = ji->ji_jsb;
+ /* only write back the journal super block if we were
+ * able to replay the journal */
+ if (ji->ji_jsb_block == 0)
+ continue;
- /* reset the journal */
- jsb->s_start = 0;
- /* XXX and if we haven't set final_seq? */
+ jsb = ji->ji_jsb;
+ /* reset the journal */
+ jsb->s_start = 0;
+
+ if (ji->ji_set_final_seq)
jsb->s_sequence = ji->ji_final_seq + 1;
- err = ocfs2_write_journal_superblock(ost->ost_fs,
- ji->ji_jsb_block,
- (char *)ji->ji_jsb);
- if (err)
- ret = err;
+ err = ocfs2_write_journal_superblock(ost->ost_fs,
+ ji->ji_jsb_block,
+ (char *)ji->ji_jsb);
+ if (err)
+ ret = err;
+ }
+
+out:
+ if (jis) {
+ for (i = 0, ji = jis; ret == 0 && i < max_nodes; i++, ji++) {
+ if (ji->ji_jsb)
+ ocfs2_free(&ji->ji_jsb);
+ if (ji->ji_cinode)
+ ocfs2_free_cached_inode(ost->ost_fs,
+ ji->ji_cinode);
+ revoke_free_all(&ji->ji_revoke);
}
-
- if (jis[i].ji_jsb)
- ocfs2_free(&jis[i].ji_jsb);
- if (jis[i].ji_cinode)
- ocfs2_free_cached_inode(ost->ost_fs, jis[i].ji_cinode);
- revoke_free_all(&jis[i].ji_revoke);
+ ocfs2_free(&jis);
}
- if (jis)
- ocfs2_free(&jis);
if (buf)
ocfs2_free(&buf);
Modified: trunk/libocfs2/ocfs2_err.et.in
===================================================================
--- trunk/libocfs2/ocfs2_err.et.in 2004-10-20 17:02:41 UTC (rev 340)
+++ trunk/libocfs2/ocfs2_err.et.in 2004-10-21 22:55:38 UTC (rev 341)
@@ -59,6 +59,9 @@
ec OCFS2_ET_BAD_JOURNAL_SUPERBLOCK_MAGIC,
"Bad magic number in journal superblock"
+ec OCFS2_ET_BAD_JOURNAL_REVOKE,
+ "Invalid revoke record in journal"
+
ec OCFS2_ET_INODE_NOT_VALID,
"Inode is not valid (active)"
More information about the Ocfs2-tools-commits
mailing list