};
struct ocfs2_xattr_info {
- int name_index;
- const char *name;
- const void *value;
- size_t value_len;
+ int xi_name_index;
+ const char *xi_name;
+ const void *xi_value;
+ size_t xi_value_len;
};
struct ocfs2_xattr_search {
int not_found;
};
+/* Operations on struct ocfs2_xa_entry */
+struct ocfs2_xa_loc;
+struct ocfs2_xa_loc_operations {
+ /*
+ * Return a pointer to the appropriate buffer in loc->xl_storage
+ * at the given offset from loc->xl_header.
+ */
+ void *(*xlo_offset_pointer)(struct ocfs2_xa_loc *loc, int offset);
+
+ /*
+ * Remove the name+value at this location. Do whatever is
+ * appropriate with the remaining name+value pairs.
+ */
+ void (*xlo_wipe_namevalue)(struct ocfs2_xa_loc *loc);
+};
+
+/*
+ * Describes an xattr entry location. This is a memory structure
+ * tracking the on-disk structure.
+ */
+struct ocfs2_xa_loc {
+ /* The ocfs2_xattr_header inside the on-disk storage. Not NULL. */
+ struct ocfs2_xattr_header *xl_header;
+
+ /* Bytes from xl_header to the end of the storage */
+ int xl_size;
+
+ /*
+ * The ocfs2_xattr_entry this location describes. If this is
+ * NULL, this location describes the on-disk structure where it
+ * would have been.
+ */
+ struct ocfs2_xattr_entry *xl_entry;
+
+ /*
+ * Internal housekeeping
+ */
+
+ /* Buffer(s) containing this entry */
+ void *xl_storage;
+
+ /* Operations on the storage backing this location */
+ const struct ocfs2_xa_loc_operations *xl_ops;
+};
+
static int ocfs2_xattr_bucket_get_name_value(struct super_block *sb,
struct ocfs2_xattr_header *xh,
int index,
size_t offs)
{
int ret = 0;
- size_t name_len = strlen(xi->name);
+ size_t name_len = strlen(xi->xi_name);
void *val = xs->base + offs;
size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
}
xs->here->xe_name_offset = cpu_to_le16(offs);
- xs->here->xe_value_size = cpu_to_le64(xi->value_len);
- if (xi->value_len <= OCFS2_XATTR_INLINE_SIZE)
+ xs->here->xe_value_size = cpu_to_le64(xi->xi_value_len);
+ if (xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE)
ocfs2_xattr_set_local(xs->here, 1);
else
ocfs2_xattr_set_local(xs->here, 0);
struct ocfs2_xattr_value_buf *vb,
size_t offs)
{
- size_t name_len = strlen(xi->name);
+ size_t name_len = strlen(xi->xi_name);
void *val = xs->base + offs;
struct ocfs2_xattr_value_root *xv = NULL;
size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
int ret = 0;
memset(val, 0, size);
- memcpy(val, xi->name, name_len);
+ memcpy(val, xi->xi_name, name_len);
xv = (struct ocfs2_xattr_value_root *)
(val + OCFS2_XATTR_SIZE(name_len));
xv->xr_clusters = 0;
xv->xr_list.l_next_free_rec = 0;
vb->vb_xv = xv;
- ret = ocfs2_xattr_value_truncate(inode, vb, xi->value_len, ctxt);
+ ret = ocfs2_xattr_value_truncate(inode, vb, xi->xi_value_len, ctxt);
if (ret < 0) {
mlog_errno(ret);
return ret;
return ret;
}
ret = __ocfs2_xattr_set_value_outside(inode, ctxt->handle, vb,
- xi->value, xi->value_len);
+ xi->xi_value, xi->xi_value_len);
if (ret < 0)
mlog_errno(ret);
return ret;
}
+/*
+ * Wipe the name+value pair and allow the storage to reclaim it. This
+ * must be followed by either removal of the entry or a call to
+ * ocfs2_xa_add_namevalue().
+ */
+static void ocfs2_xa_wipe_namevalue(struct ocfs2_xa_loc *loc)
+{
+ loc->xl_ops->xlo_wipe_namevalue(loc);
+}
+
+static void *ocfs2_xa_block_offset_pointer(struct ocfs2_xa_loc *loc,
+ int offset)
+{
+ BUG_ON(offset >= loc->xl_size);
+ return (char *)loc->xl_header + offset;
+}
+
+/*
+ * Block storage for xattrs keeps the name+value pairs compacted. When
+ * we remove one, we have to shift any that preceded it towards the end.
+ */
+static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc)
+{
+ int i, offset;
+ int namevalue_offset, first_namevalue_offset, namevalue_size;
+ struct ocfs2_xattr_entry *entry = loc->xl_entry;
+ struct ocfs2_xattr_header *xh = loc->xl_header;
+ u64 value_size = le64_to_cpu(entry->xe_value_size);
+ int count = le16_to_cpu(xh->xh_count);
+
+ namevalue_offset = le16_to_cpu(entry->xe_name_offset);
+ namevalue_size = OCFS2_XATTR_SIZE(entry->xe_name_len);
+ if (value_size > OCFS2_XATTR_INLINE_SIZE)
+ namevalue_size += OCFS2_XATTR_ROOT_SIZE;
+ else
+ namevalue_size += OCFS2_XATTR_SIZE(value_size);
+
+ for (i = 0, first_namevalue_offset = loc->xl_size;
+ i < count; i++) {
+ offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset);
+ if (offset < first_namevalue_offset)
+ first_namevalue_offset = offset;
+ }
+
+ /* Shift the name+value pairs */
+ memmove((char *)xh + first_namevalue_offset + namevalue_size,
+ (char *)xh + first_namevalue_offset,
+ namevalue_offset - first_namevalue_offset);
+ memset((char *)xh + first_namevalue_offset, 0, namevalue_size);
+
+ /* Now tell xh->xh_entries about it */
+ for (i = 0; i < count; i++) {
+ offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset);
+ if (offset < namevalue_offset)
+ le16_add_cpu(&xh->xh_entries[i].xe_name_offset,
+ namevalue_size);
+ }
+
+ /*
+ * Note that we don't update xh_free_start or xh_name_value_len
+ * because they're not used in block-stored xattrs.
+ */
+}
+
+/*
+ * Operations for xattrs stored in blocks. This includes inline inode
+ * storage and unindexed ocfs2_xattr_blocks.
+ */
+static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = {
+ .xlo_offset_pointer = ocfs2_xa_block_offset_pointer,
+ .xlo_wipe_namevalue = ocfs2_xa_block_wipe_namevalue,
+};
+
+static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc,
+ int offset)
+{
+ struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
+ int block, block_offset;
+
+ BUG_ON(offset >= OCFS2_XATTR_BUCKET_SIZE);
+
+ /* The header is at the front of the bucket */
+ block = offset >> bucket->bu_inode->i_sb->s_blocksize_bits;
+ block_offset = offset % bucket->bu_inode->i_sb->s_blocksize;
+
+ return bucket_block(bucket, block) + block_offset;
+}
+
+static void ocfs2_xa_bucket_wipe_namevalue(struct ocfs2_xa_loc *loc)
+{
+ int namevalue_size;
+ struct ocfs2_xattr_entry *entry = loc->xl_entry;
+ u64 value_size = le64_to_cpu(entry->xe_value_size);
+
+ namevalue_size = OCFS2_XATTR_SIZE(entry->xe_name_len);
+ if (value_size > OCFS2_XATTR_INLINE_SIZE)
+ namevalue_size += OCFS2_XATTR_ROOT_SIZE;
+ else
+ namevalue_size += OCFS2_XATTR_SIZE(value_size);
+
+ le16_add_cpu(&loc->xl_header->xh_name_value_len, -namevalue_size);
+}
+
+/* Operations for xattrs stored in buckets. */
+static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = {
+ .xlo_offset_pointer = ocfs2_xa_bucket_offset_pointer,
+ .xlo_wipe_namevalue = ocfs2_xa_bucket_wipe_namevalue,
+};
+
+static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc)
+{
+ int index, count;
+ struct ocfs2_xattr_header *xh = loc->xl_header;
+ struct ocfs2_xattr_entry *entry = loc->xl_entry;
+
+ ocfs2_xa_wipe_namevalue(loc);
+ loc->xl_entry = NULL;
+
+ le16_add_cpu(&xh->xh_count, -1);
+ count = le16_to_cpu(xh->xh_count);
+
+ /*
+ * Only zero out the entry if there are more remaining. This is
+ * important for an empty bucket, as it keeps track of the
+ * bucket's hash value. It doesn't hurt empty block storage.
+ */
+ if (count) {
+ index = ((char *)entry - (char *)&xh->xh_entries) /
+ sizeof(struct ocfs2_xattr_entry);
+ memmove(&xh->xh_entries[index], &xh->xh_entries[index + 1],
+ (count - index) * sizeof(struct ocfs2_xattr_entry));
+ memset(&xh->xh_entries[count], 0,
+ sizeof(struct ocfs2_xattr_entry));
+ }
+}
+
+static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
+ struct inode *inode,
+ struct buffer_head *bh,
+ struct ocfs2_xattr_entry *entry)
+{
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
+
+ loc->xl_ops = &ocfs2_xa_block_loc_ops;
+ loc->xl_storage = bh;
+ loc->xl_entry = entry;
+
+ if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_XATTR_FL)
+ loc->xl_size = le16_to_cpu(di->i_xattr_inline_size);
+ else {
+ BUG_ON(entry);
+ loc->xl_size = OCFS2_SB(inode->i_sb)->s_xattr_inline_size;
+ }
+ loc->xl_header =
+ (struct ocfs2_xattr_header *)(bh->b_data + bh->b_size -
+ loc->xl_size);
+}
+
+static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc,
+ struct buffer_head *bh,
+ struct ocfs2_xattr_entry *entry)
+{
+ struct ocfs2_xattr_block *xb =
+ (struct ocfs2_xattr_block *)bh->b_data;
+
+ BUG_ON(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED);
+
+ loc->xl_ops = &ocfs2_xa_block_loc_ops;
+ loc->xl_storage = bh;
+ loc->xl_header = &(xb->xb_attrs.xb_header);
+ loc->xl_entry = entry;
+ loc->xl_size = bh->b_size - offsetof(struct ocfs2_xattr_block,
+ xb_attrs.xb_header);
+}
+
+static void ocfs2_init_xattr_bucket_xa_loc(struct ocfs2_xa_loc *loc,
+ struct ocfs2_xattr_bucket *bucket,
+ struct ocfs2_xattr_entry *entry)
+{
+ loc->xl_ops = &ocfs2_xa_bucket_loc_ops;
+ loc->xl_storage = bucket;
+ loc->xl_header = bucket_xh(bucket);
+ loc->xl_entry = entry;
+ loc->xl_size = OCFS2_XATTR_BUCKET_SIZE;
+}
+
/*
* ocfs2_xattr_set_entry_local()
*
struct ocfs2_xattr_entry *last,
size_t min_offs)
{
- size_t name_len = strlen(xi->name);
- int i;
+ size_t name_len = strlen(xi->xi_name);
+ struct ocfs2_xa_loc loc;
- if (xi->value && xs->not_found) {
+ if (xs->xattr_bh == xs->inode_bh)
+ ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh,
+ xs->not_found ? NULL : xs->here);
+ else
+ ocfs2_init_xattr_block_xa_loc(&loc, xs->xattr_bh,
+ xs->not_found ? NULL : xs->here);
+ if (xi->xi_value && xs->not_found) {
/* Insert the new xattr entry. */
le16_add_cpu(&xs->header->xh_count, 1);
- ocfs2_xattr_set_type(last, xi->name_index);
+ ocfs2_xattr_set_type(last, xi->xi_name_index);
ocfs2_xattr_set_local(last, 1);
last->xe_name_len = name_len;
} else {
size = OCFS2_XATTR_SIZE(name_len) +
OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
- if (xi->value && size == OCFS2_XATTR_SIZE(name_len) +
- OCFS2_XATTR_SIZE(xi->value_len)) {
+ if (xi->xi_value && size == OCFS2_XATTR_SIZE(name_len) +
+ OCFS2_XATTR_SIZE(xi->xi_value_len)) {
/* The old and the new value have the
same size. Just replace the value. */
ocfs2_xattr_set_local(xs->here, 1);
- xs->here->xe_value_size = cpu_to_le64(xi->value_len);
+ xs->here->xe_value_size = cpu_to_le64(xi->xi_value_len);
/* Clear value bytes. */
memset(val + OCFS2_XATTR_SIZE(name_len),
0,
- OCFS2_XATTR_SIZE(xi->value_len));
+ OCFS2_XATTR_SIZE(xi->xi_value_len));
memcpy(val + OCFS2_XATTR_SIZE(name_len),
- xi->value,
- xi->value_len);
+ xi->xi_value,
+ xi->xi_value_len);
return;
}
- /* Remove the old name+value. */
- memmove(first_val + size, first_val, val - first_val);
- memset(first_val, 0, size);
- xs->here->xe_name_hash = 0;
- xs->here->xe_name_offset = 0;
- ocfs2_xattr_set_local(xs->here, 1);
- xs->here->xe_value_size = 0;
- min_offs += size;
-
- /* Adjust all value offsets. */
- last = xs->header->xh_entries;
- for (i = 0 ; i < le16_to_cpu(xs->header->xh_count); i++) {
- size_t o = le16_to_cpu(last->xe_name_offset);
-
- if (o < offs)
- last->xe_name_offset = cpu_to_le16(o + size);
- last += 1;
- }
+ if (!xi->xi_value)
+ ocfs2_xa_remove_entry(&loc);
+ else
+ ocfs2_xa_wipe_namevalue(&loc);
- if (!xi->value) {
- /* Remove the old entry. */
- last -= 1;
- memmove(xs->here, xs->here + 1,
- (void *)last - (void *)xs->here);
- memset(last, 0, sizeof(struct ocfs2_xattr_entry));
- le16_add_cpu(&xs->header->xh_count, -1);
- }
+ min_offs += size;
}
- if (xi->value) {
+ if (xi->xi_value) {
/* Insert the new name+value. */
size_t size = OCFS2_XATTR_SIZE(name_len) +
- OCFS2_XATTR_SIZE(xi->value_len);
+ OCFS2_XATTR_SIZE(xi->xi_value_len);
void *val = xs->base + min_offs - size;
xs->here->xe_name_offset = cpu_to_le16(min_offs - size);
memset(val, 0, size);
- memcpy(val, xi->name, name_len);
+ memcpy(val, xi->xi_name, name_len);
memcpy(val + OCFS2_XATTR_SIZE(name_len),
- xi->value,
- xi->value_len);
- xs->here->xe_value_size = cpu_to_le64(xi->value_len);
+ xi->xi_value,
+ xi->xi_value_len);
+ xs->here->xe_value_size = cpu_to_le64(xi->xi_value_len);
ocfs2_xattr_set_local(xs->here, 1);
ocfs2_xattr_hash_entry(inode, xs->header, xs->here);
}
struct ocfs2_xattr_entry *last;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
- size_t min_offs = xs->end - xs->base, name_len = strlen(xi->name);
+ size_t min_offs = xs->end - xs->base, name_len = strlen(xi->xi_name);
size_t size_l = 0;
handle_t *handle = ctxt->handle;
int free, i, ret;
struct ocfs2_xattr_info xi_l = {
- .name_index = xi->name_index,
- .name = xi->name,
- .value = xi->value,
- .value_len = xi->value_len,
+ .xi_name_index = xi->xi_name_index,
+ .xi_name = xi->xi_name,
+ .xi_value = xi->xi_value,
+ .xi_value_len = xi->xi_value_len,
};
struct ocfs2_xattr_value_buf vb = {
.vb_bh = xs->xattr_bh,
free += (size + sizeof(struct ocfs2_xattr_entry));
}
/* Check free space in inode or block */
- if (xi->value && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+ if (xi->xi_value && xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
if (free < sizeof(struct ocfs2_xattr_entry) +
OCFS2_XATTR_SIZE(name_len) +
OCFS2_XATTR_ROOT_SIZE) {
goto out;
}
size_l = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
- xi_l.value = (void *)&def_xv;
- xi_l.value_len = OCFS2_XATTR_ROOT_SIZE;
- } else if (xi->value) {
+ xi_l.xi_value = (void *)&def_xv;
+ xi_l.xi_value_len = OCFS2_XATTR_ROOT_SIZE;
+ } else if (xi->xi_value) {
if (free < sizeof(struct ocfs2_xattr_entry) +
OCFS2_XATTR_SIZE(name_len) +
- OCFS2_XATTR_SIZE(xi->value_len)) {
+ OCFS2_XATTR_SIZE(xi->xi_value_len)) {
ret = -ENOSPC;
goto out;
}
vb.vb_xv = (struct ocfs2_xattr_value_root *)
(val + OCFS2_XATTR_SIZE(name_len));
- if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+ if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
/*
* If new value need set outside also,
* first truncate old value to new value,
* then set new value with set_value_outside().
*/
ret = ocfs2_xattr_value_truncate(inode,
- &vb,
- xi->value_len,
- ctxt);
+ &vb,
+ xi->xi_value_len,
+ ctxt);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
ret = __ocfs2_xattr_set_value_outside(inode,
- handle,
- &vb,
- xi->value,
- xi->value_len);
+ handle,
+ &vb,
+ xi->xi_value,
+ xi->xi_value_len);
if (ret < 0)
mlog_errno(ret);
goto out;
if (ret < 0)
mlog_errno(ret);
- if (!ret && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+ if (!ret && xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
/*
* Set value outside in B tree.
* This is the second step for value size > INLINE_SIZE.
xblk = (struct ocfs2_xattr_block *)new_bh->b_data;
memset(xblk, 0, inode->i_sb->s_blocksize);
strcpy((void *)xblk, OCFS2_XATTR_BLOCK_SIGNATURE);
- xblk->xb_suballoc_slot = cpu_to_le16(osb->slot_num);
+ xblk->xb_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
xblk->xb_suballoc_bit = cpu_to_le16(suballoc_bit_start);
xblk->xb_fs_generation = cpu_to_le32(osb->fs_generation);
xblk->xb_blkno = cpu_to_le64(first_blkno);
BUG_ON(!xs->not_found);
- if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
+ if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
value_size = OCFS2_XATTR_ROOT_SIZE;
else
- value_size = OCFS2_XATTR_SIZE(xi->value_len);
+ value_size = OCFS2_XATTR_SIZE(xi->xi_value_len);
if (free >= sizeof(struct ocfs2_xattr_entry) +
- OCFS2_XATTR_SIZE(strlen(xi->name)) + value_size)
+ OCFS2_XATTR_SIZE(strlen(xi->xi_name)) + value_size)
return 1;
return 0;
char *base = NULL;
int name_offset, name_len = 0;
u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb,
- xi->value_len);
+ xi->xi_value_len);
u64 value_size;
/*
* No matter whether we replace an old one or add a new one,
* we need this for writing.
*/
- if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
+ if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
credits += new_clusters *
ocfs2_clusters_to_blocks(inode->i_sb, 1);
if (xis->not_found && xbs->not_found) {
credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
- if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+ if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
clusters_add += new_clusters;
credits += ocfs2_calc_extend_credits(inode->i_sb,
&def_xv.xv.xr_list,
* The credits for removing the value tree will be extended
* by ocfs2_remove_extent itself.
*/
- if (!xi->value) {
+ if (!xi->xi_value) {
if (!ocfs2_xattr_is_local(xe))
credits += ocfs2_remove_extent_credits(inode->i_sb);
}
}
- if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+ if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
/* the new values will be stored outside. */
u32 old_clusters = 0;
* value, we don't need any allocation, otherwise we have
* to guess metadata allocation.
*/
- if ((ocfs2_xattr_is_local(xe) && value_size >= xi->value_len) ||
+ if ((ocfs2_xattr_is_local(xe) &&
+ (value_size >= xi->xi_value_len)) ||
(!ocfs2_xattr_is_local(xe) &&
- OCFS2_XATTR_ROOT_SIZE >= xi->value_len))
+ OCFS2_XATTR_ROOT_SIZE >= xi->xi_value_len))
goto out;
}
meta_add += extra_meta;
mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, "
- "credits = %d\n", xi->name, meta_add, clusters_add, *credits);
+ "credits = %d\n", xi->xi_name, meta_add, clusters_add, *credits);
if (meta_add) {
ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add,
{
int ret = 0, credits, old_found;
- if (!xi->value) {
+ if (!xi->xi_value) {
/* Remove existing extended attribute */
if (!xis->not_found)
ret = ocfs2_xattr_ibody_set(inode, xi, xis, ctxt);
* If succeed and that extended attribute existing in
* external block, then we will remove it.
*/
- xi->value = NULL;
- xi->value_len = 0;
+ xi->xi_value = NULL;
+ xi->xi_value_len = 0;
old_found = xis->not_found;
xis->not_found = -ENODATA;
} else if (ret == -ENOSPC) {
if (di->i_xattr_loc && !xbs->xattr_bh) {
ret = ocfs2_xattr_block_find(inode,
- xi->name_index,
- xi->name, xbs);
+ xi->xi_name_index,
+ xi->xi_name, xbs);
if (ret)
goto out;
* If succeed and that extended attribute
* existing in inode, we will remove it.
*/
- xi->value = NULL;
- xi->value_len = 0;
+ xi->xi_value = NULL;
+ xi->xi_value_len = 0;
xbs->not_found = -ENODATA;
ret = ocfs2_calc_xattr_set_need(inode,
di,
int ret;
struct ocfs2_xattr_info xi = {
- .name_index = name_index,
- .name = name,
- .value = value,
- .value_len = value_len,
+ .xi_name_index = name_index,
+ .xi_name = name,
+ .xi_value = value,
+ .xi_value_len = value_len,
};
struct ocfs2_xattr_search xis = {
struct ocfs2_refcount_tree *ref_tree = NULL;
struct ocfs2_xattr_info xi = {
- .name_index = name_index,
- .name = name,
- .value = value,
- .value_len = value_len,
+ .xi_name_index = name_index,
+ .xi_name = name,
+ .xi_value = value,
+ .xi_value_len = value_len,
};
struct ocfs2_xattr_search xis = {
int local)
{
struct ocfs2_xattr_entry *last, *xe;
- int name_len = strlen(xi->name);
+ int name_len = strlen(xi->xi_name);
struct ocfs2_xattr_header *xh = xs->header;
u16 count = le16_to_cpu(xh->xh_count), start;
size_t blocksize = inode->i_sb->s_blocksize;
char *val;
size_t offs, size, new_size;
+ struct ocfs2_xa_loc loc;
+ ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
+ xs->not_found ? NULL : xs->here);
last = &xh->xh_entries[count];
if (!xs->not_found) {
xe = xs->here;
OCFS2_XATTR_SIZE(OCFS2_XATTR_ROOT_SIZE);
/*
- * If the new value will be stored outside, xi->value has been
- * initalized as an empty ocfs2_xattr_value_root, and the same
- * goes with xi->value_len, so we can set new_size safely here.
+ * If the new value will be stored outside, xi->xi_value has
+ * been initalized as an empty ocfs2_xattr_value_root, and
+ * the same goes with xi->xi_value_len, so we can set
+ * new_size safely here.
* See ocfs2_xattr_set_in_bucket.
*/
new_size = OCFS2_XATTR_SIZE(name_len) +
- OCFS2_XATTR_SIZE(xi->value_len);
+ OCFS2_XATTR_SIZE(xi->xi_value_len);
- le16_add_cpu(&xh->xh_name_value_len, -size);
- if (xi->value) {
+ if (xi->xi_value) {
+ ocfs2_xa_wipe_namevalue(&loc);
if (new_size > size)
goto set_new_name_value;
/* Now replace the old value with new one. */
if (local)
- xe->xe_value_size = cpu_to_le64(xi->value_len);
+ xe->xe_value_size =
+ cpu_to_le64(xi->xi_value_len);
else
xe->xe_value_size = 0;
xs->bucket, offs);
memset(val + OCFS2_XATTR_SIZE(name_len), 0,
size - OCFS2_XATTR_SIZE(name_len));
- if (OCFS2_XATTR_SIZE(xi->value_len) > 0)
+ if (OCFS2_XATTR_SIZE(xi->xi_value_len) > 0)
memcpy(val + OCFS2_XATTR_SIZE(name_len),
- xi->value, xi->value_len);
+ xi->xi_value, xi->xi_value_len);
le16_add_cpu(&xh->xh_name_value_len, new_size);
ocfs2_xattr_set_local(xe, local);
return;
} else {
- /*
- * Remove the old entry if there is more than one.
- * We don't remove the last entry so that we can
- * use it to indicate the hash value of the empty
- * bucket.
- */
- last -= 1;
- le16_add_cpu(&xh->xh_count, -1);
- if (xh->xh_count) {
- memmove(xe, xe + 1,
- (void *)last - (void *)xe);
- memset(last, 0,
- sizeof(struct ocfs2_xattr_entry));
- } else
+ ocfs2_xa_remove_entry(&loc);
+ if (!xh->xh_count)
xh->xh_free_start =
cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE);
memset(xe, 0, sizeof(struct ocfs2_xattr_entry));
xe->xe_name_hash = cpu_to_le32(name_hash);
xe->xe_name_len = name_len;
- ocfs2_xattr_set_type(xe, xi->name_index);
+ ocfs2_xattr_set_type(xe, xi->xi_name_index);
}
set_new_name_value:
/* Insert the new name+value. */
- size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(xi->value_len);
+ size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(xi->xi_value_len);
/*
* We must make sure that the name/value pair
xe->xe_name_offset = cpu_to_le16(offs - size);
memset(val, 0, size);
- memcpy(val, xi->name, name_len);
- memcpy(val + OCFS2_XATTR_SIZE(name_len), xi->value, xi->value_len);
+ memcpy(val, xi->xi_name, name_len);
+ memcpy(val + OCFS2_XATTR_SIZE(name_len), xi->xi_value,
+ xi->xi_value_len);
- xe->xe_value_size = cpu_to_le64(xi->value_len);
+ xe->xe_value_size = cpu_to_le64(xi->xi_value_len);
ocfs2_xattr_set_local(xe, local);
xs->here = xe;
le16_add_cpu(&xh->xh_free_start, -size);
u64 blkno;
mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n",
- (unsigned long)xi->value_len, xi->name_index,
+ (unsigned long)xi->xi_value_len, xi->xi_name_index,
(unsigned long long)bucket_blkno(xs->bucket));
if (!xs->bucket->bu_bhs[1]) {
{
int ret, local = 1;
size_t value_len;
- char *val = (char *)xi->value;
+ char *val = (char *)xi->xi_value;
struct ocfs2_xattr_entry *xe = xs->here;
- u32 name_hash = ocfs2_xattr_name_hash(inode, xi->name,
- strlen(xi->name));
+ u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
+ strlen(xi->xi_name));
if (!xs->not_found && !ocfs2_xattr_is_local(xe)) {
/*
* the modification to the xattr block will be done
* by following steps.
*/
- if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
- value_len = xi->value_len;
+ if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
+ value_len = xi->xi_value_len;
else
value_len = 0;
goto set_value_outside;
}
- value_len = xi->value_len;
+ value_len = xi->xi_value_len;
/* So we have to handle the inside block change now. */
if (value_len > OCFS2_XATTR_INLINE_SIZE) {
/*
* initalize a new empty value root and insert it first.
*/
local = 0;
- xi->value = &def_xv;
- xi->value_len = OCFS2_XATTR_ROOT_SIZE;
+ xi->xi_value = &def_xv;
+ xi->xi_value_len = OCFS2_XATTR_ROOT_SIZE;
}
ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs,
struct ocfs2_xattr_entry *xe;
u16 count, header_size, xh_free_start;
int free, max_free, need, old;
- size_t value_size = 0, name_len = strlen(xi->name);
+ size_t value_size = 0, name_len = strlen(xi->xi_name);
size_t blocksize = inode->i_sb->s_blocksize;
int ret, allocation = 0;
- mlog_entry("Set xattr %s in xattr index block\n", xi->name);
+ mlog_entry("Set xattr %s in xattr index block\n", xi->xi_name);
try_again:
xh = xs->header;
(unsigned long long)bucket_blkno(xs->bucket),
header_size);
- if (xi->value && xi->value_len > OCFS2_XATTR_INLINE_SIZE)
+ if (xi->xi_value && xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
value_size = OCFS2_XATTR_ROOT_SIZE;
- else if (xi->value)
- value_size = OCFS2_XATTR_SIZE(xi->value_len);
+ else if (xi->xi_value)
+ value_size = OCFS2_XATTR_SIZE(xi->xi_value_len);
if (xs->not_found)
need = sizeof(struct ocfs2_xattr_entry) +
*/
ret = ocfs2_check_xattr_bucket_collision(inode,
xs->bucket,
- xi->name);
+ xi->xi_name);
if (ret) {
mlog_errno(ret);
goto out;
*/
ocfs2_xattr_bucket_relse(xs->bucket);
ret = ocfs2_xattr_index_block_find(inode, xs->xattr_bh,
- xi->name_index,
- xi->name, xs);
+ xi->xi_name_index,
+ xi->xi_name, xs);
if (ret && ret != -ENODATA)
goto out;
xs->not_found = ret;
* refcount tree, and make the original extent become 3. So we will need
* 2 * cluster more extent recs at most.
*/
- if (!xi->value || xi->value_len <= OCFS2_XATTR_INLINE_SIZE) {
+ if (!xi->xi_value || xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE) {
ret = ocfs2_refcounted_xattr_delete_need(inode,
&(*ref_tree)->rf_ci,