ocfs2: Prefix the member fields of struct ocfs2_xattr_info.
[pandora-kernel.git] / fs / ocfs2 / xattr.c
index 8fc6fb0..c675a6c 100644 (file)
@@ -116,10 +116,10 @@ static struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX] = {
 };
 
 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 {
@@ -137,6 +137,51 @@ 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,
@@ -1316,7 +1361,7 @@ static int ocfs2_xattr_cleanup(struct inode *inode,
                               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;
 
@@ -1356,8 +1401,8 @@ static int ocfs2_xattr_update_entry(struct inode *inode,
        }
 
        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);
@@ -1382,14 +1427,14 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode,
                                         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;
@@ -1399,7 +1444,7 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode,
        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;
@@ -1410,13 +1455,199 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode,
                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()
  *
@@ -1428,13 +1659,19 @@ static void ocfs2_xattr_set_entry_local(struct inode *inode,
                                        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 {
@@ -1454,63 +1691,42 @@ static void ocfs2_xattr_set_entry_local(struct inode *inode,
                        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);
        }
@@ -1536,15 +1752,15 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
        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,
@@ -1582,7 +1798,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                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) {
@@ -1590,12 +1806,12 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                        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;
                }
@@ -1620,16 +1836,16 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                        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;
@@ -1647,10 +1863,10 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
                                }
 
                                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;
@@ -1728,7 +1944,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode,
        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.
@@ -2282,7 +2498,7 @@ static int ocfs2_create_xattr_block(handle_t *handle,
        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);
@@ -2394,13 +2610,13 @@ static int ocfs2_xattr_can_be_in_inode(struct inode *inode,
 
        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;
@@ -2424,7 +2640,7 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
        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;
 
        /*
@@ -2432,14 +2648,14 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
         * 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,
@@ -2484,7 +2700,7 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
         * 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);
 
@@ -2514,7 +2730,7 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
                }
        }
 
-       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;
 
@@ -2547,9 +2763,10 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
                 * 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;
        }
 
@@ -2639,7 +2856,7 @@ static int ocfs2_init_xattr_set_ctxt(struct inode *inode,
 
        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,
@@ -2679,7 +2896,7 @@ static int __ocfs2_xattr_set_handle(struct inode *inode,
 {
        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);
@@ -2693,8 +2910,8 @@ static int __ocfs2_xattr_set_handle(struct inode *inode,
                         * 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;
@@ -2722,8 +2939,8 @@ static int __ocfs2_xattr_set_handle(struct inode *inode,
                } 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;
 
@@ -2762,8 +2979,8 @@ static int __ocfs2_xattr_set_handle(struct inode *inode,
                                 * 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,
@@ -2829,10 +3046,10 @@ int ocfs2_xattr_set_handle(handle_t *handle,
        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 = {
@@ -2912,10 +3129,10 @@ int ocfs2_xattr_set(struct inode *inode,
        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 = {
@@ -4763,13 +4980,16 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
                                         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;
@@ -4782,22 +5002,24 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
                        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;
 
@@ -4805,28 +5027,16 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
                                                         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);
 
@@ -4860,12 +5070,12 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
                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
@@ -4884,10 +5094,11 @@ set_new_name_value:
        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);
@@ -4912,7 +5123,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
        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]) {
@@ -5210,10 +5421,10 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
 {
        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)) {
                /*
@@ -5228,8 +5439,8 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
                 * 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;
 
@@ -5243,7 +5454,7 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
                        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) {
                /*
@@ -5251,8 +5462,8 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode,
                 * 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,
@@ -5326,11 +5537,11 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
        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;
@@ -5346,10 +5557,10 @@ try_again:
                        (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) +
@@ -5432,7 +5643,7 @@ try_again:
                 */
                ret = ocfs2_check_xattr_bucket_collision(inode,
                                                         xs->bucket,
-                                                        xi->name);
+                                                        xi->xi_name);
                if (ret) {
                        mlog_errno(ret);
                        goto out;
@@ -5456,8 +5667,8 @@ try_again:
                 */
                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;
@@ -5678,7 +5889,7 @@ static int ocfs2_prepare_refcount_xattr(struct inode *inode,
         * 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,