[Ocfs2-tools-devel] [PATCH 07/12] ocfs2-tools: add more xattr APIs in lib

Tiger Yang tiger.yang at oracle.com
Tue Mar 24 19:49:29 PDT 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           |   11 +++
 libocfs2/xattr.c                |  139 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 151 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 8144a90..4a1d876 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -1086,6 +1086,8 @@ errcode_t ocfs2_block_iterate_inode(ocfs2_filesys *fs,
 				    void *priv_data);
 
 uint32_t ocfs2_xattr_uuid_hash(unsigned char *uuid);
+uint32_t ocfs2_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 +1108,14 @@ 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_value_real_size(uint16_t name_len, uint16_t value_len);
+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 f28e068..bffdfd9 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 ocfs2_xattr_uuid_hash(unsigned char *uuid)
 {
 	uint32_t i, hash = 0;
@@ -32,6 +39,24 @@ uint32_t ocfs2_xattr_uuid_hash(unsigned char *uuid)
 	return hash;
 }
 
+uint32_t ocfs2_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;
@@ -299,3 +324,117 @@ out:
 		ocfs2_free(&eb_buf);
 	return ret;
 }
+
+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