From: Tao Ma <tao.ma@oracle.com>
To: ocfs2-devel@oss.oracle.com
Subject: [Ocfs2-devel] [PATCH 2/2] ocfs2-tools: Add extended attribute support in fsck.ocfs2
Date: Fri, 25 Jul 2008 15:52:36 +0800 [thread overview]
Message-ID: <48898644.9090307@oracle.com> (raw)
In-Reply-To: <1216969599-9280-2-git-send-email-tiger.yang@oracle.com>
Tiger Yang wrote:
> +#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));
> +}
I remember with 512, there is no xattr in inode.
> +
> +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_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--) {
no le16_to_cpu in tools. there are also some below, please remove them.
> + 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);
bucket size isn't block size. So you can't just read and handle the
first block for a bucket. the same for the write.
> + 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) {
you mean inline_xattr here?
> + 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_TOO_MANY_SLOTS,
> "Too many slots for slot map"
>
> +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)) {
you should handle xb_flags swap first.
> + 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);
> + }
> +}
> +
next prev parent reply other threads:[~2008-07-25 7:52 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-25 7:06 [Ocfs2-devel] [PATCH 1/2] ocfs2-tools: Add extended attribute support in mkfs.ocfs2 Tiger Yang
2008-07-25 7:06 ` [Ocfs2-devel] [PATCH 2/2] ocfs2-tools: Add extended attribute support in fsck.ocfs2 Tiger Yang
2008-07-25 7:52 ` Tao Ma [this message]
2008-07-25 8:56 ` Tiger Yang
2008-07-25 9:08 ` Tao Ma
2008-07-25 9:33 ` [Ocfs2-devel] [PATCH 1/2] ocfs2-tools: Add extended attribute support in mkfs.ocfs2 Joel Becker
2008-07-29 5:49 ` Tiger Yang
2008-07-29 7:09 ` Tao Ma
2008-07-29 22:23 ` Joel Becker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48898644.9090307@oracle.com \
--to=tao.ma@oracle.com \
--cc=ocfs2-devel@oss.oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.