summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/xattr.c95
1 files changed, 60 insertions, 35 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 092a12318986..8f522f2f84a5 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -137,14 +137,14 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
static int ocfs2_delete_xattr_index_block(struct inode *inode,
struct buffer_head *xb_bh);
-static inline struct xattr_handler *ocfs2_xattr_handler(int name_index)
+static inline const char *ocfs2_xattr_prefix(int name_index)
{
struct xattr_handler *handler = NULL;
if (name_index > 0 && name_index < OCFS2_XATTR_MAX)
handler = ocfs2_xattr_handler_map[name_index];
- return handler;
+ return handler ? handler->prefix : NULL;
}
static u32 ocfs2_xattr_name_hash(struct inode *inode,
@@ -452,33 +452,56 @@ static int ocfs2_xattr_value_truncate(struct inode *inode,
return ret;
}
+static int ocfs2_xattr_list_entry(char *buffer, size_t size,
+ size_t *result, const char *prefix,
+ const char *name, int name_len)
+{
+ char *p = buffer + *result;
+ int prefix_len = strlen(prefix);
+ int total_len = prefix_len + name_len + 1;
+
+ *result += total_len;
+
+ /* we are just looking for how big our buffer needs to be */
+ if (!size)
+ return 0;
+
+ if (*result > size)
+ return -ERANGE;
+
+ memcpy(p, prefix, prefix_len);
+ memcpy(p + prefix_len, name, name_len);
+ p[prefix_len + name_len] = '\0';
+
+ return 0;
+}
+
static int ocfs2_xattr_list_entries(struct inode *inode,
struct ocfs2_xattr_header *header,
char *buffer, size_t buffer_size)
{
- size_t rest = buffer_size;
- int i;
+ size_t result = 0;
+ int i, type, ret;
+ const char *prefix, *name;
for (i = 0 ; i < le16_to_cpu(header->xh_count); i++) {
struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
- struct xattr_handler *handler =
- ocfs2_xattr_handler(ocfs2_xattr_get_type(entry));
-
- if (handler) {
- size_t size = handler->list(inode, buffer, rest,
- ((char *)header +
- le16_to_cpu(entry->xe_name_offset)),
- entry->xe_name_len);
- if (buffer) {
- if (size > rest)
- return -ERANGE;
- buffer += size;
- }
- rest -= size;
+ type = ocfs2_xattr_get_type(entry);
+ prefix = ocfs2_xattr_prefix(type);
+
+ if (prefix) {
+ name = (const char *)header +
+ le16_to_cpu(entry->xe_name_offset);
+
+ ret = ocfs2_xattr_list_entry(buffer, buffer_size,
+ &result, prefix, name,
+ entry->xe_name_len);
+ if (ret)
+ return ret;
}
}
- return buffer_size - rest;
+ return result;
}
static int ocfs2_xattr_ibody_list(struct inode *inode,
@@ -2456,6 +2479,7 @@ out:
struct ocfs2_xattr_tree_list {
char *buffer;
size_t buffer_size;
+ size_t result;
};
static int ocfs2_xattr_bucket_get_name_value(struct inode *inode,
@@ -2481,17 +2505,17 @@ static int ocfs2_list_xattr_bucket(struct inode *inode,
struct ocfs2_xattr_bucket *bucket,
void *para)
{
- int ret = 0;
+ int ret = 0, type;
struct ocfs2_xattr_tree_list *xl = (struct ocfs2_xattr_tree_list *)para;
- size_t size;
int i, block_off, new_offset;
+ const char *prefix, *name;
for (i = 0 ; i < le16_to_cpu(bucket->xh->xh_count); i++) {
struct ocfs2_xattr_entry *entry = &bucket->xh->xh_entries[i];
- struct xattr_handler *handler =
- ocfs2_xattr_handler(ocfs2_xattr_get_type(entry));
+ type = ocfs2_xattr_get_type(entry);
+ prefix = ocfs2_xattr_prefix(type);
- if (handler) {
+ if (prefix) {
ret = ocfs2_xattr_bucket_get_name_value(inode,
bucket->xh,
i,
@@ -2499,16 +2523,16 @@ static int ocfs2_list_xattr_bucket(struct inode *inode,
&new_offset);
if (ret)
break;
- size = handler->list(inode, xl->buffer, xl->buffer_size,
- bucket->bhs[block_off]->b_data +
- new_offset,
- entry->xe_name_len);
- if (xl->buffer) {
- if (size > xl->buffer_size)
- return -ERANGE;
- xl->buffer += size;
- }
- xl->buffer_size -= size;
+
+ name = (const char *)bucket->bhs[block_off]->b_data +
+ new_offset;
+ ret = ocfs2_xattr_list_entry(xl->buffer,
+ xl->buffer_size,
+ &xl->result,
+ prefix, name,
+ entry->xe_name_len);
+ if (ret)
+ break;
}
}
@@ -2527,6 +2551,7 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
struct ocfs2_xattr_tree_list xl = {
.buffer = buffer,
.buffer_size = buffer_size,
+ .result = 0,
};
if (le16_to_cpu(el->l_next_free_rec) == 0)
@@ -2554,7 +2579,7 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
name_hash = e_cpos - 1;
}
- ret = buffer_size - xl.buffer_size;
+ ret = xl.result;
out:
return ret;
}