[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 22:02:22 PDT 2008


Please ignore these two email. It was sent by mistake folder.

Sorry,
tiger

Tiger Yang wrote:
> 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);
> +	}
> +}
> +



More information about the Ocfs2-tools-devel mailing list