[Ocfs2-tools-devel] [PATCH 2/3] ocfs2-tools: Add extended attribute support in libocfs2
Tiger Yang
tiger.yang at oracle.com
Mon Aug 25 22:03:15 PDT 2008
This patch add some APIs for xattr operation in libocfs2.
Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
include/ocfs2/ocfs2.h | 22 ++++
libocfs2/extend_file.c | 4 +-
libocfs2/extent_map.c | 2 +-
libocfs2/feature_string.c | 4 +
libocfs2/ocfs2_err.et | 4 +-
libocfs2/xattr.c | 261 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 293 insertions(+), 4 deletions(-)
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 556f4ad..9dd8ed7 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -278,6 +278,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);
@@ -1034,5 +1035,26 @@ errcode_t ocfs2_block_iterate_inode(ocfs2_filesys *fs,
void *priv_data);
uint32_t xattr_uuid_hash(unsigned char *uuid);
+int ocfs2_extent_recs_per_xattr_block(int blocksize);
+uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs);
+uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs);
+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);
+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_dinode *di,
+ uint32_t name_hash,
+ uint64_t *p_blkno,
+ uint32_t *e_cpos,
+ uint32_t *num_clusters,
+ struct ocfs2_extent_list *el);
#endif /* _FILESYS_H */
diff --git a/libocfs2/extend_file.c b/libocfs2/extend_file.c
index 73e4033..217ea51 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/feature_string.c b/libocfs2/feature_string.c
index 369203e..d48dc84 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -171,6 +171,10 @@ static struct feature_name ocfs2_feature_names[] = {
.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_INLINE_DATA, 0},
},
{
+ .fn_name = "Xattr",
+ .fn_flag = {0, OCFS2_FEATURE_INCOMPAT_XATTR, 0},
+ },
+ {
.fn_name = NULL,
},
};
diff --git a/libocfs2/ocfs2_err.et b/libocfs2/ocfs2_err.et
index e278876..cbfa9d4 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 d198743..d65e013 100644
--- a/libocfs2/xattr.c
+++ b/libocfs2/xattr.c
@@ -23,6 +23,26 @@
#include "ocfs2/byteorder.h"
#include "ocfs2/ocfs2.h"
+int ocfs2_extent_recs_per_xattr_block(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);
+}
+
+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;
+}
+
uint32_t xattr_uuid_hash(unsigned char *uuid)
{
uint32_t i, hash = 0;
@@ -35,3 +55,244 @@ 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_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_csum = bswap_64(xb->xb_csum);
+ xb->xb_flags = bswap_16(xb->xb_flags);
+}
+
+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 (!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);
+ }
+ }
+}
+
+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_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_offset = bswap_16(xh->xh_offset);
+ xh->xh_name_value_len = bswap_16(xh->xh_name_value_len);
+ xh->xh_num_buckets = bswap_16(xh->xh_num_buckets);
+ xh->xh_csum = bswap_64(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)) {
+ 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);
+ }
+}
+
+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_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(fs, di, el, 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 = -1;
+ 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 = -1;
+ 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.1
More information about the Ocfs2-tools-devel
mailing list