[Ocfs2-tools-devel] [PATCH 03/50] libocfs2: Add ocfs2_read_refcount_block().

Tao Ma tao.ma at oracle.com
Mon Jan 11 07:30:49 PST 2010


From: Joel Becker <joel.becker at oracle.com>

The extent list swap code learns about leaf extent records for refcount
trees, and we now can read refcount blocks.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 include/ocfs2/ocfs2.h |    8 +++
 libocfs2/Makefile     |    3 +-
 libocfs2/refcount.c   |  158 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 168 insertions(+), 1 deletions(-)
 create mode 100644 libocfs2/refcount.c

diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 3770a81..68c1dd9 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -384,6 +384,14 @@ errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs, uint64_t blkno,
 					  char *eb_buf);
 errcode_t ocfs2_write_extent_block(ocfs2_filesys *fs, uint64_t blkno,
        				   char *eb_buf);
+void ocfs2_swap_refcount_list_to_cpu(ocfs2_filesys *fs, void *obj,
+				     struct ocfs2_refcount_list *rl);
+void ocfs2_swap_refcount_block_to_cpu(ocfs2_filesys *fs,
+				      struct ocfs2_refcount_block *rb);
+errcode_t ocfs2_read_refcount_block(ocfs2_filesys *fs, uint64_t blkno,
+				    char *eb_buf);
+errcode_t ocfs2_read_refcount_block_nocheck(ocfs2_filesys *fs, uint64_t blkno,
+					    char *eb_buf);
 errcode_t ocfs2_swap_dir_entries_from_cpu(void *buf, uint64_t bytes);
 errcode_t ocfs2_swap_dir_entries_to_cpu(void *buf, uint64_t bytes);
 void ocfs2_swap_dir_trailer(struct ocfs2_dir_block_trailer *trailer);
diff --git a/libocfs2/Makefile b/libocfs2/Makefile
index 8e94cc3..cafa075 100644
--- a/libocfs2/Makefile
+++ b/libocfs2/Makefile
@@ -76,7 +76,8 @@ CFILES = 		\
 	quota.c		\
 	image.c		\
 	xattr.c		\
-	extent_tree.c
+	extent_tree.c	\
+	refcount.c
 
 HFILES =		\
 	bitmap.h	\
