static struct ext4_xattr_item *
ext4_xattr_insert_item(struct ext4_xattr_ref *xattr_ref, uint8_t name_index,
const char *name, size_t name_len, const void *data,
- size_t data_size)
+ size_t data_size,
+ int *err)
{
struct ext4_xattr_item *item;
item = ext4_xattr_item_alloc(name_index, name, name_len);
- if (!item)
- return NULL;
-
- if ((xattr_ref->ea_size + EXT4_XATTR_SIZE(data_size) +
- EXT4_XATTR_LEN(item->name_len)
- >
- ext4_xattr_inode_space(xattr_ref) -
- sizeof(struct ext4_xattr_ibody_header))
- &&
- (xattr_ref->ea_size + EXT4_XATTR_SIZE(data_size) +
- EXT4_XATTR_LEN(item->name_len) >
- ext4_xattr_block_space(xattr_ref) -
- sizeof(struct ext4_xattr_header))) {
- ext4_xattr_item_free(item);
+ if (!item) {
+ if (err)
+ *err = ENOMEM;
return NULL;
}
+
item->in_inode = true;
- if (xattr_ref->inode_size_rem -
- (int32_t)EXT4_XATTR_SIZE(data_size) -
- (int32_t)EXT4_XATTR_LEN(item->name_len) < 0) {
- if (xattr_ref->block_size_rem -
- (int32_t)EXT4_XATTR_SIZE(data_size) -
- (int32_t)EXT4_XATTR_LEN(item->name_len) < 0)
+ if (xattr_ref->inode_size_rem <
+ EXT4_XATTR_SIZE(data_size) +
+ EXT4_XATTR_LEN(item->name_len)) {
+ if (xattr_ref->block_size_rem <
+ EXT4_XATTR_SIZE(data_size) +
+ EXT4_XATTR_LEN(item->name_len)) {
+ if (err)
+ *err = ENOSPC;
+
return NULL;
+ }
item->in_inode = false;
}
if (ext4_xattr_item_alloc_data(item, data, data_size) != EOK) {
ext4_xattr_item_free(item);
+ if (err)
+ *err = ENOMEM;
+
return NULL;
}
RB_INSERT(ext4_xattr_tree, &xattr_ref->root, item);
EXT4_XATTR_LEN(item->name_len);
}
xattr_ref->dirty = true;
+ if (err)
+ *err = EOK;
+
return item;
}
/*
* Check if we can hold this entry in both in-inode and
- * on-block form
- */
- if ((xattr_ref->ea_size - EXT4_XATTR_SIZE(old_data_size) +
- EXT4_XATTR_SIZE(new_data_size)
- >
- ext4_xattr_inode_space(xattr_ref) -
- sizeof(struct ext4_xattr_ibody_header))
- &&
- (xattr_ref->ea_size - EXT4_XATTR_SIZE(old_data_size) +
- EXT4_XATTR_SIZE(new_data_size)
- >
- ext4_xattr_block_space(xattr_ref) -
- sizeof(struct ext4_xattr_header))) {
-
- return ENOSPC;
- }
-
- /*
+ * on-block form.
+ *
* More complicated case: we do not allow entries stucking in
* the middle between in-inode space and on-block space, so
* the entry has to stay in either inode space or block space.
*/
if (item->in_inode) {
if (xattr_ref->inode_size_rem +
- (int32_t)EXT4_XATTR_SIZE(old_data_size) -
- (int32_t)EXT4_XATTR_SIZE(new_data_size) < 0) {
- if (xattr_ref->block_size_rem -
- (int32_t)EXT4_XATTR_SIZE(new_data_size) -
- (int32_t)EXT4_XATTR_LEN(item->name_len) < 0)
+ EXT4_XATTR_SIZE(old_data_size) <
+ EXT4_XATTR_SIZE(new_data_size)) {
+ if (xattr_ref->block_size_rem <
+ EXT4_XATTR_SIZE(new_data_size) +
+ EXT4_XATTR_LEN(item->name_len))
return ENOSPC;
to_block = true;
}
} else {
if (xattr_ref->block_size_rem +
- (int32_t)EXT4_XATTR_SIZE(old_data_size) -
- (int32_t)EXT4_XATTR_SIZE(new_data_size) < 0) {
- if (xattr_ref->inode_size_rem -
- (int32_t)EXT4_XATTR_SIZE(new_data_size) -
- (int32_t)EXT4_XATTR_LEN(item->name_len) < 0)
+ EXT4_XATTR_SIZE(old_data_size) <
+ EXT4_XATTR_SIZE(new_data_size)) {
+ if (xattr_ref->inode_size_rem <
+ EXT4_XATTR_SIZE(new_data_size) +
+ EXT4_XATTR_LEN(item->name_len))
return ENOSPC;
to_inode = true;
ext4_xattr_item_free(item);
}
xattr_ref->ea_size = 0;
- xattr_ref->inode_size_rem = ext4_xattr_inode_space(xattr_ref) -
- sizeof(struct ext4_xattr_ibody_header);
- if (xattr_ref->inode_size_rem < 0)
+ if (ext4_xattr_inode_space(xattr_ref) <
+ sizeof(struct ext4_xattr_ibody_header))
xattr_ref->inode_size_rem = 0;
+ else
+ xattr_ref->inode_size_rem =
+ ext4_xattr_inode_space(xattr_ref) -
+ sizeof(struct ext4_xattr_ibody_header);
- xattr_ref->block_size_rem = ext4_xattr_block_space(xattr_ref) -
+ xattr_ref->block_size_rem =
+ ext4_xattr_block_space(xattr_ref) -
sizeof(struct ext4_xattr_header);
}
}
RB_FOREACH_SAFE(item, ext4_xattr_tree, &xattr_ref->root, save_item)
{
- if (EXT4_XATTR_SIZE(item->data_size) +
- EXT4_XATTR_LEN(item->name_len) <=
- inode_size_rem) {
+ if (item->in_inode) {
ibody_data = (char *)ibody_data -
EXT4_XATTR_SIZE(item->data_size);
ext4_xattr_set_inode_entry(item, ibody_header, entry,
memcpy(EXT4_XATTR_NAME(block_entry), item->name,
item->name_len);
memcpy(block_data, item->data, item->data_size);
+ ext4_xattr_compute_hash(block_header, block_entry);
block_entry = EXT4_XATTR_NEXT(block_entry);
block_size_rem -= EXT4_XATTR_SIZE(item->data_size) +
EXT4_XATTR_LEN(item->name_len);
goto Finish;
}
item = ext4_xattr_insert_item(ref, name_index, name, name_len,
- data, data_size);
- if (!item)
- ret = ENOMEM;
+ data, data_size, &ret);
}
Finish:
return ret;
ref->inode_ref = inode_ref;
ref->fs = fs;
- ref->inode_size_rem = ext4_xattr_inode_space(ref) -
- sizeof(struct ext4_xattr_ibody_header);
- if (ref->inode_size_rem < 0)
+ if (ext4_xattr_inode_space(ref) <
+ sizeof(struct ext4_xattr_ibody_header))
ref->inode_size_rem = 0;
+ else
+ ref->inode_size_rem =
+ ext4_xattr_inode_space(ref) -
+ sizeof(struct ext4_xattr_ibody_header);
- ref->block_size_rem = ext4_xattr_block_space(ref) -
+ ref->block_size_rem =
+ ext4_xattr_block_space(ref) -
sizeof(struct ext4_xattr_header);
+
rc = ext4_xattr_fetch(ref);
if (rc != EOK) {
ext4_xattr_purge_items(ref);