summaryrefslogtreecommitdiff
path: root/fs/ext4/xattr.c
diff options
context:
space:
mode:
authorTahsin Erdogan <tahsin@google.com>2017-07-06 00:01:59 -0400
committerTheodore Ts'o <tytso@mit.edu>2017-07-06 00:01:59 -0400
commitaf65207c76ce8e6263a3b097ea35365dde9913d0 (patch)
tree222298b2f179736a158d83341511cd9c7a81eca0 /fs/ext4/xattr.c
parentad47f9533994d7e3d2dbfa4fffe85934a1627edc (diff)
ext4: fix __ext4_new_inode() journal credits calculation
ea_inode feature allows creating extended attributes that are up to 64k in size. Update __ext4_new_inode() to pick increased credit limits. To avoid overallocating too many journal credits, update __ext4_xattr_set_credits() to make a distinction between xattr create vs update. This helps __ext4_new_inode() because all attributes are known to be new, so we can save credits that are normally needed to delete old values. Also, have fscrypt specify its maximum context size so that we don't end up allocating credits for 64k size. Signed-off-by: Tahsin Erdogan <tahsin@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/xattr.c')
-rw-r--r--fs/ext4/xattr.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 34fa37e7744c..cff4f41ced61 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -830,11 +830,10 @@ static void ext4_xattr_inode_free_quota(struct inode *inode, size_t len)
dquot_free_inode(inode);
}
-static int __ext4_xattr_set_credits(struct inode *inode,
- struct buffer_head *block_bh,
- size_t value_len)
+int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode,
+ struct buffer_head *block_bh, size_t value_len,
+ bool is_create)
{
- struct super_block *sb = inode->i_sb;
int credits;
int blocks;
@@ -860,7 +859,7 @@ static int __ext4_xattr_set_credits(struct inode *inode,
* In case of inline data, we may push out the data to a block,
* so we need to reserve credits for this eventuality
*/
- if (ext4_has_inline_data(inode))
+ if (inode && ext4_has_inline_data(inode))
credits += ext4_writepage_trans_blocks(inode) + 1;
/* We are done if ea_inode feature is not enabled. */
@@ -882,19 +881,23 @@ static int __ext4_xattr_set_credits(struct inode *inode,
/* Blocks themselves. */
credits += blocks;
- /* Dereference ea_inode holding old xattr value.
- * Old ea_inode, inode map, block bitmap, group descriptor.
- */
- credits += 4;
+ if (!is_create) {
+ /* Dereference ea_inode holding old xattr value.
+ * Old ea_inode, inode map, block bitmap, group descriptor.
+ */
+ credits += 4;
- /* Data blocks for old ea_inode. */
- blocks = XATTR_SIZE_MAX >> sb->s_blocksize_bits;
+ /* Data blocks for old ea_inode. */
+ blocks = XATTR_SIZE_MAX >> sb->s_blocksize_bits;
- /* Indirection block or one level of extent tree for old ea_inode. */
- blocks += 1;
+ /* Indirection block or one level of extent tree for old
+ * ea_inode.
+ */
+ blocks += 1;
- /* Block bitmap and group descriptor updates for each block. */
- credits += blocks * 2;
+ /* Block bitmap and group descriptor updates for each block. */
+ credits += blocks * 2;
+ }
/* We may need to clone the existing xattr block in which case we need
* to increment ref counts for existing ea_inodes referenced by it.
@@ -2263,7 +2266,9 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
goto cleanup;
}
- credits = __ext4_xattr_set_credits(inode, bh, value_len);
+ credits = __ext4_xattr_set_credits(inode->i_sb, inode, bh,
+ value_len,
+ flags & XATTR_CREATE);
brelse(bh);
if (!ext4_handle_has_enough_credits(handle, credits)) {
@@ -2370,7 +2375,8 @@ cleanup:
return error;
}
-int ext4_xattr_set_credits(struct inode *inode, size_t value_len, int *credits)
+int ext4_xattr_set_credits(struct inode *inode, size_t value_len,
+ bool is_create, int *credits)
{
struct buffer_head *bh;
int err;
@@ -2386,7 +2392,8 @@ int ext4_xattr_set_credits(struct inode *inode, size_t value_len, int *credits)
if (IS_ERR(bh)) {
err = PTR_ERR(bh);
} else {
- *credits = __ext4_xattr_set_credits(inode, bh, value_len);
+ *credits = __ext4_xattr_set_credits(inode->i_sb, inode, bh,
+ value_len, is_create);
brelse(bh);
err = 0;
}
@@ -2417,7 +2424,8 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name,
return error;
retry:
- error = ext4_xattr_set_credits(inode, value_len, &credits);
+ error = ext4_xattr_set_credits(inode, value_len, flags & XATTR_CREATE,
+ &credits);
if (error)
return error;