From 06b005e6bdb827c5950dc38ce00d3043353659f5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 11 Aug 2016 13:31:52 -0400 Subject: [PATCH] add patch factor-out-loop-for-freeing-inode-xattr-space --- factor-out-loop-for-freeing-inode-xattr-space | 166 ++++++++++++++++++++++++++ series | 1 + timestamps | 9 +- 3 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 factor-out-loop-for-freeing-inode-xattr-space diff --git a/factor-out-loop-for-freeing-inode-xattr-space b/factor-out-loop-for-freeing-inode-xattr-space new file mode 100644 index 00000000..bce97edd --- /dev/null +++ b/factor-out-loop-for-freeing-inode-xattr-space @@ -0,0 +1,166 @@ +ext4: factor out loop for freeing inode xattr space + +From: Jan Kara + +Move loop to make enough space in the inode from +ext4_expand_extra_isize_ea() into a separate function to make that +function smaller and better readable and also to avoid delaration of +variables inside a loop block. + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +--- + fs/ext4/xattr.c | 121 ++++++++++++++++++++++++++++++++------------------------ + 1 file changed, 69 insertions(+), 52 deletions(-) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 2ef687620205..c15d63389957 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1417,6 +1417,63 @@ out: + return error; + } + ++static int ext4_xattr_make_inode_space(handle_t *handle, struct inode *inode, ++ struct ext4_inode *raw_inode, ++ int isize_diff, size_t ifree, ++ size_t bfree, int *total_ino) ++{ ++ struct ext4_xattr_ibody_header *header = IHDR(inode, raw_inode); ++ struct ext4_xattr_entry *small_entry; ++ struct ext4_xattr_entry *entry; ++ struct ext4_xattr_entry *last; ++ unsigned int entry_size; /* EA entry size */ ++ unsigned int total_size; /* EA entry size + value size */ ++ unsigned int min_total_size; ++ int error; ++ ++ while (isize_diff > ifree) { ++ entry = NULL; ++ small_entry = NULL; ++ min_total_size = ~0U; ++ last = IFIRST(header); ++ /* Find the entry best suited to be pushed into EA block */ ++ for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { ++ total_size = ++ EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) + ++ EXT4_XATTR_LEN(last->e_name_len); ++ if (total_size <= bfree && ++ total_size < min_total_size) { ++ if (total_size + ifree < isize_diff) { ++ small_entry = last; ++ } else { ++ entry = last; ++ min_total_size = total_size; ++ } ++ } ++ } ++ ++ if (entry == NULL) { ++ if (small_entry == NULL) ++ return -ENOSPC; ++ entry = small_entry; ++ } ++ ++ entry_size = EXT4_XATTR_LEN(entry->e_name_len); ++ total_size = entry_size + ++ EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); ++ error = ext4_xattr_move_to_block(handle, inode, raw_inode, ++ entry); ++ if (error) ++ return error; ++ ++ *total_ino -= entry_size; ++ ifree += total_size; ++ bfree -= total_size; ++ } ++ ++ return 0; ++} ++ + /* + * Expand an inode by new_extra_isize bytes when EAs are present. + * Returns 0 on success or negative error number on failure. +@@ -1491,66 +1548,26 @@ retry: + brelse(bh); + goto retry; + } +- error = -1; ++ error = -ENOSPC; + goto cleanup; + } + } else { + bfree = inode->i_sb->s_blocksize; + } + +- while (isize_diff > ifree) { +- struct ext4_xattr_entry *small_entry = NULL, *entry = NULL; +- struct ext4_xattr_entry *last; +- unsigned int entry_size; /* EA entry size */ +- unsigned int total_size; /* EA entry size + value size */ +- unsigned int min_total_size = ~0U; +- +- last = IFIRST(header); +- /* Find the entry best suited to be pushed into EA block */ +- for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { +- total_size = +- EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) + +- EXT4_XATTR_LEN(last->e_name_len); +- if (total_size <= bfree && +- total_size < min_total_size) { +- if (total_size + ifree < isize_diff) { +- small_entry = last; +- } else { +- entry = last; +- min_total_size = total_size; +- } +- } +- } +- +- if (entry == NULL) { +- if (small_entry) { +- entry = small_entry; +- } else { +- if (!tried_min_extra_isize && +- s_min_extra_isize) { +- tried_min_extra_isize++; +- new_extra_isize = s_min_extra_isize; +- brelse(bh); +- goto retry; +- } +- error = -1; +- goto cleanup; +- } ++ error = ext4_xattr_make_inode_space(handle, inode, raw_inode, ++ isize_diff, ifree, bfree, ++ &total_ino); ++ if (error) { ++ if (error == -ENOSPC && !tried_min_extra_isize && ++ s_min_extra_isize) { ++ tried_min_extra_isize++; ++ new_extra_isize = s_min_extra_isize; ++ brelse(bh); ++ goto retry; + } +- +- entry_size = EXT4_XATTR_LEN(entry->e_name_len); +- total_size = entry_size + +- EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); +- error = ext4_xattr_move_to_block(handle, inode, raw_inode, +- entry); +- if (error) +- goto cleanup; +- +- total_ino -= entry_size; +- ifree += total_size; +- bfree -= total_size; ++ goto cleanup; + } +- + shift: + /* Adjust the offsets and shift the remaining entries ahead */ + ext4_xattr_shift_entries(IFIRST(header), EXT4_I(inode)->i_extra_isize +-- +2.6.6 + + diff --git a/series b/series index cea1b214..301f141c 100644 --- a/series +++ b/series @@ -16,6 +16,7 @@ remove-checks-for-e-value-block replace-bogus-assertion-in-ext4_xattr_shift_entries factor-out-xattr-moving remove-unused-variables-from-ext4_expand_isize_ea +factor-out-loop-for-freeing-inode-xattr-space ########################################## # unstable patches diff --git a/timestamps b/timestamps index 71274050..f7541fb6 100755 --- a/timestamps +++ b/timestamps @@ -38,14 +38,15 @@ touch -d @1470027062 validate-that-metadata-blocks-do-not-overlap-superblock touch -d @1470930630 fix-xattr-shifting-when-expanding-inodes touch -d @1470931112 fix-xattr-shifting-when-expanding-inodes-2 touch -d @1470931201 properly-align-shifted-xattrs-when-expanding-inodes -touch -d @1470931261 stable-boundary touch -d @1470933535 avoid-deadlock-while-expanding-inode-size touch -d @1470935961 fixup-free-space-calculations-when-expanding-inodes touch -d @1470936139 check-that-external-xattr-value-block-is-zero touch -d @1470936235 remove-checks-for-e-value-block touch -d @1470936306 replace-bogus-assertion-in-ext4_xattr_shift_entries touch -d @1470936476 factor-out-xattr-moving -touch -d @1470936510 series -touch -d @1470936532 status +touch -d @1470936536 stable-boundary touch -d @1470936567 remove-unused-variables-from-ext4_expand_isize_ea -touch -d @1470936578 timestamps +touch -d @1470936666 factor-out-loop-for-freeing-inode-xattr-space +touch -d @1470936687 series +touch -d @1470936697 status +touch -d @1470936705 timestamps -- 2.11.4.GIT