[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