Commit b347e2bc authored by Tahsin Erdogan's avatar Tahsin Erdogan Committed by Theodore Ts'o

ext4: retry storing value in external inode with xattr block too

When value size is <= EXT4_XATTR_MIN_LARGE_EA_SIZE(), and it
doesn't fit in either inline or xattr block, a second try is made to
store it in an external inode while storing the entry itself in inline
area. There should also be an attempt to store the entry in xattr block.

This patch adds a retry loop to do that. It also makes the caller the
sole decider on whether to store a value in an external inode.
Signed-off-by: default avatarTahsin Erdogan <tahsin@google.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent b3155298
...@@ -909,11 +909,6 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, ...@@ -909,11 +909,6 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
int in_inode = i->in_inode; int in_inode = i->in_inode;
int rc; int rc;
if (ext4_has_feature_ea_inode(inode->i_sb) &&
(EXT4_XATTR_SIZE(i->value_len) >
EXT4_XATTR_MIN_LARGE_EA_SIZE(inode->i_sb->s_blocksize)))
in_inode = 1;
/* Compute min_offs and last. */ /* Compute min_offs and last. */
last = s->first; last = s->first;
for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
...@@ -1095,7 +1090,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, ...@@ -1095,7 +1090,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
{ {
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct buffer_head *new_bh = NULL; struct buffer_head *new_bh = NULL;
struct ext4_xattr_search *s = &bs->s; struct ext4_xattr_search s_copy = bs->s;
struct ext4_xattr_search *s = &s_copy;
struct mb_cache_entry *ce = NULL; struct mb_cache_entry *ce = NULL;
int error = 0; int error = 0;
struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
...@@ -1517,6 +1513,11 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, ...@@ -1517,6 +1513,11 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
if (!bs.s.not_found && ext4_xattr_value_same(&bs.s, &i)) if (!bs.s.not_found && ext4_xattr_value_same(&bs.s, &i))
goto cleanup; goto cleanup;
if (ext4_has_feature_ea_inode(inode->i_sb) &&
(EXT4_XATTR_SIZE(i.value_len) >
EXT4_XATTR_MIN_LARGE_EA_SIZE(inode->i_sb->s_blocksize)))
i.in_inode = 1;
retry_inode:
error = ext4_xattr_ibody_set(handle, inode, &i, &is); error = ext4_xattr_ibody_set(handle, inode, &i, &is);
if (!error && !bs.s.not_found) { if (!error && !bs.s.not_found) {
i.value = NULL; i.value = NULL;
...@@ -1528,20 +1529,20 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, ...@@ -1528,20 +1529,20 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
goto cleanup; goto cleanup;
} }
error = ext4_xattr_block_set(handle, inode, &i, &bs); error = ext4_xattr_block_set(handle, inode, &i, &bs);
if (ext4_has_feature_ea_inode(inode->i_sb) && if (!error && !is.s.not_found) {
error == -ENOSPC) {
/* xattr not fit to block, store at external
* inode */
i.in_inode = 1;
error = ext4_xattr_ibody_set(handle, inode,
&i, &is);
}
if (error)
goto cleanup;
if (!is.s.not_found) {
i.value = NULL; i.value = NULL;
error = ext4_xattr_ibody_set(handle, inode, &i, error = ext4_xattr_ibody_set(handle, inode, &i,
&is); &is);
} else if (error == -ENOSPC) {
/*
* Xattr does not fit in the block, store at
* external inode if possible.
*/
if (ext4_has_feature_ea_inode(inode->i_sb) &&
!i.in_inode) {
i.in_inode = 1;
goto retry_inode;
}
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment