ext4: factor out xattr moving
Factor out function for moving xattrs from inode into external xattr block from ext4_expand_extra_isize_ea(). That function is already quite long and factoring out this rather standalone functionality helps readability. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
Родитель
9440571388
Коммит
3f2571c1f9
159
fs/ext4/xattr.c
159
fs/ext4/xattr.c
|
@ -1339,6 +1339,84 @@ static void ext4_xattr_shift_entries(struct ext4_xattr_entry *entry,
|
||||||
memmove(to, from, n);
|
memmove(to, from, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move xattr pointed to by 'entry' from inode into external xattr block
|
||||||
|
*/
|
||||||
|
static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
|
||||||
|
struct ext4_inode *raw_inode,
|
||||||
|
struct ext4_xattr_entry *entry)
|
||||||
|
{
|
||||||
|
struct ext4_xattr_ibody_find *is = NULL;
|
||||||
|
struct ext4_xattr_block_find *bs = NULL;
|
||||||
|
char *buffer = NULL, *b_entry_name = NULL;
|
||||||
|
size_t value_offs, value_size;
|
||||||
|
struct ext4_xattr_info i = {
|
||||||
|
.value = NULL,
|
||||||
|
.value_len = 0,
|
||||||
|
.name_index = entry->e_name_index,
|
||||||
|
};
|
||||||
|
struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode);
|
||||||
|
int error;
|
||||||
|
|
||||||
|
value_offs = le16_to_cpu(entry->e_value_offs);
|
||||||
|
value_size = le32_to_cpu(entry->e_value_size);
|
||||||
|
|
||||||
|
is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
|
||||||
|
bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
|
||||||
|
buffer = kmalloc(value_size, GFP_NOFS);
|
||||||
|
b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
|
||||||
|
if (!is || !bs || !buffer || !b_entry_name) {
|
||||||
|
error = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
is->s.not_found = -ENODATA;
|
||||||
|
bs->s.not_found = -ENODATA;
|
||||||
|
is->iloc.bh = NULL;
|
||||||
|
bs->bh = NULL;
|
||||||
|
|
||||||
|
/* Save the entry name and the entry value */
|
||||||
|
memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
|
||||||
|
memcpy(b_entry_name, entry->e_name, entry->e_name_len);
|
||||||
|
b_entry_name[entry->e_name_len] = '\0';
|
||||||
|
i.name = b_entry_name;
|
||||||
|
|
||||||
|
error = ext4_get_inode_loc(inode, &is->iloc);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
error = ext4_xattr_ibody_find(inode, &i, is);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Remove the chosen entry from the inode */
|
||||||
|
error = ext4_xattr_ibody_set(handle, inode, &i, is);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
i.name = b_entry_name;
|
||||||
|
i.value = buffer;
|
||||||
|
i.value_len = value_size;
|
||||||
|
error = ext4_xattr_block_find(inode, &i, bs);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Add entry which was removed from the inode into the block */
|
||||||
|
error = ext4_xattr_block_set(handle, inode, &i, bs);
|
||||||
|
if (error)
|
||||||
|
goto out;
|
||||||
|
error = 0;
|
||||||
|
out:
|
||||||
|
kfree(b_entry_name);
|
||||||
|
kfree(buffer);
|
||||||
|
if (is)
|
||||||
|
brelse(is->iloc.bh);
|
||||||
|
kfree(is);
|
||||||
|
kfree(bs);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expand an inode by new_extra_isize bytes when EAs are present.
|
* Expand an inode by new_extra_isize bytes when EAs are present.
|
||||||
* Returns 0 on success or negative error number on failure.
|
* Returns 0 on success or negative error number on failure.
|
||||||
|
@ -1349,9 +1427,6 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
|
||||||
struct ext4_xattr_ibody_header *header;
|
struct ext4_xattr_ibody_header *header;
|
||||||
struct ext4_xattr_entry *entry, *last, *first;
|
struct ext4_xattr_entry *entry, *last, *first;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
struct ext4_xattr_ibody_find *is = NULL;
|
|
||||||
struct ext4_xattr_block_find *bs = NULL;
|
|
||||||
char *buffer = NULL, *b_entry_name = NULL;
|
|
||||||
size_t min_offs;
|
size_t min_offs;
|
||||||
size_t ifree, bfree;
|
size_t ifree, bfree;
|
||||||
int total_ino;
|
int total_ino;
|
||||||
|
@ -1427,27 +1502,11 @@ retry:
|
||||||
}
|
}
|
||||||
|
|
||||||
while (isize_diff > ifree) {
|
while (isize_diff > ifree) {
|
||||||
size_t offs, size, entry_size;
|
|
||||||
struct ext4_xattr_entry *small_entry = NULL;
|
struct ext4_xattr_entry *small_entry = NULL;
|
||||||
struct ext4_xattr_info i = {
|
unsigned int entry_size; /* EA entry size */
|
||||||
.value = NULL,
|
unsigned int total_size; /* EA entry size + value size */
|
||||||
.value_len = 0,
|
|
||||||
};
|
|
||||||
unsigned int total_size; /* EA entry size + value size */
|
|
||||||
unsigned int min_total_size = ~0U;
|
unsigned int min_total_size = ~0U;
|
||||||
|
|
||||||
is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
|
|
||||||
bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
|
|
||||||
if (!is || !bs) {
|
|
||||||
error = -ENOMEM;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
is->s.not_found = -ENODATA;
|
|
||||||
bs->s.not_found = -ENODATA;
|
|
||||||
is->iloc.bh = NULL;
|
|
||||||
bs->bh = NULL;
|
|
||||||
|
|
||||||
last = IFIRST(header);
|
last = IFIRST(header);
|
||||||
/* Find the entry best suited to be pushed into EA block */
|
/* Find the entry best suited to be pushed into EA block */
|
||||||
entry = NULL;
|
entry = NULL;
|
||||||
|
@ -1474,8 +1533,6 @@ retry:
|
||||||
s_min_extra_isize) {
|
s_min_extra_isize) {
|
||||||
tried_min_extra_isize++;
|
tried_min_extra_isize++;
|
||||||
new_extra_isize = s_min_extra_isize;
|
new_extra_isize = s_min_extra_isize;
|
||||||
kfree(is); is = NULL;
|
|
||||||
kfree(bs); bs = NULL;
|
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
@ -1483,58 +1540,18 @@ retry:
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offs = le16_to_cpu(entry->e_value_offs);
|
|
||||||
size = le32_to_cpu(entry->e_value_size);
|
|
||||||
entry_size = EXT4_XATTR_LEN(entry->e_name_len);
|
entry_size = EXT4_XATTR_LEN(entry->e_name_len);
|
||||||
total_size = entry_size + EXT4_XATTR_SIZE(size);
|
total_size = entry_size +
|
||||||
i.name_index = entry->e_name_index,
|
EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size));
|
||||||
buffer = kmalloc(EXT4_XATTR_SIZE(size), GFP_NOFS);
|
error = ext4_xattr_move_to_block(handle, inode, raw_inode,
|
||||||
b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
|
entry);
|
||||||
if (!buffer || !b_entry_name) {
|
|
||||||
error = -ENOMEM;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
/* Save the entry name and the entry value */
|
|
||||||
memcpy(buffer, (void *)IFIRST(header) + offs,
|
|
||||||
EXT4_XATTR_SIZE(size));
|
|
||||||
memcpy(b_entry_name, entry->e_name, entry->e_name_len);
|
|
||||||
b_entry_name[entry->e_name_len] = '\0';
|
|
||||||
i.name = b_entry_name;
|
|
||||||
|
|
||||||
error = ext4_get_inode_loc(inode, &is->iloc);
|
|
||||||
if (error)
|
if (error)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
error = ext4_xattr_ibody_find(inode, &i, is);
|
|
||||||
if (error)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Remove the chosen entry from the inode */
|
|
||||||
error = ext4_xattr_ibody_set(handle, inode, &i, is);
|
|
||||||
if (error)
|
|
||||||
goto cleanup;
|
|
||||||
total_ino -= entry_size;
|
total_ino -= entry_size;
|
||||||
ifree += total_size;
|
ifree += total_size;
|
||||||
bfree -= total_size;
|
bfree -= total_size;
|
||||||
|
|
||||||
i.name = b_entry_name;
|
|
||||||
i.value = buffer;
|
|
||||||
i.value_len = size;
|
|
||||||
error = ext4_xattr_block_find(inode, &i, bs);
|
|
||||||
if (error)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Add entry which was removed from the inode into the block */
|
|
||||||
error = ext4_xattr_block_set(handle, inode, &i, bs);
|
|
||||||
if (error)
|
|
||||||
goto cleanup;
|
|
||||||
kfree(b_entry_name);
|
|
||||||
kfree(buffer);
|
|
||||||
b_entry_name = NULL;
|
|
||||||
buffer = NULL;
|
|
||||||
brelse(is->iloc.bh);
|
|
||||||
kfree(is);
|
|
||||||
kfree(bs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shift:
|
shift:
|
||||||
|
@ -1552,12 +1569,6 @@ out:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
kfree(b_entry_name);
|
|
||||||
kfree(buffer);
|
|
||||||
if (is)
|
|
||||||
brelse(is->iloc.bh);
|
|
||||||
kfree(is);
|
|
||||||
kfree(bs);
|
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
/*
|
/*
|
||||||
* We deliberately leave EXT4_STATE_NO_EXPAND set here since inode
|
* We deliberately leave EXT4_STATE_NO_EXPAND set here since inode
|
||||||
|
|
Загрузка…
Ссылка в новой задаче