1 ext4: factor out xattr moving
3 From: Jan Kara <jack@suse.cz>
5 Factor out function for moving xattrs from inode into external xattr
6 block from ext4_expand_extra_isize_ea(). That function is already quite
7 long and factoring out this rather standalone functionality helps
10 Signed-off-by: Jan Kara <jack@suse.cz>
11 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 fs/ext4/xattr.c | 159 ++++++++++++++++++++++++++++++--------------------------
14 1 file changed, 85 insertions(+), 74 deletions(-)
16 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
17 index 82b025c977fc..8f582ae1032d 100644
20 @@ -1340,6 +1340,84 @@ static void ext4_xattr_shift_entries(struct ext4_xattr_entry *entry,
24 + * Move xattr pointed to by 'entry' from inode into external xattr block
26 +static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
27 + struct ext4_inode *raw_inode,
28 + struct ext4_xattr_entry *entry)
30 + struct ext4_xattr_ibody_find *is = NULL;
31 + struct ext4_xattr_block_find *bs = NULL;
32 + char *buffer = NULL, *b_entry_name = NULL;
33 + size_t value_offs, value_size;
34 + struct ext4_xattr_info i = {
37 + .name_index = entry->e_name_index,
39 + struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
42 + value_offs = le16_to_cpu(entry->e_value_offs);
43 + value_size = le32_to_cpu(entry->e_value_size);
45 + is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
46 + bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
47 + buffer = kmalloc(value_size, GFP_NOFS);
48 + b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
49 + if (!is || !bs || !buffer || !b_entry_name) {
54 + is->s.not_found = -ENODATA;
55 + bs->s.not_found = -ENODATA;
59 + /* Save the entry name and the entry value */
60 + memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
61 + memcpy(b_entry_name, entry->e_name, entry->e_name_len);
62 + b_entry_name[entry->e_name_len] = '\0';
63 + i.name = b_entry_name;
65 + error = ext4_get_inode_loc(inode, &is->iloc);
69 + error = ext4_xattr_ibody_find(inode, &i, is);
73 + /* Remove the chosen entry from the inode */
74 + error = ext4_xattr_ibody_set(handle, inode, &i, is);
78 + i.name = b_entry_name;
80 + i.value_len = value_size;
81 + error = ext4_xattr_block_find(inode, &i, bs);
85 + /* Add entry which was removed from the inode into the block */
86 + error = ext4_xattr_block_set(handle, inode, &i, bs);
91 + kfree(b_entry_name);
94 + brelse(is->iloc.bh);
102 * Expand an inode by new_extra_isize bytes when EAs are present.
103 * Returns 0 on success or negative error number on failure.
105 @@ -1349,9 +1427,6 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
106 struct ext4_xattr_ibody_header *header;
107 struct ext4_xattr_entry *entry, *last, *first;
108 struct buffer_head *bh = NULL;
109 - struct ext4_xattr_ibody_find *is = NULL;
110 - struct ext4_xattr_block_find *bs = NULL;
111 - char *buffer = NULL, *b_entry_name = NULL;
115 @@ -1427,27 +1502,11 @@ retry:
118 while (isize_diff > ifree) {
119 - size_t offs, size, entry_size;
120 struct ext4_xattr_entry *small_entry = NULL;
121 - struct ext4_xattr_info i = {
125 - unsigned int total_size; /* EA entry size + value size */
126 + unsigned int entry_size; /* EA entry size */
127 + unsigned int total_size; /* EA entry size + value size */
128 unsigned int min_total_size = ~0U;
130 - is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
131 - bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
137 - is->s.not_found = -ENODATA;
138 - bs->s.not_found = -ENODATA;
139 - is->iloc.bh = NULL;
142 last = IFIRST(header);
143 /* Find the entry best suited to be pushed into EA block */
145 @@ -1474,8 +1533,6 @@ retry:
147 tried_min_extra_isize++;
148 new_extra_isize = s_min_extra_isize;
149 - kfree(is); is = NULL;
150 - kfree(bs); bs = NULL;
154 @@ -1483,58 +1540,18 @@ retry:
158 - offs = le16_to_cpu(entry->e_value_offs);
159 - size = le32_to_cpu(entry->e_value_size);
160 - entry_size = EXT4_XATTR_LEN(entry->e_name_len);
161 - total_size = entry_size + EXT4_XATTR_SIZE(size);
162 - i.name_index = entry->e_name_index,
163 - buffer = kmalloc(EXT4_XATTR_SIZE(size), GFP_NOFS);
164 - b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
165 - if (!buffer || !b_entry_name) {
169 - /* Save the entry name and the entry value */
170 - memcpy(buffer, (void *)IFIRST(header) + offs,
171 - EXT4_XATTR_SIZE(size));
172 - memcpy(b_entry_name, entry->e_name, entry->e_name_len);
173 - b_entry_name[entry->e_name_len] = '\0';
174 - i.name = b_entry_name;
176 - error = ext4_get_inode_loc(inode, &is->iloc);
180 - error = ext4_xattr_ibody_find(inode, &i, is);
181 + entry_size = EXT4_XATTR_LEN(entry->e_name_len);
182 + total_size = entry_size +
183 + EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size));
184 + error = ext4_xattr_move_to_block(handle, inode, raw_inode,
189 - /* Remove the chosen entry from the inode */
190 - error = ext4_xattr_ibody_set(handle, inode, &i, is);
193 total_ino -= entry_size;
197 - i.name = b_entry_name;
199 - i.value_len = size;
200 - error = ext4_xattr_block_find(inode, &i, bs);
204 - /* Add entry which was removed from the inode into the block */
205 - error = ext4_xattr_block_set(handle, inode, &i, bs);
208 - kfree(b_entry_name);
210 - b_entry_name = NULL;
212 - brelse(is->iloc.bh);
218 @@ -1552,12 +1569,6 @@ out:
222 - kfree(b_entry_name);
225 - brelse(is->iloc.bh);
230 * We deliberately leave EXT4_STATE_NO_EXPAND set here since inode
235 To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
236 the body of a message to majordomo@vger.kernel.org
237 More majordomo info at http://vger.kernel.org/majordomo-info.html