ret = NULL;
} else {
- uint32_t block_size =
- ext4_sb_get_block_size(&xattr_ref->fs->sb);
+ int32_t block_size =
+ ext4_sb_get_block_size(&xattr_ref->fs->sb);
ret = (void *)((char *)xattr_ref->block.data +
to_le16(entry->e_value_offs));
if ((char *)ret + EXT4_XATTR_SIZE(to_le32(entry->e_value_size))
name,
name_len);
if (item) {
+ if (item == xattr_ref->iter_from)
+ xattr_ref->iter_from = RB_NEXT(ext4_xattr_tree,
+ &xattr_ref->root,
+ item);
+
RB_REMOVE(ext4_xattr_tree, &xattr_ref->root, item);
ext4_xattr_item_free(item);
xattr_ref->ea_size -= EXT4_XATTR_SIZE(item->data_size) +
ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref)
{
struct ext4_xattr_item *item, *save_item;
+ uint64_t xattr_block = ext4_inode_get_file_acl(xattr_ref->inode_ref->inode,
+ &xattr_ref->fs->sb);
RB_FOREACH_SAFE(item,
ext4_xattr_tree,
&xattr_ref->root,
RB_REMOVE(ext4_xattr_tree, &xattr_ref->root, item);
ext4_xattr_item_free(item);
}
- xattr_ref->ea_size = sizeof(struct ext4_xattr_header) +
- sizeof(struct ext4_xattr_ibody_header);
+ xattr_ref->ea_size = 0;
+ if (xattr_block)
+ xattr_ref->ea_size += sizeof(struct ext4_xattr_header);
+
+ if (ext4_xattr_inode_space(xattr_ref) >
+ sizeof(struct ext4_xattr_ibody_header))
+ xattr_ref->ea_size += sizeof(struct ext4_xattr_ibody_header);
}
{
int ret = EOK;
- uint64_t xattr_block;
+ uint64_t xattr_block = 0;
xattr_block = ext4_inode_get_file_acl(xattr_ref->inode_ref->inode,
&xattr_ref->fs->sb);
if (!xattr_block) {
goto Finish;
ret = ext4_block_get(xattr_ref->fs->bdev,
- &xattr_ref->inode_ref->block,
+ &xattr_ref->block,
xattr_block);
if (ret != EOK) {
ext4_balloc_free_block(xattr_ref->inode_ref,
xattr_ref->inode_ref->dirty = true;
xattr_ref->block_loaded = true;
xattr_ref->ea_size += sizeof(struct ext4_xattr_header);
-}
+ }
Finish:
return ret;
xattr_ref->inode_ref->dirty = true;
xattr_ref->block_loaded = false;
xattr_ref->ea_size -= sizeof(struct ext4_xattr_header);
+}
+
+static void
+ext4_xattr_set_block_header(struct ext4_xattr_ref *xattr_ref)
+{
+ struct ext4_xattr_header *block_header = NULL;
+ block_header = EXT4_XATTR_BHDR(&xattr_ref->block);
+ memset(block_header, 0, sizeof(struct ext4_xattr_header));
+ block_header->h_magic = EXT4_XATTR_MAGIC;
+ block_header->h_refcount = to_le32(1);
+ block_header->h_blocks = to_le32(1);
+}
+
+static void
+ext4_xattr_set_inode_entry(struct ext4_xattr_item *item,
+ struct ext4_xattr_ibody_header *ibody_header,
+ struct ext4_xattr_entry *entry,
+ void *ibody_data_ptr)
+{
+ entry->e_name_len = to_le32(item->name_len);
+ entry->e_name_index = item->name_index;
+ entry->e_value_offs =
+ (char *)ibody_data_ptr -
+ (char *)EXT4_XATTR_IFIRST(ibody_header);
+ entry->e_value_block = 0;
+ entry->e_value_size = item->data_size;
+}
+
+static void
+ext4_xattr_set_block_entry(struct ext4_xattr_item *item,
+ struct ext4_xattr_header *block_header,
+ struct ext4_xattr_entry *block_entry,
+ void *block_data_ptr)
+{
+ block_entry->e_name_len = to_le32(item->name_len);
+ block_entry->e_name_index = item->name_index;
+ block_entry->e_value_offs =
+ (char *)block_data_ptr - (char *)block_header;
+ block_entry->e_value_block = 0;
+ block_entry->e_value_size = item->data_size;
}
static int
void *ibody_data, *block_data;
struct ext4_xattr_item *item, *save_item;
size_t inode_size_rem, block_size_rem;
- struct ext4_xattr_header *header = NULL;
struct ext4_xattr_ibody_header *ibody_header = NULL;
+ struct ext4_xattr_header *block_header = NULL;
struct ext4_xattr_entry *entry = NULL;
struct ext4_xattr_entry *block_entry = NULL;
if (inode_size_rem > sizeof(struct ext4_xattr_ibody_header)) {
memset(ibody_header, 0, inode_size_rem);
ibody_header->h_magic = EXT4_XATTR_MAGIC;
- xattr_ref->inode_ref->dirty = true;
ibody_data = (char *)ibody_header + inode_size_rem;
inode_size_rem -= sizeof(struct ext4_xattr_ibody_header);
+
+ xattr_ref->inode_ref->dirty = true;
}
/* If we need an extra block to hold the EA entries*/
if (xattr_ref->ea_size > inode_size_rem) {
goto Finish;
}
- header = EXT4_XATTR_BHDR(&xattr_ref->block);
+ block_header = EXT4_XATTR_BHDR(&xattr_ref->block);
block_entry = EXT4_XATTR_BFIRST(&xattr_ref->block);
- memset(header, 0, sizeof(struct ext4_xattr_header));
- header->h_magic = EXT4_XATTR_MAGIC;
- header->h_refcount = to_le32(1);
- header->h_blocks = to_le32(1);
- block_data = (char *)header + block_size_rem;
+ ext4_xattr_set_block_header(xattr_ref);
+ block_data = (char *)block_header + block_size_rem;
block_size_rem -= sizeof(struct ext4_xattr_header);
+
xattr_ref->block.dirty = true;
} else {
/* We don't need an extra block.*/
if (xattr_ref->block_loaded) {
- header = EXT4_XATTR_BHDR(&xattr_ref->block);
- header->h_refcount =
- to_le32(to_le32(header->h_refcount) - 1);
- if (!header->h_refcount) {
+ block_header = EXT4_XATTR_BHDR(&xattr_ref->block);
+ block_header->h_refcount =
+ to_le32(to_le32(block_header->h_refcount) - 1);
+ if (!block_header->h_refcount) {
ext4_xattr_try_free_block(xattr_ref);
- header = NULL;
+ block_header = NULL;
} else {
- xattr_ref->block.dirty = true;
block_entry = EXT4_XATTR_BFIRST(&xattr_ref->block);
- block_data = (char *)header + block_size_rem;
+ block_data = (char *)block_header + block_size_rem;
block_size_rem -= sizeof(struct ext4_xattr_header);
+ ext4_inode_set_file_acl(xattr_ref->inode_ref->inode,
+ &xattr_ref->fs->sb,
+ 0);
+
+ xattr_ref->inode_ref->dirty = true;
+ xattr_ref->block.dirty = true;
}
}
}
if (EXT4_XATTR_SIZE(item->data_size) +
EXT4_XATTR_LEN(item->name_len) <=
inode_size_rem) {
- ibody_data = (char *)ibody_data - EXT4_XATTR_SIZE(item->data_size);
- entry->e_name_len = to_le32(item->name_len);
- entry->e_name_index = item->name_index;
- entry->e_value_offs =
- (char *)ibody_data -
- (char *)EXT4_XATTR_IFIRST(ibody_header);
- entry->e_value_block = 0;
- entry->e_value_size = item->data_size;
- memcpy(EXT4_XATTR_NAME(entry), item->name, item->name_len);
+ ibody_data = (char *)ibody_data -
+ EXT4_XATTR_SIZE(item->data_size);
+ ext4_xattr_set_inode_entry(item,
+ ibody_header,
+ entry,
+ ibody_data);
+ memcpy(EXT4_XATTR_NAME(entry),
+ item->name, item->name_len);
memcpy(ibody_data, item->data, item->data_size);
entry = EXT4_XATTR_NEXT(entry);
inode_size_rem -=
EXT4_XATTR_SIZE(item->data_size) +
EXT4_XATTR_LEN(item->name_len);
+
+ xattr_ref->inode_ref->dirty = true;
continue;
}
if (EXT4_XATTR_SIZE(item->data_size) +
ret = ENOSPC;
goto Finish;
}
- block_data = (char *)block_data - EXT4_XATTR_SIZE(item->data_size);
- block_entry->e_name_len = to_le32(item->name_len);
- block_entry->e_name_index = item->name_index;
- block_entry->e_value_offs =
- (char *)block_data - (char *)header;
- block_entry->e_value_block = 0;
- block_entry->e_value_size = item->data_size;
- memcpy(EXT4_XATTR_NAME(block_entry), item->name, item->name_len);
- memcpy(block_data, item->data, item->data_size);
+ block_data = (char *)block_data -
+ EXT4_XATTR_SIZE(item->data_size);
+ ext4_xattr_set_block_entry(item,
+ block_header,
+ block_entry,
+ block_data);
+ memcpy(EXT4_XATTR_NAME(block_entry),
+ item->name, item->name_len);
+ memcpy(block_data,
+ item->data, item->data_size);
block_entry = EXT4_XATTR_NEXT(block_entry);
block_size_rem -=
EXT4_XATTR_SIZE(item->data_size) +
EXT4_XATTR_LEN(item->name_len);
+
block_modified = true;
}
xattr_ref->dirty = false;
if (block_modified) {
- ext4_xattr_rehash(header,
+ ext4_xattr_rehash(block_header,
EXT4_XATTR_BFIRST(&xattr_ref->block));
+ xattr_ref->block.dirty = true;
}
}
return ret;
}
+void
+ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref,
+ int (iter)(struct ext4_xattr_ref *ref,
+ struct ext4_xattr_item *item))
+{
+ struct ext4_xattr_item *item;
+ if (!ref->iter_from)
+ ref->iter_from = RB_MIN(ext4_xattr_tree, &ref->root);
+
+ RB_FOREACH_FROM(item,
+ ext4_xattr_tree,
+ ref->iter_from) {
+ int ret = EXT4_XATTR_ITERATE_CONT;
+ if (iter)
+ iter(ref, item);
+
+ if (ret != EXT4_XATTR_ITERATE_CONT) {
+ if (ret == EXT4_XATTR_ITERATE_STOP)
+ ref->iter_from = NULL;
+
+ break;
+ }
+ }
+}
+
+static void
+ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref)
+{
+ ref->iter_from = NULL;
+}
int ext4_fs_set_xattr(struct ext4_xattr_ref *ref,
uint8_t name_index,
&fs->sb);
RB_INIT(&ref->root);
ref->ea_size = 0;
+ ref->iter_from = NULL;
if (xattr_block) {
rc = ext4_block_get(fs->bdev,
- &inode_ref->block, xattr_block);
+ &ref->block, xattr_block);
if (rc != EOK)
return EIO;
void ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref)
{
+ ext4_xattr_write_to_disk(ref);
if (ref->block_loaded) {
ext4_block_set(ref->fs->bdev, &ref->block);
ref->block_loaded = false;
}
- ext4_xattr_write_to_disk(ref);
ext4_xattr_purge_items(ref);
ref->inode_ref = NULL;
ref->fs = NULL;