add patch add-ext4_is_quota_file
[ext4-patch-queue.git] / retry-storing-value-in-external-inode-with-xattr-block-too
blob70aee29e0062a73d06682dbc18c7b4c123c27f2d
1 ext4: retry storing value in external inode with xattr block too
3 From: Tahsin Erdogan <tahsin@google.com>
5 When value size is <= EXT4_XATTR_MIN_LARGE_EA_SIZE(), and it
6 doesn't fit in either inline or xattr block, a second try is made to
7 store it in an external inode while storing the entry itself in inline
8 area. There should also be an attempt to store the entry in xattr block.
10 This patch adds a retry loop to do that. It also makes the caller the
11 sole decider on whether to store a value in an external inode.
13 Signed-off-by: Tahsin Erdogan <tahsin@google.com>
14 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
15 ---
16 v2: fix checkpatch.pl warning about indented retry_inode: label
18  fs/ext4/xattr.c | 35 ++++++++++++++++++-----------------
19  1 file changed, 18 insertions(+), 17 deletions(-)
21 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
22 index dcf7ec98f138..0dfae3f8e209 100644
23 --- a/fs/ext4/xattr.c
24 +++ b/fs/ext4/xattr.c
25 @@ -911,11 +911,6 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
26         int in_inode = i->in_inode;
27         int rc;
29 -       if (ext4_has_feature_ea_inode(inode->i_sb) &&
30 -           (EXT4_XATTR_SIZE(i->value_len) >
31 -            EXT4_XATTR_MIN_LARGE_EA_SIZE(inode->i_sb->s_blocksize)))
32 -               in_inode = 1;
34         /* Compute min_offs and last. */
35         last = s->first;
36         for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
37 @@ -1097,7 +1092,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
38  {
39         struct super_block *sb = inode->i_sb;
40         struct buffer_head *new_bh = NULL;
41 -       struct ext4_xattr_search *s = &bs->s;
42 +       struct ext4_xattr_search s_copy = bs->s;
43 +       struct ext4_xattr_search *s = &s_copy;
44         struct mb_cache_entry *ce = NULL;
45         int error = 0;
46         struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
47 @@ -1519,6 +1515,11 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
48                 if (!bs.s.not_found && ext4_xattr_value_same(&bs.s, &i))
49                         goto cleanup;
51 +               if (ext4_has_feature_ea_inode(inode->i_sb) &&
52 +                   (EXT4_XATTR_SIZE(i.value_len) >
53 +                       EXT4_XATTR_MIN_LARGE_EA_SIZE(inode->i_sb->s_blocksize)))
54 +                       i.in_inode = 1;
55 +retry_inode:
56                 error = ext4_xattr_ibody_set(handle, inode, &i, &is);
57                 if (!error && !bs.s.not_found) {
58                         i.value = NULL;
59 @@ -1530,20 +1531,20 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
60                                         goto cleanup;
61                         }
62                         error = ext4_xattr_block_set(handle, inode, &i, &bs);
63 -                       if (ext4_has_feature_ea_inode(inode->i_sb) &&
64 -                           error == -ENOSPC) {
65 -                               /* xattr not fit to block, store at external
66 -                                * inode */
67 -                               i.in_inode = 1;
68 -                               error = ext4_xattr_ibody_set(handle, inode,
69 -                                                            &i, &is);
70 -                       }
71 -                       if (error)
72 -                               goto cleanup;
73 -                       if (!is.s.not_found) {
74 +                       if (!error && !is.s.not_found) {
75                                 i.value = NULL;
76                                 error = ext4_xattr_ibody_set(handle, inode, &i,
77                                                              &is);
78 +                       } else if (error == -ENOSPC) {
79 +                               /*
80 +                                * Xattr does not fit in the block, store at
81 +                                * external inode if possible.
82 +                                */
83 +                               if (ext4_has_feature_ea_inode(inode->i_sb) &&
84 +                                   !i.in_inode) {
85 +                                       i.in_inode = 1;
86 +                                       goto retry_inode;
87 +                               }
88                         }
89                 }
90         }
91 -- 
92 2.13.1.611.g7e3b11ae1-goog