[Ocfs2-tools-devel] [PATCH 5/9] ocfs2-tools: add xattr support in lib

Tiger Yang tiger.yang at oracle.com
Sat Jan 24 00:03:30 PST 2009


This patch add xattr APIs in libocfs2.
Such as, read/write xattr block, swap xattr structure from/to cpu,
get xattr record, etc.

Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
 include/ocfs2/ocfs2.h  |   20 ++++
 libocfs2/extend_file.c |   38 +++++++
 libocfs2/ocfs2_err.et  |    4 +-
 libocfs2/xattr.c       |  267 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 328 insertions(+), 1 deletions(-)

diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 7b7f91d..fdeec5e 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -1086,5 +1086,25 @@ errcode_t ocfs2_block_iterate_inode(ocfs2_filesys *fs,
 				    void *priv_data);
 
 uint32_t xattr_uuid_hash(unsigned char *uuid);
+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);
+uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs);
+void ocfs2_swap_xattrs_to_cpu(struct ocfs2_xattr_header *xh);
+void ocfs2_swap_xattrs_from_cpu(struct ocfs2_xattr_header *xh);
+void ocfs2_swap_xattr_block_to_cpu(struct ocfs2_xattr_block *xb);
+void ocfs2_swap_xattr_block_from_cpu(struct ocfs2_xattr_block *xb);
+errcode_t ocfs2_read_xattr_block(ocfs2_filesys *fs,
+				 uint64_t blkno,
+				 char *xb_buf);
+errcode_t ocfs2_write_xattr_block(ocfs2_filesys *fs,
+				  uint64_t blkno,
+				  char *xb_buf);
+errcode_t ocfs2_xattr_get_rec(ocfs2_filesys *fs,
+			      struct ocfs2_xattr_block *xb,
+			      uint32_t name_hash,
+			      uint64_t *p_blkno,
+			      uint32_t *e_cpos,
+			      uint32_t *num_clusters);
 
 #endif  /* _FILESYS_H */
diff --git a/libocfs2/extend_file.c b/libocfs2/extend_file.c
index 73e4033..a27b478 100644
--- a/libocfs2/extend_file.c
+++ b/libocfs2/extend_file.c
@@ -1027,6 +1027,44 @@ out:
 	return ret;
 }
 
