summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2009-08-14 16:58:38 -0700
committerJoel Becker <joel.becker@oracle.com>2010-02-26 15:41:09 -0800
commitbde1e5400a1b21ef47932ab00446c7361ff3c139 (patch)
tree289c2e4d50fe82a122ba5ceae1d17a1281263262
parent11179f2c92cb025b1ff0b794f9714b3fb395855f (diff)
downloadlinux-bde1e5400a1b21ef47932ab00446c7361ff3c139.tar.gz
linux-bde1e5400a1b21ef47932ab00446c7361ff3c139.tar.bz2
linux-bde1e5400a1b21ef47932ab00446c7361ff3c139.zip
ocfs2: Remove xattrs via ocfs2_xa_loc
Add ocfs2_xa_remove_entry(), which will remove an xattr entry from its storage via the ocfs2_xa_loc descriptor. Signed-off-by: Joel Becker <joel.becker@oracle.com>
-rw-r--r--fs/ocfs2/xattr.c62
1 files changed, 29 insertions, 33 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 945ca697eb25..22a60a7c35ca 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -1573,7 +1573,29 @@ static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = {
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,
@@ -1638,7 +1660,6 @@ static void ocfs2_xattr_set_entry_local(struct inode *inode,
size_t min_offs)
{
size_t name_len = strlen(xi->name);
- int i;
struct ocfs2_xa_loc loc;
if (xs->xattr_bh == xs->inode_bh)
@@ -1686,25 +1707,12 @@ static void ocfs2_xattr_set_entry_local(struct inode *inode,
return;
}
- /* Remove the old name+value. */
- ocfs2_xa_wipe_namevalue(&loc);
- 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;
+ if (!xi->value)
+ ocfs2_xa_remove_entry(&loc);
+ else
+ ocfs2_xa_wipe_namevalue(&loc);
min_offs += size;
-
- if (!xi->value) {
- /* Remove the old entry. */
- i = le16_to_cpu(xs->header->xh_count) - 1;
- last = &xs->header->xh_entries[i];
- xs->header->xh_count = cpu_to_le16(i);
-
- memmove(xs->here, xs->here + 1,
- (void *)last - (void *)xs->here);
- memset(last, 0, sizeof(struct ocfs2_xattr_entry));
- }
}
if (xi->value) {
/* Insert the new name+value. */
@@ -5001,8 +5009,8 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
new_size = OCFS2_XATTR_SIZE(name_len) +
OCFS2_XATTR_SIZE(xi->value_len);
- ocfs2_xa_wipe_namevalue(&loc);
if (xi->value) {
+ ocfs2_xa_wipe_namevalue(&loc);
if (new_size > size)
goto set_new_name_value;
@@ -5024,20 +5032,8 @@ static void ocfs2_xattr_set_entry_normal(struct inode *inode,
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);