[Ocfs2-tools-devel] [PATCH 4/4] Ocfs2-tools: Fix bug in libocfs2's swap code to let fswreck behave correctly in big endian machine.

Tristan Ye tristan.ye at oracle.com
Wed Jun 24 03:44:15 PDT 2009


Currently, ocfs2_write_inode() and ocfs2_read_inode() in libocfs2 will swap
all its field to make it big-endian compatible when writting to disk or reading
from disk. It will be fine when we write/read the inode/extent in a normal case,
which means the field of inode we're going to write/read is correct. However, in
the fswreck's case, we corrupted some fields(such as cl_next_free_rec, tl_count etc)
which will be used later as a count number to swap rec[i]'s field in a loop. that will
definitely leads to an error in a big-endian platform where swap code being introduced.

The strategy we use here is to correct the count number in libocfs2 swap code just like
fsck.ocfs2 did. Note that we only correct the count number but leave the field which
corrupted by fswreck unchanged there.

Following prompt codes which failed in the big-endian machine before will benefit from this patch,

EXTENT_LIST_FREE
CHAIN_NEXT_FREE
LALLOC_BM_SIZE
LALLOC_BM_OVERRUN
LALLOC_BM_STRADDL
LALLOC_USED_OVERRUN
LALLOC_CLEAR
DEALLOC_COUNT

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 fswreck/local_alloc.c |    6 +++---
 libocfs2/extents.c    |   16 ++++++++++++++--
 libocfs2/inode.c      |   25 +++++++++++++++++++++----
 3 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/fswreck/local_alloc.c b/fswreck/local_alloc.c
index b95efcc..eb9187e 100644
--- a/fswreck/local_alloc.c
+++ b/fswreck/local_alloc.c
@@ -87,10 +87,10 @@ static void create_local_alloc(ocfs2_filesys *fs, uint64_t blkno)
 
 	la = &(di->id2.i_lab);
 
-	la->la_bm_off = cpu_to_le32(la_off);
-	di->id1.bitmap1.i_total = cpu_to_le32(la_size);
+	la->la_bm_off = la_off;
+	di->id1.bitmap1.i_total = la_size;
 	di->id1.bitmap1.i_used = 0;
-	memset(la->la_bitmap, 0, le16_to_cpu(la->la_size));
+	memset(la->la_bitmap, 0, la->la_size);
 	
 	ret = ocfs2_write_inode(fs, blkno, buf);
 	if (ret)
diff --git a/libocfs2/extents.c b/libocfs2/extents.c
index 4b6808a..0fcb310 100644
--- a/libocfs2/extents.c
+++ b/libocfs2/extents.c
@@ -35,6 +35,8 @@
 #include "ocfs2/byteorder.h"
 #include "ocfs2/ocfs2.h"
 
