[Ocfs2-tools-devel] [PATCH 2/2] ocfs2-tools: Add extended attribute support in fsck.ocfs2

Tiger Yang tiger.yang at oracle.com
Mon Aug 25 21:57:57 PDT 2008


This patch will check all extended attribute associated with each inode,
mark all xattr block as used.

Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
 fsck.ocfs2/Makefile             |    3 +-
 fsck.ocfs2/extent.c             |   17 +--
 fsck.ocfs2/include/extent.h     |   13 ++
 fsck.ocfs2/include/xattr.h      |   29 +++
 fsck.ocfs2/pass1.c              |   18 ++-
 fsck.ocfs2/xattr.c              |  420 +++++++++++++++++++++++++++++++++++++++
 include/ocfs2-kernel/ocfs2_fs.h |    7 +
 include/ocfs2/ocfs2.h           |    6 +
 libocfs2/extend_file.c          |    4 +-
 libocfs2/extent_map.c           |    2 +-
 libocfs2/ocfs2_err.et           |    3 +
 libocfs2/xattr.c                |  110 ++++++++++
 12 files changed, 609 insertions(+), 23 deletions(-)
 create mode 100644 fsck.ocfs2/include/xattr.h
 create mode 100644 fsck.ocfs2/xattr.c

diff --git a/fsck.ocfs2/Makefile b/fsck.ocfs2/Makefile
index b804f67..f60515c 100644
--- a/fsck.ocfs2/Makefile
+++ b/fsck.ocfs2/Makefile
@@ -30,7 +30,8 @@ CFILES =	fsck.c		\
 		pass4.c 	\
 		problem.c 	\
 		strings.c 	\
-		util.c
+		util.c		\
+		xattr.c
 
 HFILES = 	include/fsck.h		\
 		include/dirblocks.h	\
diff --git a/fsck.ocfs2/extent.c b/fsck.ocfs2/extent.c
index 665704d..5f6639c 100644
--- a/fsck.ocfs2/extent.c
+++ b/fsck.ocfs2/extent.c
@@ -46,19 +46,6 @@
 
 static const char *whoami = "extent.c";
 
-struct extent_info {
-	uint64_t	ei_max_size;
-	uint64_t	ei_clusters;
-	uint64_t	ei_last_eb_blk;
-	uint16_t	ei_expected_depth;
-	unsigned	ei_expect_depth:1;
-};
-
-static errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
-			  struct ocfs2_dinode *di,
-			  struct ocfs2_extent_list *el,
-			  uint16_t max_recs, int *changed);
-
 static errcode_t check_eb(o2fsck_state *ost, struct extent_info *ei,
 			  struct ocfs2_dinode *di, uint64_t blkno,
 			  int *is_valid)
@@ -233,7 +220,7 @@ out:
 	return ret;
 }
 
-static errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
+errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
 			  struct ocfs2_dinode *di,
 			  struct ocfs2_extent_list *el,
 			  uint16_t max_recs, int *changed)
@@ -373,4 +360,4 @@ errcode_t o2fsck_check_extents(o2fsck_state *ost,
 		o2fsck_write_inode(ost, di->i_blkno, di);
 
 	return ret;
-}	
+}
diff --git a/fsck.ocfs2/include/extent.h b/fsck.ocfs2/include/extent.h
index 6fff28b..1266b7f 100644
--- a/fsck.ocfs2/include/extent.h
+++ b/fsck.ocfs2/include/extent.h
@@ -22,8 +22,21 @@
 
 #include "fsck.h"
 
+struct extent_info {
+	uint64_t	ei_max_size;
+	uint64_t	ei_clusters;
+	uint64_t	ei_last_eb_blk;
+	uint16_t	ei_expected_depth;
+	unsigned	ei_expect_depth:1;
+};
+
 errcode_t o2fsck_check_extents(o2fsck_state *ost,
                                struct ocfs2_dinode *di);
 
+errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
+			  struct ocfs2_dinode *di,
+			  struct ocfs2_extent_list *el,
+			  uint16_t max_recs, int *changed);
+
 #endif /* __O2FSCK_EXTENT_H__ */
 
diff --git a/fsck.ocfs2/include/xattr.h b/fsck.ocfs2/include/xattr.h
new file mode 100644
index 0000000..49ad945
--- /dev/null
+++ b/fsck.ocfs2/include/xattr.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef __O2FSCK_XATTR_H__
+#define __O2FSCK_XATTR_H__
+
+#include "fsck.h"
+
+errcode_t o2fsck_check_xattr(o2fsck_state *ost,
+			     struct ocfs2_dinode *di);
+
+#endif /* __O2FSCK_XATTR_H__ */
+
diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
index 70611b4..471a0be 100644
--- a/fsck.ocfs2/pass1.c
+++ b/fsck.ocfs2/pass1.c
@@ -59,6 +59,7 @@
 
 #include "dirblocks.h"
 #include "dirparents.h"
+#include "xattr.h"
 #include "extent.h"
 #include "icount.h"
 #include "fsck.h"
@@ -758,13 +759,22 @@ static errcode_t o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
 		.vb_di = di,
 	};
 
+	if (di->i_flags & (OCFS2_SUPER_BLOCK_FL | OCFS2_LOCAL_ALLOC_FL |
+			   OCFS2_BITMAP_FL | OCFS2_CHAIN_FL |
+			   OCFS2_DEALLOC_FL))
+		return 0;
+
+	ret = o2fsck_check_xattr(ost, di);
+	if (ret) {
+		com_err(whoami, ret, "while iterating over the xattr blocks "
+			"for inode %"PRIu64, di->i_blkno);
+		goto out;
+	}
+
 	/* don't bother to verify for inodes that don't have i_list,
 	 * we have to trust i_mode/i_clusters to tell us that a symlink
 	 * has put target data in the union instead of i_list */
-	if ((di->i_flags & (OCFS2_SUPER_BLOCK_FL | OCFS2_LOCAL_ALLOC_FL |
-			    OCFS2_BITMAP_FL | OCFS2_CHAIN_FL |
-			    OCFS2_DEALLOC_FL)) ||
-	    (S_ISLNK(di->i_mode) && di->i_clusters == 0))
+	if (S_ISLNK(di->i_mode) && di->i_clusters == 0)
 		return 0;
 
 	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
