--- /dev/null
+From: Tao Ma <tao.ma@oracle.com>
+Subject: [PATCH 05/16] Add the basic xattr disk layout in ocfs2_fs.h
+Patch-mainline: 2.6.28?
+References: FATE302067
+
+Ocfs2 uses a very flexible structure for storing extended attributes on
+disk. Small amount of attributes are stored directly in the inode block - up
+to 256 bytes worth. If that fills up, attributes are also stored in an
+external block, linked to from the inode block. That block can in turn
+expand to a btree, capable of storing large numbers of attributes.
+
+Individual attribute values are stored inline if they're small enough
+(currently about 80 bytes, this can be changed though), and otherwise are
+expanded to a btree. The theoretical limit to the size of an individual
+attribute is about the same as an inode, though the kernel's upper bound on
+the size of an attributes data is far smaller.
+
+Signed-off-by: Tao Ma <tao.ma@oracle.com>
+Signed-off-by: Mark Fasheh <mfasheh@suse.com>
+---
+ fs/ocfs2/ocfs2_fs.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 118 insertions(+), 0 deletions(-)
+
+diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
+index 4f61985..1b46505 100644
+--- a/fs/ocfs2/ocfs2_fs.h
++++ b/fs/ocfs2/ocfs2_fs.h
+@@ -64,6 +64,7 @@
+ #define OCFS2_INODE_SIGNATURE "INODE01"
+ #define OCFS2_EXTENT_BLOCK_SIGNATURE "EXBLK01"
+ #define OCFS2_GROUP_DESC_SIGNATURE "GROUP01"
++#define OCFS2_XATTR_BLOCK_SIGNATURE "XATTR01"
+
+ /* Compatibility flags */
+ #define OCFS2_HAS_COMPAT_FEATURE(sb,mask) \
+@@ -715,6 +716,123 @@ struct ocfs2_group_desc
+ /*40*/ __u8 bg_bitmap[0];
+ };
+
++/*
++ * On disk extended attribute structure for OCFS2.
++ */
++
++/*
++ * ocfs2_xattr_entry indicates one extend attribute.
++ *
++ * Note that it can be stored in inode, one block or one xattr bucket.
++ */
++struct ocfs2_xattr_entry {
++ __le32 xe_name_hash; /* hash value of xattr prefix+suffix. */
++ __le16 xe_name_offset; /* byte offset from the 1st etnry in the local
++ local xattr storage(inode, xattr block or
++ xattr bucket). */
++ __u8 xe_name_len; /* xattr name len, does't include prefix. */
++ __u8 xe_type; /* the low 7 bits indicates the name prefix's
++ * type and the highest 1 bits indicate whether
++ * the EA is stored in the local storage. */
++ __le64 xe_value_size; /* real xattr value length. */
++};
++
++/*
++ * On disk structure for xattr header.
++ *
++ * One ocfs2_xattr_header describes how many ocfs2_xattr_entry records in
++ * the local xattr storage.
++ */
++struct ocfs2_xattr_header {
++ __le16 xh_count; /* contains the count of how
++ many records are in the
++ local xattr storage. */
++ __le16 xh_reserved1;
++ __le32 xh_reserved2;
++ __le64 xh_csum;
++ struct ocfs2_xattr_entry xh_entries[0]; /* xattr entry list. */
++};
++
++/*
++ * On disk structure for xattr value root.
++ *
++ * It is used when one extended attribute's size is larger, and we will save it
++ * in an outside cluster. It will stored in a b-tree like file content.
++ */
++struct ocfs2_xattr_value_root {
++/*00*/ __le32 xr_clusters; /* clusters covered by xattr value. */
++ __le32 xr_reserved0;
++ __le64 xr_last_eb_blk; /* Pointer to last extent block */
++/*10*/ struct ocfs2_extent_list xr_list; /* Extent record list */
++};
++
++/*
++ * On disk structure for xattr tree root.
++ *
++ * It is used when there are too many extended attributes for one file. These
++ * attributes will be organized and stored in an indexed-btree.
++ */
++struct ocfs2_xattr_tree_root {
++/*00*/ __le32 xt_clusters; /* clusters covered by xattr. */
++ __le32 xt_reserved0;
++ __le64 xt_last_eb_blk; /* Pointer to last extent block */
++/*10*/ struct ocfs2_extent_list xt_list; /* Extent record list */
++};
++
++#define OCFS2_XATTR_INDEXED 0x1
++
++/*
++ * On disk structure for xattr block.
++ */
++struct ocfs2_xattr_block {
++/*00*/ __u8 xb_signature[8]; /* Signature for verification */
++ __le16 xb_suballoc_slot; /* Slot suballocator this
++ block belongs to. */
++ __le16 xb_suballoc_bit; /* Bit offset in suballocator
++ block group */
++ __le32 xb_fs_generation; /* Must match super block */
++/*10*/ __le64 xb_blkno; /* Offset on disk, in blocks */
++ __le64 xb_csum;
++/*20*/ __le16 xb_flags; /* Indicates whether this block contains
++ real xattr or a xattr tree. */
++ __le16 xb_reserved0;
++ __le32 xb_reserved1;
++ __le64 xb_reserved2;
++/*30*/ union {
++ struct ocfs2_xattr_header xb_header; /* xattr header if this
++ block contains xattr */
++ struct ocfs2_xattr_tree_root xb_root;/* xattr tree root if this
++ block cotains xattr
++ tree. */
++ } xb_attrs;
++};
++
++#define OCFS2_XATTR_ENTRY_LOCAL 0x80
++#define OCFS2_XATTR_TYPE_MASK 0x7F
++static inline void ocfs2_xattr_set_local(struct ocfs2_xattr_entry *xe,
++ int local)
++{
++ if (local)
++ xe->xe_type |= OCFS2_XATTR_ENTRY_LOCAL;
++ else
++ xe->xe_type &= ~OCFS2_XATTR_ENTRY_LOCAL;
++}
++
++static inline int ocfs2_xattr_is_local(struct ocfs2_xattr_entry *xe)
++{
++ return xe->xe_type & OCFS2_XATTR_ENTRY_LOCAL;
++}
++
++static inline void ocfs2_xattr_set_type(struct ocfs2_xattr_entry *xe, int type)
++{
++ xe->xe_type |= type & OCFS2_XATTR_TYPE_MASK;
++}
++
++static inline int ocfs2_xattr_get_type(struct ocfs2_xattr_entry *xe)
++{
++ return xe->xe_type & OCFS2_XATTR_TYPE_MASK;
++}
++
+ #ifdef __KERNEL__
+ static inline int ocfs2_fast_symlink_chars(struct super_block *sb)
+ {
+--
+1.5.4.5
+