+int ocfs2_xattr_find_leaf(ocfs2_filesys *fs, struct ocfs2_xattr_block *xb,
+			  uint32_t cpos, char **leaf_buf)
+{
+	int ret;
+	char *buf = NULL;
+	struct ocfs2_path *path = NULL;
+	struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
+
+	assert(el->l_tree_depth > 0);
+
+
+	ret = ocfs2_malloc0(sizeof(*path), &path);
+
+	if (!path) {
+		ret = OCFS2_ET_NO_MEMORY;
+		goto out;
+	} else {
+		path->p_tree_depth = el->l_tree_depth;
+		path->p_node[0].blkno = xb->xb_blkno;
+		path->p_node[0].buf = (char *)xb;
+		path->p_node[0].el = el;
+	}
+
+	ret = ocfs2_find_path(fs, path, cpos);
+	if (ret)
+		goto out;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret)
+		goto out;
+
+	memcpy(buf, path_leaf_buf(path), fs->fs_blocksize);
+	*leaf_buf = buf;
+out:
+	ocfs2_free_path(path);
+	return ret;
+}
+
 /*
  * Adjust the adjacent records (left_rec, right_rec) involved in a rotation.
  *
diff --git a/libocfs2/ocfs2_err.et b/libocfs2/ocfs2_err.et
index b169ec7..1d43b21 100644
--- a/libocfs2/ocfs2_err.et
+++ b/libocfs2/ocfs2_err.et
@@ -171,10 +171,12 @@ ec	OCFS2_ET_NO_BACKUP_SUPER,
 ec      OCFS2_ET_TOO_MANY_SLOTS,
         "Too many slots for slot map"
 
-
 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"
+
 ec	OCFS2_ET_UNKNOWN_FEATURE,
 	"Unknown feature"
 
diff --git a/libocfs2/xattr.c b/libocfs2/xattr.c
index 287ce0e..921a093 100644
--- a/libocfs2/xattr.c
+++ b/libocfs2/xattr.c
@@ -32,3 +32,270 @@ uint32_t xattr_uuid_hash(unsigned char *uuid)
 	return hash;
 }
 
+uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs)
+{
+	return fs->fs_clustersize / OCFS2_XATTR_BUCKET_SIZE;
+}
+
+uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs)
+{
+	return OCFS2_XATTR_BUCKET_SIZE / fs->fs_blocksize;
+}
+
+static void ocfs2_swap_xattr_entry(struct ocfs2_xattr_entry *xe)
+{
+	xe->xe_name_hash	= bswap_32(xe->xe_name_hash);
+	xe->xe_name_offset	= bswap_16(xe->xe_name_offset);
+	xe->xe_value_size	= bswap_64(xe->xe_value_size);
+}
+
+static void ocfs2_swap_xattr_tree_root(struct ocfs2_xattr_tree_root *xt)
+{
+	xt->xt_clusters		= bswap_32(xt->xt_clusters);
+	xt->xt_last_eb_blk	= bswap_64(xt->xt_last_eb_blk);
+}
+
+static void ocfs2_swap_xattr_value_root(struct ocfs2_xattr_value_root *xr)
+{
+	xr->xr_clusters		= bswap_32(xr->xr_clusters);
+	xr->xr_last_eb_blk	= bswap_64(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_blkno		= bswap_64(xb->xb_blkno);
+	xb->xb_flags		= bswap_16(xb->xb_flags);
+}
+
+static 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_free_start	= bswap_16(xh->xh_free_start);
+	xh->xh_name_value_len	= bswap_16(xh->xh_name_value_len);
+	xh->xh_num_buckets	= bswap_16(xh->xh_num_buckets);
+}
+
+static 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];
+
+		ocfs2_swap_xattr_entry(xe);
+
+		if (!ocfs2_xattr_is_local(xe)) {
+			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);
+		}
+	}
+}
+
+static 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 (!ocfs2_xattr_is_local(xe)) {
+			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_extent_list_from_cpu(&xr->xr_list);
+			ocfs2_swap_xattr_value_root(xr);
+		}
+		ocfs2_swap_xattr_entry(xe);
+	}
+}
+
+void ocfs2_swap_xattrs_to_cpu(struct ocfs2_xattr_header *xh)
+{
+	ocfs2_swap_xattr_header(xh);
+	ocfs2_swap_xattr_entries_to_cpu(xh);
+}
+
+void ocfs2_swap_xattrs_from_cpu(struct ocfs2_xattr_header *xh)
+{
+	ocfs2_swap_xattr_entries_from_cpu(xh);
+	ocfs2_swap_xattr_header(xh);
+}
+
+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);
+	}
+}
+
+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_extent_list_from_cpu(&xb->xb_attrs.xb_root.xt_list);
+		ocfs2_swap_xattr_tree_root(&xb->xb_attrs.xb_root);
+	}
+
+	ocfs2_swap_xattr_block_header(xb);
+}
+
+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;
+}
+
+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;
+}
+
+errcode_t ocfs2_xattr_get_rec(ocfs2_filesys *fs,
+			      struct ocfs2_xattr_block *xb,
+			      uint32_t name_hash,
+			      uint64_t *p_blkno,
+			      uint32_t *e_cpos,
+			      uint32_t *num_clusters)
+{
+	int i;
+	errcode_t ret = 0;
+	char *eb_buf = NULL;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_rec *rec = NULL;
+	struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
+	uint64_t e_blkno = 0;
+
+	if (el->l_tree_depth) {
+		ret = ocfs2_xattr_find_leaf(fs, xb, name_hash, &eb_buf);
+		if (ret)
+			goto out;
+
+		eb = (struct ocfs2_extent_block *) eb_buf;
+		el = &eb->h_list;
+
+		if (el->l_tree_depth) {
+			ret = OCFS2_ET_INVALID_ARGUMENT;
+			goto out;
+		}
+	}
+
+	for (i = el->l_next_free_rec - 1; i >= 0; i--) {
+		rec = &el->l_recs[i];
+
+		if (rec->e_cpos <= name_hash) {
+			e_blkno = rec->e_blkno;
+			break;
+		}
+	}
+
+	if (!e_blkno) {
+		ret = OCFS2_ET_INVALID_ARGUMENT;
+		goto out;
+	}
+
+	*p_blkno = rec->e_blkno;
+	*num_clusters = rec->e_leaf_clusters;
+	if (e_cpos)
+		*e_cpos = rec->e_cpos;
+out:
+	if (eb_buf)
+		ocfs2_free(&eb_buf);
+	return ret;
+}
-- 
1.5.4.4




More information about the Ocfs2-tools-devel mailing list