diff --git a/fsck.ocfs2/xattr.c b/fsck.ocfs2/xattr.c
new file mode 100644
index 0000000..15fa934
--- /dev/null
+++ b/fsck.ocfs2/xattr.c
@@ -0,0 +1,420 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * 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.
+ */
+#include <string.h>
+#include <inttypes.h>
+
+#include "ocfs2/byteorder.h"
+#include "ocfs2/ocfs2.h"
+
+#include "xattr.h"
+#include "extent.h"
+#include "fsck.h"
+#include "problem.h"
+#include "util.h"
+
+static const char *whoami = "xattr.c";
+
+static inline int ocfs2_xattr_extent_recs_per_inode(int blocksize)
+{
+	int size;
+
+	size = blocksize - offsetof(struct ocfs2_xattr_block,
+				    xb_attrs.xb_root.xt_list.l_recs);
+
+	return (size / sizeof(struct ocfs2_extent_rec));
+}
+
+static inline uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs)
+{
+	return (fs->fs_clustersize / OCFS2_XATTR_BUCKET_SIZE);
+}
+
+static inline uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs)
+{
+	return (OCFS2_XATTR_BUCKET_SIZE / fs->fs_blocksize);
+}
+
+static errcode_t check_xattr(o2fsck_state *ost,
+			     struct ocfs2_dinode *di,
+			     struct ocfs2_xattr_header *xh,
+			     int *changed)
+{
+	struct extent_info ei = {0, };
+	int i;
+	errcode_t ret = 0;
+
+	for (i = 0 ; i < xh->xh_count; i++) {
+		int change = 0;
+		struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
+
+		if (!xe->xe_local) {
+			struct ocfs2_xattr_value_root *xv =
+				(struct ocfs2_xattr_value_root *)
+				((void *)xh + xe->xe_name_offset +
+				OCFS2_XATTR_SIZE(xe->xe_name_len));
+			struct ocfs2_extent_list *el = &xv->xr_list;
+			ret = check_el(ost, &ei, di, el, 1, &change);
+			if (ret)
+				break;
+			if (change) {
+				*changed = 1;
+				ocfs2_swap_extent_list_from_cpu(el);
+			}
+		}
+	}
+
+	return ret;
+}
+
+static errcode_t ocfs2_read_xattr_block(ocfs2_filesys *fs,
+				 uint64_t blkno,
+				 char *xb_buf)
+{
+	errcode_t ret = 0;
+	char *blk;
+	struct ocfs2_xattr_block *xb;
+
+	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;
+
+	xb = (struct ocfs2_xattr_block *)blk;
+
+	if (memcmp(xb->xb_signature, OCFS2_XATTR_BLOCK_SIGNATURE,
+		   strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
+		ret = OCFS2_ET_BAD_XATTR_BLOCK_MAGIC;
+		goto out;
+	}
+
+	memcpy(xb_buf, blk, fs->fs_blocksize);
+
+	xb = (struct ocfs2_xattr_block *)xb_buf;
+	ocfs2_swap_xattr_block_to_cpu(xb);
+
+out:
+	ocfs2_free(&blk);
+
+	return ret;
+}
+
+
+static errcode_t ocfs2_write_xattr_block(ocfs2_filesys *fs,
+					 uint64_t blkno,
+					 char *xb_buf)
+{
+	errcode_t ret = 0;
+	char *blk;
+	struct ocfs2_xattr_block *xb;
+
+	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;
+
+	memcpy(blk, xb_buf, fs->fs_blocksize);
+
+	xb = (struct ocfs2_xattr_block *)blk;
+	ocfs2_swap_xattr_block_from_cpu(xb);
+
+	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;
+}
+
+static errcode_t ocfs2_xattr_get_rec(o2fsck_state *ost,
+				     struct ocfs2_dinode *di,
+				     uint32_t name_hash,
+				     uint64_t *p_blkno,
+				     uint32_t *e_cpos,
+				     uint32_t *num_clusters,
+				     struct ocfs2_extent_list *el)
+{
+	int i;
+	errcode_t ret = 0;
+	char *eb_buf = NULL;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_rec *rec = NULL;
+	uint64_t e_blkno = 0;
+
+	if (el->l_tree_depth) {
+		ret = ocfs2_find_leaf(ost->ost_fs, di, el, name_hash, &eb_buf);
+		if (ret) {
+			com_err(whoami, ret, "while finding leaf of xattr "
+				"tree");
+			goto out;
+		}
+
+		eb = (struct ocfs2_extent_block *) eb_buf;
+		el = &eb->h_list;
+
+		if (el->l_tree_depth) {
+			ret = -1;
+			goto out;
+		}
+	}
+
+	for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {
+		rec = &el->l_recs[i];
+
+		if (le32_to_cpu(rec->e_cpos) <= name_hash) {
+			e_blkno = le64_to_cpu(rec->e_blkno);
+			break;
+		}
+	}
+
+	if (!e_blkno) {
+		ret = -1;
+		goto out;
+	}
+
+	*p_blkno = le64_to_cpu(rec->e_blkno);
+	*num_clusters = le16_to_cpu(rec->e_leaf_clusters);
+	if (e_cpos)
+		*e_cpos = le32_to_cpu(rec->e_cpos);
+out:
+	if (eb_buf)
+		ocfs2_free(&eb_buf);
+	return ret;
+}
+
+static errcode_t ocfs2_iterate_xattr_buckets(o2fsck_state *ost,
+					     struct ocfs2_dinode *di,
+					     uint64_t blkno,
+					     uint32_t clusters)
+{
+	int i;
+	errcode_t ret = 0;
+	char *bucket = NULL;
+	struct ocfs2_xattr_header *xh;
+	int block_num = ocfs2_blocks_per_xattr_bucket(ost->ost_fs);
+	uint32_t bpc = ocfs2_xattr_buckets_per_cluster(ost->ost_fs);
+	uint32_t bucket_num = clusters * bpc;
+	char *bhs = NULL;
+
+
+	ret = ocfs2_malloc_blocks(ost->ost_fs->fs_io, block_num, &bhs);
+	if (ret) {
+		com_err(whoami, ret, "while allocating room to read bucket "
+			"of xattr data");
+		goto out;
+	}
+
+	for (i = 0; i < bucket_num; i++, blkno += block_num) {
+		int changed = 0;
+
+		ret = io_read_block(ost->ost_fs->fs_io, blkno, block_num, bhs);
+		if (ret) {
+			com_err(whoami, ret, "while reading blocks of xattr "
+				"bucket");
+			goto out;
+		}
+
+		bucket = bhs;
+
+		xh = (struct ocfs2_xattr_header *)bucket;
+		ocfs2_swap_xattr_header(xh);
+		ocfs2_swap_xattr_entries_to_cpu(xh);
+		/*
+		 * The real bucket num in this series of blocks is stored
+		 * in the 1st bucket.
+		 */
+		if (i == 0)
+			bucket_num = le16_to_cpu(xh->xh_reserved1);
+
+		ret = check_xattr(ost, di, xh, &changed);
+		if (ret)
+			break;
+		if (changed) {
+			ocfs2_swap_xattr_entries_from_cpu(xh);
+			ocfs2_swap_xattr_header(xh);
+			io_write_block(ost->ost_fs->fs_io, blkno, block_num,
+				       bhs);
+		}
+	}
+out:
+	ocfs2_free(&bhs);
+
+	return ret;
+}
+
+static errcode_t o2fsck_check_xattr_index_block(
+					o2fsck_state *ost,
+					struct ocfs2_dinode *di,
+					struct ocfs2_xattr_tree_root *xt,
+					int *changed)
+{
+	struct ocfs2_extent_list *el = &xt->xt_list;
+	errcode_t ret = 0;
+	uint32_t name_hash = UINT_MAX, e_cpos = 0, num_clusters = 0;
+	uint64_t p_blkno = 0;
+	struct extent_info ei = {0, };
+
+	if (el->l_next_free_rec == 0)
+		return 0;
+
+	ret = check_el(ost, &ei, di, el,
+		ocfs2_xattr_extent_recs_per_inode(ost->ost_fs->fs_blocksize),
+		changed);
+	if (ret)
+		return ret;
+
+	while (name_hash > 0) {
+		ret = ocfs2_xattr_get_rec(ost, di, name_hash, &p_blkno,
+					  &e_cpos, &num_clusters, el);
+		if (ret) {
+			com_err(whoami, ret, "while getting bucket record "
+				"of xattr data.");
+			goto out;
+		}
+
+		ret = ocfs2_iterate_xattr_buckets(ost, di, p_blkno,
+						  num_clusters);
+		if (ret) {
+			com_err(whoami, ret, "while iterating buckets "
+				"of xattr data.");
+			goto out;
+		}
+
+		if (e_cpos == 0)
+			break;
+
+		name_hash = e_cpos - 1;
+	}
+	if (*changed)
+		ocfs2_swap_extent_list_from_cpu(el);
+
+out:
+	return ret;
+}
+
+static errcode_t o2fsck_check_xattr_ibody(o2fsck_state *ost,
+					  struct ocfs2_dinode *di)
+{
+	errcode_t ret;
+	struct ocfs2_xattr_header *xh = NULL;
+	int changed = 0;
+
+	xh = (struct ocfs2_xattr_header *)
+		 ((void *)di + ost->ost_fs->fs_blocksize -
+		  di->i_xattr_inline_size);
+
+	ocfs2_swap_xattr_header(xh);
+	ocfs2_swap_xattr_entries_to_cpu(xh);
+
+	ret = check_xattr(ost, di, xh, &changed);
+
+	if (changed) {
+		ocfs2_swap_xattr_entries_from_cpu(xh);
+		ocfs2_swap_xattr_header(xh);
+		o2fsck_write_inode(ost, di->i_blkno, di);
+	}
+	return ret;
+}
+
+static errcode_t o2fsck_check_xattr_block(o2fsck_state *ost,
+					  struct ocfs2_dinode *di)
+{
+	errcode_t ret;
+	char *blk = NULL;
+	struct ocfs2_xattr_block *xb = NULL;
+	int changed = 0;
+
+	o2fsck_mark_cluster_allocated(ost,
+		ocfs2_blocks_to_clusters(ost->ost_fs, di->i_xattr_loc));
+
+	ret = ocfs2_malloc_block(ost->ost_fs->fs_io, &blk);
+	if (ret) {
+		com_err(whoami, ret, "while allocating room to read block "
+			"of xattr.");
+		return ret;
+	}
+
+	ret = ocfs2_read_xattr_block(ost->ost_fs, di->i_xattr_loc, blk);
+	if (ret) {
+		com_err(whoami, ret, "while reading externel block of xattr.");
+		return ret;
+	}
+
+	xb = (struct ocfs2_xattr_block *)blk;
+
+	if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
+		struct ocfs2_xattr_header *xh = &xb->xb_attrs.xb_header;
+
+		ret = check_xattr(ost, di, xh, &changed);
+	} else {
+		struct ocfs2_xattr_tree_root *xt = &xb->xb_attrs.xb_root;
+
+		ret = o2fsck_check_xattr_index_block(ost, di, xt, &changed);
+	}
+
+	if (changed)
+		ocfs2_write_xattr_block(ost->ost_fs, di->i_xattr_loc, blk);
+
+	if (blk)
+		ocfs2_free(&blk);
+
+	return ret;
+}
+
+/*
+ * o2fsck_check_xattr
+ *
+ * Check extended attribute in inode block or external block.
+ */
+errcode_t o2fsck_check_xattr(o2fsck_state *ost,
+			     struct ocfs2_dinode *di)
+{
+	errcode_t ret = 0;
+
+	if (!(di->i_dyn_features & OCFS2_HAS_XATTR_FL))
+		return 0;
+
+	if (di->i_dyn_features & OCFS2_HAS_XATTR_FL) {
+		ret = o2fsck_check_xattr_ibody(ost, di);
+		if (ret)
+			return ret;
+	}
+	if (di->i_xattr_loc)
+		ret = o2fsck_check_xattr_block(ost, di);
+
+	return ret;
+}
diff --git a/include/ocfs2-kernel/ocfs2_fs.h b/include/ocfs2-kernel/ocfs2_fs.h
index ade9ec1..ee44be8 100644
--- a/include/ocfs2-kernel/ocfs2_fs.h
+++ b/include/ocfs2-kernel/ocfs2_fs.h
@@ -728,6 +728,13 @@ struct ocfs2_group_desc
 /* Inline extended attribute size (in bytes) */
 #define OCFS2_MIN_XATTR_INLINE_SIZE     256
 