diff --git a/libocfs2/refcount.c b/libocfs2/refcount.c
new file mode 100644
index 0000000..f8f26c4
--- /dev/null
+++ b/libocfs2/refcount.c
@@ -0,0 +1,158 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * refcount.c
+ *
+ * Functions for the refcount tree structure.  Part of the OCFS2 userspace
+ * library.
+ *
+ * Copyright (C) 2009 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.
+ */
+
+#define _XOPEN_SOURCE 600  /* Triggers XOPEN2K in features.h */
+#define _LARGEFILE64_SOURCE
+
+#include <string.h>
+#include <inttypes.h>
+
+#include "ocfs2/byteorder.h"
+#include "ocfs2/ocfs2.h"
+
+
+static void ocfs2_swap_refcount_list_primary(struct ocfs2_refcount_list *rl)
+{
+	rl->rl_count	= bswap_16(rl->rl_count);
+	rl->rl_used	= bswap_16(rl->rl_used);
+}
+
+static void ocfs2_swap_refcount_list_secondary(ocfs2_filesys *fs, void *obj,
+					       struct ocfs2_refcount_list *rl)
+{
+	int i;
+
+	for (i = 0; i < rl->rl_count; i++) {
+		struct ocfs2_refcount_rec *rec = &rl->rl_recs[i];
+
+		if (ocfs2_swap_barrier(fs, obj, rec,
+				       sizeof(struct ocfs2_refcount_rec)))
+			break;
+
+		rec->r_cpos	= bswap_64(rec->r_cpos);
+		rec->r_clusters	= bswap_32(rec->r_clusters);
+		rec->r_refcount	= bswap_32(rec->r_refcount);
+	}
+}
+
+void ocfs2_swap_refcount_list_to_cpu(ocfs2_filesys *fs, void *obj,
+				     struct ocfs2_refcount_list *rl)
+{
+	if (cpu_is_little_endian)
+		return;
+
+	ocfs2_swap_refcount_list_primary(rl);
+	ocfs2_swap_refcount_list_secondary(fs, obj, rl);
+}
+
+static void ocfs2_swap_refcount_block_header(struct ocfs2_refcount_block *rb)
+{
+
+	rb->rf_suballoc_slot	= bswap_16(rb->rf_suballoc_slot);
+	rb->rf_suballoc_bit	= bswap_16(rb->rf_suballoc_bit);
+	rb->rf_fs_generation	= bswap_32(rb->rf_fs_generation);
+	rb->rf_blkno		= bswap_64(rb->rf_blkno);
+	rb->rf_parent		= bswap_64(rb->rf_parent);
+	rb->rf_last_eb_blk	= bswap_64(rb->rf_last_eb_blk);
+	rb->rf_count		= bswap_32(rb->rf_count);
+	rb->rf_flags		= bswap_32(rb->rf_flags);
+	rb->rf_clusters		= bswap_32(rb->rf_clusters);
+	rb->rf_cpos		= bswap_32(rb->rf_cpos);
+}
+
+void ocfs2_swap_refcount_block_to_cpu(ocfs2_filesys *fs,
+				      struct ocfs2_refcount_block *rb)
+{
+	if (cpu_is_little_endian)
+		return;
+
+	ocfs2_swap_refcount_block_header(rb);
+	if (rb->rf_flags & OCFS2_REFCOUNT_TREE_FL)
+		ocfs2_swap_extent_list_to_cpu(fs, rb, &rb->rf_list);
+	else
+		ocfs2_swap_refcount_list_to_cpu(fs, rb, &rb->rf_records);
+}
+
+errcode_t ocfs2_read_refcount_block_nocheck(ocfs2_filesys *fs,
+					    uint64_t blkno,
+					    char *rb_buf)
+{
+	errcode_t ret;
+	char *blk;
+	struct ocfs2_refcount_block *rb;
+
+	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 = ocfs2_read_blocks(fs, blkno, 1, blk);
+	if (ret)
+		goto out;
+
+	rb = (struct ocfs2_refcount_block *)blk;
+
+	ret = ocfs2_validate_meta_ecc(fs, blk, &rb->rf_check);
+	if (ret)
+		goto out;
+
+	if (memcmp(rb->rf_signature, OCFS2_REFCOUNT_BLOCK_SIGNATURE,
+		   strlen(OCFS2_REFCOUNT_BLOCK_SIGNATURE))) {
+		ret = OCFS2_ET_BAD_EXTENT_BLOCK_MAGIC;
+		goto out;
+	}
+
+	memcpy(rb_buf, blk, fs->fs_blocksize);
+
+	rb = (struct ocfs2_refcount_block *) rb_buf;
+	ocfs2_swap_refcount_block_to_cpu(fs, rb);
+
+out:
+	ocfs2_free(&blk);
+
+	return ret;
+}
+
+errcode_t ocfs2_read_refcount_block(ocfs2_filesys *fs, uint64_t blkno,
+				    char *rb_buf)
+{
+	errcode_t ret;
+	struct ocfs2_refcount_block *rb =
+		(struct ocfs2_refcount_block *)rb_buf;
+
+	ret = ocfs2_read_refcount_block_nocheck(fs, blkno, rb_buf);
+
+	/*
+	 * Return corruption error here if the user may have a chance
+	 * to walk off the end.
+	 * XXX: We trust the rb->rf_flags here.
+	 */
+	if (ret == 0 &&
+	    (((rb->rf_flags & OCFS2_REFCOUNT_TREE_FL) &&
+	     rb->rf_list.l_next_free_rec > rb->rf_list.l_count) ||
+	     (!(rb->rf_flags & OCFS2_REFCOUNT_TREE_FL) &&
+	     rb->rf_records.rl_used > rb->rf_records.rl_count)))
+		ret = OCFS2_ET_CORRUPT_EXTENT_BLOCK;
+
+	return ret;
+}
-- 
1.5.5




More information about the Ocfs2-tools-devel mailing list