add patch project-expand-inode-extra-size-if-needed
[ext4-patch-queue.git] / inplace-xattr-block-update-fails-to-deduplicate-blocks
blob0df960abe90cc9c09385a8f4e5be3280c28df817
1 ext4: inplace xattr block update fails to deduplicate blocks
3 From: Tahsin Erdogan <tahsin@google.com>
5 When an xattr block has a single reference, block is updated inplace
6 and it is reinserted to the cache. Later, a cache lookup is performed
7 to see whether an existing block has the same contents. This cache
8 lookup will most of the time return the just inserted entry so
9 deduplication is not achieved.
11 Running the following test script will produce two xattr blocks which
12 can be observed in "File ACL: " line of debugfs output:
14   mke2fs -b 1024 -I 128 -F -O extent /dev/sdb 1G
15   mount /dev/sdb /mnt/sdb
17   touch /mnt/sdb/{x,y}
19   setfattr -n user.1 -v aaa /mnt/sdb/x
20   setfattr -n user.2 -v bbb /mnt/sdb/x
22   setfattr -n user.1 -v aaa /mnt/sdb/y
23   setfattr -n user.2 -v bbb /mnt/sdb/y
25   debugfs -R 'stat x' /dev/sdb | cat
26   debugfs -R 'stat y' /dev/sdb | cat
28 This patch defers the reinsertion to the cache so that we can locate
29 other blocks with the same contents.
31 Signed-off-by: Tahsin Erdogan <tahsin@google.com>
32 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
33 Reviewed-by: Andreas Dilger <adilger@dilger.ca>
34 ---
35  fs/ext4/xattr.c | 4 +---
36  1 file changed, 1 insertion(+), 3 deletions(-)
38 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
39 index cff4f41ced61..ad4ea1cf685f 100644
40 --- a/fs/ext4/xattr.c
41 +++ b/fs/ext4/xattr.c
42 @@ -1815,9 +1815,6 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
43                         ea_bdebug(bs->bh, "modifying in-place");
44                         error = ext4_xattr_set_entry(i, s, handle, inode,
45                                                      true /* is_block */);
46 -                       if (!error)
47 -                               ext4_xattr_block_cache_insert(ea_block_cache,
48 -                                                             bs->bh);
49                         ext4_xattr_block_csum_set(inode, bs->bh);
50                         unlock_buffer(bs->bh);
51                         if (error == -EFSCORRUPTED)
52 @@ -1973,6 +1970,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
53                 } else if (bs->bh && s->base == bs->bh->b_data) {
54                         /* We were modifying this block in-place. */
55                         ea_bdebug(bs->bh, "keeping this block");
56 +                       ext4_xattr_block_cache_insert(ea_block_cache, bs->bh);
57                         new_bh = bs->bh;
58                         get_bh(new_bh);
59                 } else {
60 -- 
61 2.13.2.932.g7449e964c-goog