[Ocfs2-tools-devel] [PATCH 06/11] ocfs2-tools: add more xattr APIs in lib
Tiger Yang
tiger.yang at oracle.com
Thu Feb 26 23:53:53 PST 2009
This patch mainly add read/write xattr bucket API in libocfs2.
Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
include/ocfs2-kernel/ocfs2_fs.h | 1 +
include/ocfs2/ocfs2.h | 9 +++
libocfs2/xattr.c | 139 +++++++++++++++++++++++++++++++++++++++
3 files changed, 149 insertions(+), 0 deletions(-)
diff --git a/include/ocfs2-kernel/ocfs2_fs.h b/include/ocfs2-kernel/ocfs2_fs.h
index 1eddbcd..24bf2c1 100644
--- a/include/ocfs2-kernel/ocfs2_fs.h
+++ b/include/ocfs2-kernel/ocfs2_fs.h
@@ -877,6 +877,7 @@ struct ocfs2_xattr_tree_root {
#define OCFS2_XATTR_SIZE(size) (((size) + OCFS2_XATTR_ROUND) & \
~(OCFS2_XATTR_ROUND))
+#define OCFS2_XATTR_INLINE_SIZE 80
#define OCFS2_XATTR_BUCKET_SIZE 4096
#define OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET (OCFS2_XATTR_BUCKET_SIZE \
/ OCFS2_MIN_BLOCKSIZE)
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index fdeec5e..4aa75ca 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -1086,6 +1086,7 @@ errcode_t ocfs2_block_iterate_inode(ocfs2_filesys *fs,
void *priv_data);
uint32_t xattr_uuid_hash(unsigned char *uuid);
+uint32_t xattr_name_hash(uint32_t uuid_hash, const char *name, int name_len);
int ocfs2_xattr_find_leaf(ocfs2_filesys *fs, struct ocfs2_xattr_block *xb,
uint32_t cpos, char **leaf_buf);
uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs);
@@ -1106,5 +1107,13 @@ errcode_t ocfs2_xattr_get_rec(ocfs2_filesys *fs,
uint64_t *p_blkno,
uint32_t *e_cpos,
uint32_t *num_clusters);
+uint16_t ocfs2_xattr_min_offset(struct ocfs2_xattr_header *xh, uint16_t size);
+uint16_t ocfs2_xattr_name_value_len(struct ocfs2_xattr_header *xh);
+errcode_t ocfs2_read_xattr_bucket(ocfs2_filesys *fs,
+ uint64_t blkno,
+ char *bucket_buf);
+errcode_t ocfs2_write_xattr_bucket(ocfs2_filesys *fs,
+ uint64_t blkno,
+ char *bucket_buf);
#endif /* _FILESYS_H */
diff --git a/libocfs2/xattr.c b/libocfs2/xattr.c
index 1059ef2..cabeb0b 100644
--- a/libocfs2/xattr.c
+++ b/libocfs2/xattr.c
@@ -20,6 +20,13 @@
#include "ocfs2/byteorder.h"
#include "ocfs2/ocfs2.h"
+struct ocfs2_xattr_def_value_root {
+ struct ocfs2_xattr_value_root xv;
+ struct ocfs2_extent_rec er;
+};
+
+#define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root))
+
uint32_t xattr_uuid_hash(unsigned char *uuid)
{
uint32_t i, hash = 0;
@@ -32,6 +39,24 @@ uint32_t xattr_uuid_hash(unsigned char *uuid)
return hash;
}
+uint32_t xattr_name_hash(uint32_t uuid_hash,
+ const char *name,
+ int name_len)
+{
+ /* Get hash value of uuid from super block */
+ uint32_t hash = uuid_hash;
+ int i;
+
+ /* hash extended attribute name */
+ for (i = 0; i < name_len; i++) {
+ hash = (hash << OCFS2_HASH_SHIFT) ^
+ (hash >> (8*sizeof(hash) - OCFS2_HASH_SHIFT)) ^
+ *name++;
+ }
+
+ return hash;
+}
+
uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs)
{
return fs->fs_clustersize / OCFS2_XATTR_BUCKET_SIZE;
@@ -290,3 +315,117 @@ out:
ocfs2_free(&eb_buf);
return ret;
}
+
+static uint16_t ocfs2_xattr_value_real_size(uint16_t name_len,
+ uint16_t value_len)
+{
+ uint16_t size = 0;
+
+ if (value_len <= OCFS2_XATTR_INLINE_SIZE)
+ size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(value_len);
+ else
+ size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
+
+ return size;
+}
+
+uint16_t ocfs2_xattr_min_offset(struct ocfs2_xattr_header *xh, uint16_t size)
+{
+ int i;
+ uint16_t min_offs = size;
+
+ for (i = 0 ; i < xh->xh_count; i++) {
+ struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
+ size_t offs = xe->xe_name_offset;
+
+ if (offs < min_offs)
+ min_offs = offs;
+ }
+ return min_offs;
+}
+
+uint16_t ocfs2_xattr_name_value_len(struct ocfs2_xattr_header *xh)
+{
+ int i;
+ uint16_t total_len = 0;
+
+ for (i = 0 ; i < xh->xh_count; i++) {
+ struct ocfs2_xattr_entry *xe = &xh->xh_entries[i];
+
+ total_len += ocfs2_xattr_value_real_size(xe->xe_name_len,
+ xe->xe_value_size);
+ }
+ return total_len;
+}
+
+errcode_t ocfs2_read_xattr_bucket(ocfs2_filesys *fs,
+ uint64_t blkno,
+ char *bucket_buf)
+{
+ errcode_t ret = 0;
+ char *bucket;
+ struct ocfs2_xattr_header *xh;
+ int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(fs);
+
+ ret = ocfs2_malloc_blocks(fs->fs_io, blk_per_bucket, &bucket);
+ if (ret)
+ return ret;
+
+ ret = io_read_block(fs->fs_io, blkno, blk_per_bucket, bucket);
+ if (ret)
+ goto out;
+
+ xh = (struct ocfs2_xattr_header *)bucket;
+ if (ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super))) {
+ ret = ocfs2_block_check_validate(bucket,
+ OCFS2_XATTR_BUCKET_SIZE,
+ &xh->xh_check);
+ if (ret)
+ goto out;
+ }
+
+ memcpy(bucket_buf, bucket, OCFS2_XATTR_BUCKET_SIZE);
+ xh = (struct ocfs2_xattr_header *)bucket_buf;
+ ocfs2_swap_xattrs_to_cpu(xh);
+out:
+ ocfs2_free(&bucket);
+ return ret;
+}
+
+errcode_t ocfs2_write_xattr_bucket(ocfs2_filesys *fs,
+ uint64_t blkno,
+ char *bucket_buf)
+{
+
+ errcode_t ret = 0;
+ char *bucket;
+ struct ocfs2_xattr_header *xh;
+ int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(fs);
+
+ 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_blocks(fs->fs_io, blk_per_bucket, &bucket);
+ if (ret)
+ return ret;
+
+ memcpy(bucket, bucket_buf, OCFS2_XATTR_BUCKET_SIZE);
+
+ xh = (struct ocfs2_xattr_header *)bucket;
+ ocfs2_swap_xattrs_from_cpu(xh);
+
+ if (ocfs2_meta_ecc(OCFS2_RAW_SB(fs->fs_super)))
+ ocfs2_block_check_compute(bucket, OCFS2_XATTR_BUCKET_SIZE,
+ &xh->xh_check);
+
+ ret = io_write_block(fs->fs_io, blkno, blk_per_bucket, bucket);
+ if (!ret)
+ fs->fs_flags |= OCFS2_FLAG_CHANGED;
+
+ ocfs2_free(&bucket);
+ return ret;
+}
--
1.5.4.1
More information about the Ocfs2-tools-devel
mailing list