+#define OCFS2_XATTR_BUCKET_SIZE		4096
+
+#define OCFS2_XATTR_ROUND		3
+
+#define OCFS2_XATTR_SIZE(size)  (((size) + OCFS2_XATTR_ROUND) & \
+				~(OCFS2_XATTR_ROUND))
+
 struct ocfs2_xattr_entry {
 	__le32	xe_name_hash;
 	__le16	xe_name_offset;
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 1f81c47..6aadd46 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -291,6 +291,7 @@ errcode_t ocfs2_get_clusters(ocfs2_cached_inode *cinode,
 			     uint32_t *num_clusters,
 			     uint16_t *extent_flags);
 int ocfs2_find_leaf(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+		    struct ocfs2_extent_list *el,
 		    uint32_t cpos, char **leaf_buf);
 int ocfs2_search_extent_list(struct ocfs2_extent_list *el, uint32_t v_cluster);
 void ocfs2_swap_journal_superblock(journal_superblock_t *jsb);
@@ -942,5 +943,10 @@ errcode_t ocfs2_block_iterate_inode(ocfs2_filesys *fs,
 				    void *priv_data);
 
 uint32_t xattr_uuid_hash(unsigned char *uuid);
+void ocfs2_swap_xattr_entries_to_cpu(struct ocfs2_xattr_header *xh);
+void ocfs2_swap_xattr_entries_from_cpu(struct ocfs2_xattr_header *xh);
+void ocfs2_swap_xattr_header(struct ocfs2_xattr_header *xh);
+void ocfs2_swap_xattr_block_from_cpu(struct ocfs2_xattr_block *xb);
+void ocfs2_swap_xattr_block_to_cpu(struct ocfs2_xattr_block *xb);
 
 #endif  /* _FILESYS_H */
diff --git a/libocfs2/extend_file.c b/libocfs2/extend_file.c
index 1cb4a00..4cc7a94 100644
--- a/libocfs2/extend_file.c
+++ b/libocfs2/extend_file.c
@@ -997,16 +997,16 @@ static int ocfs2_find_path(ocfs2_filesys *fs, struct ocfs2_path *path,
  * This function doesn't handle non btree extent lists.
  */
 int ocfs2_find_leaf(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+		    struct ocfs2_extent_list *el,
 		    uint32_t cpos, char **leaf_buf)
 {
 	int ret;
 	char *buf = NULL;
 	struct ocfs2_path *path = NULL;
-	struct ocfs2_extent_list *el = &di->id2.i_list;
 
 	assert(el->l_tree_depth > 0);
 
-	path = ocfs2_new_inode_path(fs, di);
+	path = ocfs2_new_path(fs, (char *)di, el);
 	if (!path) {
 		ret = OCFS2_ET_NO_MEMORY;
 		goto out;
diff --git a/libocfs2/extent_map.c b/libocfs2/extent_map.c
index 7e5f8fe..dd081fc 100644
--- a/libocfs2/extent_map.c
+++ b/libocfs2/extent_map.c
@@ -147,7 +147,7 @@ errcode_t ocfs2_get_clusters(ocfs2_cached_inode *cinode,
 	el = &di->id2.i_list;
 
 	if (el->l_tree_depth) {
-		ret = ocfs2_find_leaf(fs, di, v_cluster, &eb_buf);
+		ret = ocfs2_find_leaf(fs, di, el, v_cluster, &eb_buf);
 		if (ret)
 			goto out;
 
diff --git a/libocfs2/ocfs2_err.et b/libocfs2/ocfs2_err.et
index 9b33a3b..88b3366 100644
--- a/libocfs2/ocfs2_err.et
+++ b/libocfs2/ocfs2_err.et
@@ -171,4 +171,7 @@ ec	OCFS2_ET_NO_BACKUP_SUPER,
 ec	OCFS2_ET_CANNOT_INLINE_DATA,
 	"Can't write the data inline"
 
+ec	OCFS2_ET_BAD_XATTR_BLOCK_MAGIC,
+	"Bad magic number in xattr block"
+
 	end
diff --git a/libocfs2/xattr.c b/libocfs2/xattr.c
index d198743..767b333 100644
--- a/libocfs2/xattr.c
+++ b/libocfs2/xattr.c
@@ -35,3 +35,113 @@ uint32_t xattr_uuid_hash(unsigned char *uuid)
 	return hash;
 }
 
+static void ocfs2_swap_xattr_tree_root(struct ocfs2_xattr_tree_root *xt)
+{
+	xt->xt_clusters		= bswap_16(xt->xt_clusters);
+	xt->xt_last_eb_blk	= bswap_16(xt->xt_last_eb_blk);
+}
+
+static void ocfs2_swap_xattr_value_root(struct ocfs2_xattr_value_root *xr)
+{
+	xr->xr_clusters		= bswap_16(xr->xr_clusters);
+	xr->xr_last_eb_blk	= bswap_16(xr->xr_last_eb_blk);
+}
+
+static void ocfs2_swap_xattr_block_header(struct ocfs2_xattr_block *xb)
+{
+	xb->xb_suballoc_slot	= bswap_16(xb->xb_suballoc_slot);
+	xb->xb_suballoc_bit	= bswap_16(xb->xb_suballoc_bit);
+	xb->xb_fs_generation	= bswap_32(xb->xb_fs_generation);
+	xb->xb_csum 		= bswap_32(xb->xb_csum);
+	xb->xb_flags		= bswap_16(xb->xb_flags);
+	xb->xb_blkno		= bswap_64(xb->xb_blkno);
+}
+
+void ocfs2_swap_xattr_entries_to_cpu(struct ocfs2_xattr_header *xh)
+{
+	uint16_t i;
+
+	if (cpu_is_little_endian)
+		return;
+
+	for (i = 0; i < xh->xh_count; i++) {
+		struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
+
+		xe->xe_name_offset	= bswap_16(xe->xe_name_offset);
+		xe->xe_value_size	= bswap_64(xe->xe_value_size);
+
+		if (!xe->xe_local) {
+			struct ocfs2_xattr_value_root *xr =
+				(struct ocfs2_xattr_value_root *)
+				((char *)xh + xe->xe_name_offset +
+				OCFS2_XATTR_SIZE(xe->xe_name_len));
+
+			ocfs2_swap_xattr_value_root(xr);
+			ocfs2_swap_extent_list_to_cpu(&xr->xr_list);
+		}
+	}
+}
+
+void ocfs2_swap_xattr_entries_from_cpu(struct ocfs2_xattr_header *xh)
+{
+	uint16_t i;
+
+	if (cpu_is_little_endian)
+		return;
+
+	for (i = 0; i < xh->xh_count; i++) {
+		struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
+
+		if (!xe->xe_local) {
+			struct ocfs2_xattr_value_root *xr =
+				(struct ocfs2_xattr_value_root *)
+				((char *)xh + xe->xe_name_offset +
+				OCFS2_XATTR_SIZE(xe->xe_name_len));
+
+			ocfs2_swap_xattr_value_root(xr);
+		}
+		xe->xe_name_offset	= bswap_16(xe->xe_name_offset);
+		xe->xe_value_size	= bswap_64(xe->xe_value_size);
+	}
+}
+
+void ocfs2_swap_xattr_header(struct ocfs2_xattr_header *xh)
+{
+	if (cpu_is_little_endian)
+		return;
+
+	xh->xh_count		= bswap_16(xh->xh_count);
+	xh->xh_reserved1	= bswap_16(xh->xh_reserved1);
+	xh->xh_csum		= bswap_32(xh->xh_csum);
+}
+
+void ocfs2_swap_xattr_block_from_cpu(struct ocfs2_xattr_block *xb)
+{
+	if (cpu_is_little_endian)
+		return;
+
+	if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
+		ocfs2_swap_xattr_entries_from_cpu(&xb->xb_attrs.xb_header);
+		ocfs2_swap_xattr_header(&xb->xb_attrs.xb_header);
+	} else {
+		ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
+	}
+
+	ocfs2_swap_xattr_block_header(xb);
+}
+
+void ocfs2_swap_xattr_block_to_cpu(struct ocfs2_xattr_block *xb)
+{
+	if (cpu_is_little_endian)
+		return;
+
+	ocfs2_swap_xattr_block_header(xb);
+	if (!(xb->xb_flags & OCFS2_XATTR_INDEXED)) {
+		ocfs2_swap_xattr_header(&xb->xb_attrs.xb_header);
+		ocfs2_swap_xattr_entries_to_cpu(&xb->xb_attrs.xb_header);
+	} else {
+		ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
+		ocfs2_swap_extent_list_to_cpu(&xb->xb_attrs.xb_root.xt_list);
+	}
+}
+
-- 
1.5.4.4




More information about the Ocfs2-tools-devel mailing list