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

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Oct 19 19:44:23 CDT 2004


Author: zab
Date: 2004-10-19 19:44:21 -0500 (Tue, 19 Oct 2004)
New Revision: 337

Added:
   trunk/fsck.ocfs2/include/journal.h
   trunk/fsck.ocfs2/journal.c
Modified:
   trunk/fsck.ocfs2/Makefile
   trunk/fsck.ocfs2/fsck.c
   trunk/fsck.ocfs2/include/pass1.h
   trunk/fsck.ocfs2/pass1.c
   trunk/fsck.ocfs2/pass2.c
   trunk/libocfs2/include/jfs_compat.h
   trunk/libocfs2/include/ocfs2.h
   trunk/libocfs2/mkjournal.c
   trunk/libocfs2/ocfs2_err.et.in
Log:
o journal replay in fsck that seems to do something.  still fragile.


Modified: trunk/fsck.ocfs2/Makefile
===================================================================
--- trunk/fsck.ocfs2/Makefile	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/fsck.ocfs2/Makefile	2004-10-20 00:44:21 UTC (rev 337)
@@ -17,6 +17,7 @@
 		dirblocks.c 	\
 		dirparents.c 	\
 		icount.c 	\
+		journal.c 	\
 		pass1.c 	\
 		pass2.c 	\
 		pass3.c 	\
@@ -29,6 +30,7 @@
 		include/dirblocks.h	\
 		include/dirparents.h	\
 		include/icount.h	\
+		include/journal.h	\
 		include/pass1.h		\
 		include/pass2.h		\
 		include/pass3.h		\

Modified: trunk/fsck.ocfs2/fsck.c
===================================================================
--- trunk/fsck.ocfs2/fsck.c	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/fsck.ocfs2/fsck.c	2004-10-20 00:44:21 UTC (rev 337)
@@ -34,6 +34,7 @@
 
 #include "fsck.h"
 #include "icount.h"
+#include "journal.h"
 #include "pass1.h"
 #include "pass2.h"
 #include "pass3.h"
@@ -254,10 +255,9 @@
 
 	/* XXX do we want checking for different revisions of ocfs2? */
 
-	/* XXX worry about the journal */
+	/* XXX should be verifying super-block bits here. 
+	 * like s_max_nodes, journal recovery trusts it. */
 
-	/* XXX should be verifying super-block bits here. */
-
 	/* ocfs2_open() already checked _incompat and _ro_compat */
 	if (OCFS2_RAW_SB(ost->ost_fs->fs_super)->s_feature_compat &
 	    ~OCFS2_FEATURE_COMPAT_SUPP) {
@@ -276,6 +276,8 @@
 	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_pass1(ost);
 	if (ret)
 		com_err(argv[0], ret, "pass1 failed");

Added: trunk/fsck.ocfs2/include/journal.h
===================================================================
--- trunk/fsck.ocfs2/include/journal.h	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/fsck.ocfs2/include/journal.h	2004-10-20 00:44:21 UTC (rev 337)
@@ -0,0 +1,32 @@
+/*
+ * journal.h
+ *
+ * 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.
+ *
+ * Author: Zach Brown
+ */
+
+#ifndef __O2FSCK_JOURNAL_H__
+#define __O2FSCK_JOURNAL_H__
+
+#include "fsck.h"
+
+errcode_t o2fsck_replay_journals(o2fsck_state *ost);
+
+#endif /* __O2FSCK_JOURNAL_H__ */
+

Modified: trunk/fsck.ocfs2/include/pass1.h
===================================================================
--- trunk/fsck.ocfs2/include/pass1.h	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/fsck.ocfs2/include/pass1.h	2004-10-20 00:44:21 UTC (rev 337)
@@ -27,6 +27,7 @@
 #include "fsck.h"
 
 errcode_t o2fsck_pass1(o2fsck_state *ost);
+void o2fsck_mark_block_used(o2fsck_state *ost, uint64_t blkno);
 
 #endif /* __O2FSCK_PASS1_H__ */
 

Added: trunk/fsck.ocfs2/journal.c
===================================================================
--- trunk/fsck.ocfs2/journal.c	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/fsck.ocfs2/journal.c	2004-10-20 00:44:21 UTC (rev 337)
@@ -0,0 +1,525 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * journal.c
+ *
+ * file system checker for OCFS2
+ *
+ * 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.
+ *
+ * Authors: Zach Brown
+ */
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "fsck.h"
+#include "journal.h"
+/* jfs_compat.h defines these */
+#undef cpu_to_be32
+#undef be32_to_cpu
+#include "jfs_user.h"
+#include "ocfs2.h"
+#include "pass1.h"
+#include "util.h"
+
+static char *whoami = "journal recovery";
+
+struct journal_info {
+	int			ji_node;
+	uint64_t		ji_ino;
+	struct rb_root		ji_revoke;
+	journal_superblock_t	*ji_jsb;
+	uint64_t		ji_jsb_block;
+	ocfs2_cached_inode	*ji_cinode;
+
+	uint32_t		ji_final_seq;
+};
+
+struct revoke_entry {
+	struct rb_node	r_node;
+	uint64_t	r_block;
+	uint32_t	r_seq;
+};
+
+static int seq_gt(uint32_t x, uint32_t y)
+{
+	int32_t diff = x - y;
+	return diff > 0;
+}
+static int seq_geq(uint32_t x, uint32_t y)
+{
+	int32_t diff = x - y;
+	return diff >= 0;
+}
+
+static void revoke_insert(struct rb_root *root, uint64_t block, uint32_t seq)
+{
+	struct rb_node ** p = &root->rb_node;
+	struct rb_node * parent = NULL;
+	struct revoke_entry *re;
+
+	while (*p)
+	{
+		parent = *p;
+		re = rb_entry(parent, struct revoke_entry, r_node);
+
+		if (block < re->r_block)
+			p = &(*p)->rb_left;
+		else if (block > re->r_block)
+			p = &(*p)->rb_right;
+		else {
+			if (seq_gt(seq, re->r_seq))
+				re->r_seq = seq;
+			return;
+		}
+	}
+
+	re = malloc(sizeof(struct revoke_entry));
+	if (re == NULL)
+		fatal_error(OCFS2_ET_NO_MEMORY, "while allocating "
+			    "space for revoke entries");
+
+	re->r_block = block;
+	re->r_seq = seq;
+
+	rb_link_node(&re->r_node, parent, p);
+	rb_insert_color(&re->r_node, root);
+}
+
+static int revoke_this_block(struct rb_root *root, uint64_t block, 
+		 	     uint32_t seq)
+{
+	struct rb_node *node = root->rb_node;
+	struct revoke_entry *re;
+
+	while (node) {
+		re = rb_entry(node, struct revoke_entry, r_node);
+
+		if (block < re->r_block)
+			node = node->rb_left;
+		else if (block > re->r_block)
+			node = node->rb_right;
+		else {
+			/* only revoke if we've recorded a revoke entry for
+			 * this block that is <= the seq that we're interested
+			 * in */
+			if (re && !seq_gt(seq, re->r_seq)) {
+				verbosef("%"PRIu64" is revoked\n", block);
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void revoke_free_all(struct rb_root *root)
+{
+	struct revoke_entry *re;
+	struct rb_node *node;
+
+	while((node = rb_first(root)) != NULL) {
+		re = rb_entry(node, struct revoke_entry, r_node);
+		rb_erase(node, root);
+		free(re);
+	}
+}
+
+static void 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;
+
+	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;
+	}
+
+	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);
+}
+
+static uint64_t jwrap(journal_superblock_t *jsb, uint64_t block)
+{
+	uint64_t diff = jsb->s_maxlen - jsb->s_first;
+
+	if (diff == 0) /* ugh */
+		return 0;
+
+	while (block > jsb->s_maxlen)
+		block -= diff;
+
+	return block;
+}
+
+static uint64_t count_tags(char *buf, size_t size)
+{
+	journal_block_tag_t *tag, *last;
+	uint64_t nr = 0;
+
+	if (size < sizeof(journal_header_t) + sizeof(*tag))
+		return 0;
+
+       	tag = (journal_block_tag_t *)&buf[sizeof(journal_header_t)];
+       	last = (journal_block_tag_t *)&buf[size - sizeof(*tag)];
+
+	for(; tag <= last; tag++) {
+		nr++;
+		if (tag->t_flags & cpu_to_be32(JFS_FLAG_LAST_TAG))
+			break;
+		/* inline uuids are 16 bytes, tags are 8 */
+		if (!(tag->t_flags & cpu_to_be32(JFS_FLAG_SAME_UUID)))
+			tag += 2;
+	}
+
+	return nr;
+}
+
+static errcode_t lookup_journal_block(o2fsck_state *ost, 
+				      struct journal_info *ji, 
+				      uint64_t blkoff,
+				      uint64_t *blkno)
+{
+	errcode_t err;
+	int contig;
+
+	err = ocfs2_extent_map_get_blocks(ji->ji_cinode->ci_map, blkoff,
+					  1, blkno, &contig);
+	if (err) 
+		com_err(whoami, err, "while looking up logical block "
+			"%"PRIu64" in node %d's journal", blkoff, ji->ji_node);
+#if 0
+	/* XXX when we more aggresively track blocks.. */
+	o2fsck_mark_block_used(ost, *blkno);
+#endif
+
+	return err;
+}
+
+static errcode_t read_journal_block(o2fsck_state *ost, 
+				    struct journal_info *ji, 
+				    uint64_t blkoff, 
+				    char *buf)
+{
+	errcode_t err;
+	uint64_t	blkno;
+
+	err = lookup_journal_block(ost, ji, blkoff, &blkno);
+	if (err)
+		return err;
+
+	err = io_read_block(ost->ost_fs->fs_io, blkno, 1, buf);
+	if (err)
+		com_err(whoami, err, "while reading block %"PRIu64" of node "
+			"%d's journal", blkno, ji->ji_node);
+
+	return err;
+}
+
+static errcode_t replay_blocks(o2fsck_state *ost, struct journal_info *ji,
+			       char *buf, uint64_t seq, uint64_t *next_block)
+{
+	journal_block_tag_t tag, *tagp;
+	size_t i, num;
+	char *io_buf = NULL;
+	errcode_t err, ret = 0;
+		
+	tagp = (journal_block_tag_t *)(buf + sizeof(journal_header_t));
+	num = (ji->ji_jsb->s_blocksize - sizeof(journal_header_t)) / 
+	      sizeof(tag);
+
+	ret = ocfs2_malloc_blocks(ost->ost_fs->fs_io, 1, &io_buf);
+	if (ret) {
+		com_err(whoami, ret, "while allocating a block buffer");
+		goto out;
+	}
+
+	for(i = 0; i < num; i++, tagp++, (*next_block)++) {
+		memcpy(&tag, tagp, sizeof(tag));
+		tag.t_flags = be32_to_cpu(tag.t_flags);
+		tag.t_blocknr = be32_to_cpu(tag.t_blocknr);
+
+		*next_block = jwrap(ji->ji_jsb, *next_block);
+
+		verbosef("recovering journal block %"PRIu64" to disk block "
+			 "%"PRIu32"\n", *next_block, tag.t_blocknr);	
+
+		if (revoke_this_block(&ji->ji_revoke, tag.t_blocknr, seq))
+			goto skip_io;
+
+		err = read_journal_block(ost, ji, *next_block, io_buf);
+		if (err) {
+			ret = err;
+			goto skip_io;
+		}
+
+		if (tag.t_flags & JFS_FLAG_ESCAPE) {
+			uint32_t magic = cpu_to_be32(JFS_MAGIC_NUMBER);
+			memcpy(io_buf, &magic, sizeof(magic));
+		}
+
+		err = io_write_block(ost->ost_fs->fs_io, tag.t_blocknr, 1, 
+				     io_buf);
+		if (err)
+			ret = err;
+
+	skip_io:
+		if (tag.t_flags & JFS_FLAG_LAST_TAG)
+			i = num; /* be sure to increment next_block */
+		/* inline uuids are 16 bytes, tags are 8 */
+		if (!(tag.t_flags & JFS_FLAG_SAME_UUID))
+			tagp += 2;
+	}
+	
+out:
+	if (io_buf)
+		ocfs2_free(&io_buf);
+	return ret;
+}
+
+static errcode_t walk_journal(o2fsck_state *ost, int node, 
+			      struct journal_info *ji, char *buf, int recover)
+{
+	errcode_t err = 0;
+	uint32_t next_seq;
+	uint64_t next_block;
+	journal_superblock_t *jsb = ji->ji_jsb;
+	journal_header_t jh;
+
+	next_seq = jsb->s_sequence;
+	next_block = jsb->s_start;
+
+	/* s_start == 0 when we have nothing to do */
+	if (next_block == 0)
+		return 0;
+
+	while(1) {
+		verbosef("next_seq %"PRIu32" next_block %"PRIu64"\n", next_seq, 
+			 next_block);
+
+		if (recover && seq_geq(next_seq, ji->ji_final_seq))
+			break;
+
+		err = read_journal_block(ost, ji, next_block, buf);
+		if (err)
+			break;
+
+		next_block = jwrap(jsb, next_block + 1);
+
+		memcpy(&jh, buf, sizeof(jh));
+		jh.h_magic = be32_to_cpu(jh.h_magic);
+		jh.h_blocktype = be32_to_cpu(jh.h_blocktype);
+		jh.h_sequence = be32_to_cpu(jh.h_sequence);
+
+		verbosef("jh magic %x\n", jh.h_magic);
+
+		if (jh.h_magic != JFS_MAGIC_NUMBER)
+			break;
+
+		verbosef("jh block %x\n", jh.h_blocktype);
+		verbosef("jh seq %"PRIu32"\n", jh.h_sequence);
+
+		if (jh.h_sequence != next_seq)
+			break;
+
+		switch(jh.h_blocktype) {
+		case JFS_DESCRIPTOR_BLOCK:
+			verbosef("found a desc type %x\n", jh.h_blocktype);
+			if (!recover) {
+				next_block = jwrap(jsb, next_block + 
+					    count_tags(buf, jsb->s_blocksize));
+				continue;
+			}
+
+			err = replay_blocks(ost, ji, buf, next_seq, 
+					    &next_block);
+			break;
+
+		case JFS_COMMIT_BLOCK:
+			verbosef("found a commit type %x\n", jh.h_blocktype);
+			next_seq++;
+			break;
+
+		case JFS_REVOKE_BLOCK:
+			verbosef("found a revoke type %x\n", jh.h_blocktype);
+			add_revoke_records(ji, buf, jsb->s_blocksize,
+					   next_seq);
+			break;
+
+		default:
+			verbosef("unknown type %x\n", jh.h_blocktype);
+			break;
+		}
+	}
+
+	verbosef("done scanning with seq %"PRIu32"\n", next_seq);
+
+	if (!recover)
+		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 "
+			"%"PRIu32" as we expected from a previous scan.",
+			next_seq, ji->ji_final_seq);
+	}
+
+	return err;
+}
+
+static errcode_t prep_journal_info(o2fsck_state *ost, int node,
+			           struct journal_info *ji)
+{
+	errcode_t err;
+
+	ji->ji_revoke = RB_ROOT;
+	ji->ji_node = node;
+
+	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 "
+			    "journal superblock", node);
+
+	err = ocfs2_lookup_system_inode(ost->ost_fs, JOURNAL_SYSTEM_INODE,
+					node, &ji->ji_ino);
+	if (err) {
+		com_err(whoami, err, "while looking up the journal inode for "
+			"node %d", node);
+		goto out;
+	}
+
+	err = ocfs2_read_cached_inode(ost->ost_fs, ji->ji_ino, &ji->ji_cinode);
+	if (err) {
+		com_err(whoami, err, "while reading cached inode %"PRIu64" "
+			"for node %d's journal", ji->ji_ino, node);
+		goto out;
+	}
+
+	err = ocfs2_extent_map_new(ost->ost_fs, ji->ji_cinode, 
+				   &ji->ji_cinode->ci_map);
+	if (err) {
+		com_err(whoami, err, "while initializing extent map");
+		goto out;
+	}
+
+	err = lookup_journal_block(ost, ji, 0, &ji->ji_jsb_block);
+	if (err)
+		goto out;
+
+	/* XXX be smarter about reading in the whole super block if it
+	 * spans multiple blocks */
+	err = ocfs2_read_journal_superblock(ost->ost_fs, ji->ji_jsb_block, 
+					    (char *)ji->ji_jsb);
+	if (err) {
+		com_err(whoami, err, "while reading block %"PRIu64" as node "
+			"%d's journal super block", ji->ji_jsb_block,
+			ji->ji_node);
+		goto out;
+	}
+
+	verbosef("jsb start %u maxlen %u\n", ji->ji_jsb->s_start,
+		 ji->ji_jsb->s_maxlen);
+out:
+	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 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;
+	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 "
+			    "blocks");
+
+	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");
+
+	/* 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) {
+			ret = err;
+			continue;
+		}
+
+		err = walk_journal(ost, i, &jis[i], buf, 0);
+		if (err) {
+			ret = err;
+		}
+	}
+
+	for (i = 0, ji = jis; ret == 0 && i < max_nodes; i++, ji++) {
+		err = walk_journal(ost, i, ji, buf, 1);
+		if (err) {
+			ret = err;
+			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;
+
+			/* reset the journal */
+			jsb->s_start = 0;
+			/* XXX and if we haven't set final_seq? */
+			jsb->s_sequence = ji->ji_final_seq + 1;
+
+			err = ocfs2_write_journal_superblock(ost->ost_fs,
+					ji->ji_jsb_block, ji->ji_jsb);
+			if (err)
+				ret = err;
+		}
+
+		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);
+	}
+
+	if (jis)
+		ocfs2_free(&jis);
+	if (buf)
+		ocfs2_free(&buf);
+
+	return ret;
+}

Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/fsck.ocfs2/pass1.c	2004-10-20 00:44:21 UTC (rev 337)
@@ -39,7 +39,7 @@
 
 static const char *whoami = "pass1";
 
