diff options
author | Andrew Morton <akpm@osdl.org> | 2003-07-06 05:40:57 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-07-06 05:40:57 -0700 |
commit | a39afa31c59075459f1b0f89d9e6e3446d0ff6a2 (patch) | |
tree | 70d799d12e8677e8124ecf4162740db5d16de977 /fs/ext3/xattr.c | |
parent | 3edb027feea281c11a7ef5e56bcf3489878d3056 (diff) | |
download | history-a39afa31c59075459f1b0f89d9e6e3446d0ff6a2.tar.gz |
[PATCH] xattr: update-in-place optimisation
From: Andreas Gruenbacher <agruen@suse.de>
It is common to update extended attributes without changing the value's
length. This patch optimizes this case. In addition to that, the current
code tries to recognize early when extended attribute blocks become
empty. This optimization is not of significant value, so this patch
removes it, and moves the empty block test further down.
Diffstat (limited to 'fs/ext3/xattr.c')
-rw-r--r-- | fs/ext3/xattr.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 578cfad5f6bf6e..0db74f94229681 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -644,13 +644,24 @@ bad_block: ext3_error(sb, "ext3_xattr_set", here->e_name_len = name_len; memcpy(here->e_name, name, name_len); } else { - /* Remove the old value. */ if (!here->e_value_block && here->e_value_size) { char *first_val = (char *)header + min_offs; size_t offs = le16_to_cpu(here->e_value_offs); char *val = (char *)header + offs; size_t size = EXT3_XATTR_SIZE( le32_to_cpu(here->e_value_size)); + + if (size == EXT3_XATTR_SIZE(value_len)) { + /* The old and the new value have the same + size. Just replace. */ + here->e_value_size = cpu_to_le32(value_len); + memset(val + size - EXT3_XATTR_PAD, 0, + EXT3_XATTR_PAD); /* Clear pad bytes. */ + memcpy(val, value, value_len); + goto skip_replace; + } + + /* Remove the old value. */ memmove(first_val + size, first_val, val - first_val); memset(first_val, 0, size); here->e_value_offs = 0; @@ -667,20 +678,12 @@ bad_block: ext3_error(sb, "ext3_xattr_set", } } if (value == NULL) { - /* Remove this attribute. */ - if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) { - /* This block is now empty. */ - error = ext3_xattr_set_handle2(handle, inode, - bh, NULL); - goto cleanup; - } else { - /* Remove the old name. */ - size_t size = EXT3_XATTR_LEN(name_len); - last = ENTRY((char *)last - size); - memmove(here, (char*)here + size, - (char*)last - (char*)here); - memset(last, 0, size); - } + /* Remove the old name. */ + size_t size = EXT3_XATTR_LEN(name_len); + last = ENTRY((char *)last - size); + memmove(here, (char*)here + size, + (char*)last - (char*)here); + memset(last, 0, size); } } @@ -697,9 +700,15 @@ bad_block: ext3_error(sb, "ext3_xattr_set", memcpy(val, value, value_len); } } - ext3_xattr_rehash(header, here); - error = ext3_xattr_set_handle2(handle, inode, bh, header); +skip_replace: + if (IS_LAST_ENTRY(ENTRY(header+1))) { + /* This block is now empty. */ + error = ext3_xattr_set_handle2(handle, inode, bh, NULL); + } else { + ext3_xattr_rehash(header, here); + error = ext3_xattr_set_handle2(handle, inode, bh, header); + } cleanup: brelse(bh); |