+static uint16_t max_ext_recs = 0;
+
 static void ocfs2_swap_extent_list_primary(struct ocfs2_extent_list *el)
 {
 	el->l_tree_depth = bswap_16(el->l_tree_depth);
@@ -44,9 +46,15 @@ static void ocfs2_swap_extent_list_primary(struct ocfs2_extent_list *el)
 
 static void ocfs2_swap_extent_list_secondary(struct ocfs2_extent_list *el)
 {
-	uint16_t i;
+	uint16_t i, num_recs = el->l_next_free_rec;
+
+	if (max_ext_recs > el->l_count)
+		max_ext_recs = el->l_count;
+
+	if (el->l_next_free_rec > max_ext_recs)
+		num_recs = el->l_count;
 
-	for(i = 0; i < el->l_next_free_rec; i++) {
+	for(i = 0; i < num_recs; i++) {
 		struct ocfs2_extent_rec *rec = &el->l_recs[i];
 
 		rec->e_cpos = bswap_32(rec->e_cpos);
@@ -153,6 +161,8 @@ errcode_t ocfs2_read_extent_block(ocfs2_filesys *fs, uint64_t blkno,
 	struct ocfs2_extent_block *eb =
 		(struct ocfs2_extent_block *)eb_buf;
 
+	max_ext_recs = ocfs2_extent_recs_per_eb(fs->fs_blocksize);
+
 	ret = ocfs2_read_extent_block_nocheck(fs, blkno, eb_buf);
 
 	if (ret == 0 && eb->h_list.l_next_free_rec > eb->h_list.l_count)
@@ -175,6 +185,8 @@ errcode_t ocfs2_write_extent_block(ocfs2_filesys *fs, uint64_t blkno,
 	    (blkno > fs->fs_blocks))
 		return OCFS2_ET_BAD_BLKNO;
 
+	max_ext_recs = ocfs2_extent_recs_per_eb(fs->fs_blocksize);
+
 	ret = ocfs2_malloc_block(fs->fs_io, &blk);
 	if (ret)
 		return ret;
diff --git a/libocfs2/inode.c b/libocfs2/inode.c
index e786f5e..f4fa21e 100644
--- a/libocfs2/inode.c
+++ b/libocfs2/inode.c
@@ -34,6 +34,8 @@
 #include "ocfs2/byteorder.h"
 #include "ocfs2/ocfs2.h"
 
+static uint16_t max_chain_recs = 0;
+static uint16_t max_trunc_recs = 0;
 
 errcode_t ocfs2_check_directory(ocfs2_filesys *fs, uint64_t dir)
 {
@@ -68,9 +70,15 @@ static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
 
 	if (di->i_flags & OCFS2_CHAIN_FL) {
 		struct ocfs2_chain_list *cl = &di->id2.i_chain;
-		uint16_t i;
+		uint16_t i, num_recs = cl->cl_next_free_rec;
 
-		for (i = 0; i < cl->cl_next_free_rec; i++) {
+		if (max_chain_recs > cl->cl_count)
+			max_chain_recs = cl->cl_count;
+
+		if (cl->cl_next_free_rec > max_chain_recs)
+			num_recs = cl->cl_count;
+
+		for (i = 0; i < num_recs; i++) {
 			struct ocfs2_chain_rec *rec = &cl->cl_recs[i];
 
 			rec->c_free  = bswap_32(rec->c_free);
@@ -80,9 +88,12 @@ static void ocfs2_swap_inode_third(struct ocfs2_dinode *di)
 
 	} else if (di->i_flags & OCFS2_DEALLOC_FL) {
 		struct ocfs2_truncate_log *tl = &di->id2.i_dealloc;
-		uint16_t i;
+		uint16_t i, count = tl->tl_count;
 
-		for(i = 0; i < tl->tl_count; i++) {
+		if (tl->tl_count > max_trunc_recs)
+			count = max_trunc_recs;
+
+		for(i = 0; i < count; i++) {
 			struct ocfs2_truncate_rec *rec =
 				&tl->tl_recs[i];
 
@@ -263,6 +274,9 @@ errcode_t ocfs2_read_inode(ocfs2_filesys *fs, uint64_t blkno,
 	    (blkno > fs->fs_blocks))
 		return OCFS2_ET_BAD_BLKNO;
 
+	max_chain_recs = ocfs2_chain_recs_per_inode(fs->fs_blocksize);
+	max_trunc_recs = ocfs2_truncate_recs_per_inode(fs->fs_blocksize);
+
 	ret = ocfs2_malloc_block(fs->fs_io, &blk);
 	if (ret)
 		return ret;
@@ -306,6 +320,9 @@ errcode_t ocfs2_write_inode(ocfs2_filesys *fs, uint64_t blkno,
 	if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) ||
 	    (blkno > fs->fs_blocks))
 		return OCFS2_ET_BAD_BLKNO;
+	
+	max_chain_recs = ocfs2_chain_recs_per_inode(fs->fs_blocksize);
+	max_trunc_recs = ocfs2_truncate_recs_per_inode(fs->fs_blocksize);
 
 	ret = ocfs2_malloc_block(fs->fs_io, &blk);
 	if (ret)
-- 
1.5.5




More information about the Ocfs2-tools-devel mailing list