-static void mark_block_used(o2fsck_state *ost, uint64_t blkno)
+void o2fsck_mark_block_used(o2fsck_state *ost, uint64_t blkno)
 {
 	int was_set;
 	ocfs2_bitmap_set(ost->ost_found_blocks, blkno, &was_set);
@@ -305,7 +305,7 @@
 	struct verifying_blocks *vb = priv_data;
 	verbosef("found gd block %"PRIu64"\n", gd_blkno);
 	/* don't have bcount */
-	mark_block_used(vb->vb_ost, gd_blkno);
+	o2fsck_mark_block_used(vb->vb_ost, gd_blkno);
 	vb_saw_block(vb, vb->vb_num_blocks);
 	return 0;
 }
@@ -319,7 +319,7 @@
 
 	if (tree_depth > 0) {
 		verbosef("found extent block %"PRIu64"\n", rec->e_blkno);
-		mark_block_used(vb->vb_ost, rec->e_blkno);
+		o2fsck_mark_block_used(vb->vb_ost, rec->e_blkno);
 	}
 
 	return 0;
@@ -448,6 +448,8 @@
 		if (!(di->i_flags & OCFS2_VALID_FL))
 			continue;
 
+		verbosef("found inode %"PRIu64"\n", blkno);
+
 		o2fsck_verify_inode_fields(fs, ost, blkno, di);
 
 		/* XXX be able to mark the blocks in the inode as 

Modified: trunk/fsck.ocfs2/pass2.c
===================================================================
--- trunk/fsck.ocfs2/pass2.c	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/fsck.ocfs2/pass2.c	2004-10-20 00:44:21 UTC (rev 337)
@@ -461,6 +461,8 @@
 				dbe->e_blkno);
 	}
 
+	verbosef("dir block %"PRIu64"\n", dbe->e_blkno);
+
 	while (offset < dd->fs->fs_blocksize) {
 		dirent = (struct ocfs2_dir_entry *)(dd->buf + offset);
 

Modified: trunk/libocfs2/include/jfs_compat.h
===================================================================
--- trunk/libocfs2/include/jfs_compat.h	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/libocfs2/include/jfs_compat.h	2004-10-20 00:44:21 UTC (rev 337)
@@ -4,9 +4,7 @@
 
 #include "kernel-list.h"
 #include <errno.h>
-#ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
-#endif
 
 // libocfs.h has these
 //#define printk printf

Modified: trunk/libocfs2/include/ocfs2.h
===================================================================
--- trunk/libocfs2/include/ocfs2.h	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/libocfs2/include/ocfs2.h	2004-10-20 00:44:21 UTC (rev 337)
@@ -274,6 +274,10 @@
 errcode_t ocfs2_create_journal_superblock(ocfs2_filesys *fs,
 					  uint32_t size, int flags,
 					  char **ret_jsb);
+errcode_t ocfs2_read_journal_superblock(ocfs2_filesys *fs, uint64_t blkno,
+					char *jsb_buf);
+errcode_t ocfs2_write_journal_superblock(ocfs2_filesys *fs, uint64_t blkno,
+					 char *jsb_buf);
 
 errcode_t ocfs2_read_extent_block(ocfs2_filesys *fs, uint64_t blkno,
        				  char *eb_buf);

Modified: trunk/libocfs2/mkjournal.c
===================================================================
--- trunk/libocfs2/mkjournal.c	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/libocfs2/mkjournal.c	2004-10-20 00:44:21 UTC (rev 337)
@@ -92,6 +92,99 @@
 	return 0;
 }
 
+errcode_t ocfs2_read_journal_superblock(ocfs2_filesys *fs, uint64_t blkno,
+					char *jsb_buf)
+{
+	errcode_t ret;
+	char *blk;
+	journal_superblock_t *disk, *jsb;
+	
+	if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) ||
+	    (blkno > fs->fs_blocks))
+		return OCFS2_ET_BAD_BLKNO;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &blk);
+	if (ret)
+		return ret;
+
+	ret = io_read_block(fs->fs_io, blkno, 1, blk);
+	if (ret)
+		goto out;
+
+	disk = (journal_superblock_t *)blk;
+	jsb = (journal_superblock_t *)jsb_buf;
+
+	if (disk->s_header.h_magic != htonl(JFS_MAGIC_NUMBER)) {
+		ret = OCFS2_ET_BAD_JOURNAL_SUPERBLOCK_MAGIC;
+		goto out;
+	}
+
+	memcpy(jsb_buf, blk, fs->fs_blocksize);
+
+	/* XXX incomplete */
+	jsb->s_header.h_magic = be32_to_cpu(disk->s_header.h_magic);
+	jsb->s_header.h_blocktype = be32_to_cpu(disk->s_header.h_blocktype);
+
+	jsb->s_blocksize = be32_to_cpu(disk->s_blocksize);
+	jsb->s_maxlen = be32_to_cpu(disk->s_maxlen);
+	jsb->s_first = be32_to_cpu(disk->s_first);
+	jsb->s_start = be32_to_cpu(disk->s_start);
+	jsb->s_sequence = be32_to_cpu(disk->s_sequence);
+	jsb->s_errno = be32_to_cpu(disk->s_errno);
+
+	ret = 0;
+out:
+	ocfs2_free(&blk);
+
+	return ret;
+}
+
+errcode_t ocfs2_write_journal_superblock(ocfs2_filesys *fs, uint64_t blkno,
+					 char *jsb_buf)
+{
+	errcode_t ret;
+	char *blk;
+	journal_superblock_t *disk, *jsb;
+	
+	if (!(fs->fs_flags & OCFS2_FLAG_RW))
+		return OCFS2_ET_RO_FILESYS;
+
+	if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) ||
+	    (blkno > fs->fs_blocks))
+		return OCFS2_ET_BAD_BLKNO;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &blk);
+	if (ret)
+		return ret;
+
+	disk = (journal_superblock_t *)blk;
+	jsb = (journal_superblock_t *)jsb_buf;
+
+	memcpy(blk, jsb_buf, fs->fs_blocksize);
+
+	/* XXX incomplete */
+	disk->s_header.h_magic = cpu_to_be32(jsb->s_header.h_magic);
+	disk->s_header.h_blocktype = cpu_to_be32(jsb->s_header.h_blocktype);
+
+	disk->s_blocksize = cpu_to_be32(jsb->s_blocksize);
+	disk->s_maxlen = cpu_to_be32(jsb->s_maxlen);
+	disk->s_first = cpu_to_be32(jsb->s_first);
+	disk->s_start = cpu_to_be32(jsb->s_start);
+	disk->s_sequence = cpu_to_be32(jsb->s_sequence);
+	disk->s_errno = cpu_to_be32(jsb->s_errno);
+
+	ret = io_write_block(fs->fs_io, blkno, 1, blk);
+	if (ret)
+		goto out;
+
+	fs->fs_flags |= OCFS2_FLAG_CHANGED;
+	ret = 0;
+out:
+	ocfs2_free(&blk);
+
+	return ret;
+}
+
 #ifdef DEBUG_EXE
 #if 0
 static uint64_t read_number(const char *num)

Modified: trunk/libocfs2/ocfs2_err.et.in
===================================================================
--- trunk/libocfs2/ocfs2_err.et.in	2004-10-19 18:21:39 UTC (rev 336)
+++ trunk/libocfs2/ocfs2_err.et.in	2004-10-20 00:44:21 UTC (rev 337)
@@ -56,6 +56,9 @@
 ec	OCFS2_ET_JOURNAL_TOO_SMALL,
 	"Journal must be at least 1024 blocks"
 
+ec	OCFS2_ET_BAD_JOURNAL_SUPERBLOCK_MAGIC,
+	"Bad magic number in journal superblock"
+
 ec	OCFS2_ET_INODE_NOT_VALID,
 	"Inode is not valid (active)"
 



More information about the Ocfs2-tools-commits mailing list