Commit 922ec355 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim

f2fs crypto: avoid unneeded memory allocation when {en/de}crypting symlink

This patch adopts f2fs with codes of ext4, it removes unneeded memory
allocation in creating/accessing path of symlink.
Signed-off-by: default avatarChao Yu <chao2.yu@samsung.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent ae108668
...@@ -257,6 +257,18 @@ u32 f2fs_fname_crypto_round_up(u32 size, u32 blksize) ...@@ -257,6 +257,18 @@ u32 f2fs_fname_crypto_round_up(u32 size, u32 blksize)
return ((size + blksize - 1) / blksize) * blksize; return ((size + blksize - 1) / blksize) * blksize;
} }
unsigned f2fs_fname_encrypted_size(struct inode *inode, u32 ilen)
{
struct f2fs_crypt_info *ci = F2FS_I(inode)->i_crypt_info;
int padding = 32;
if (ci)
padding = 4 << (ci->ci_flags & F2FS_POLICY_FLAGS_PAD_MASK);
if (ilen < F2FS_CRYPTO_BLOCK_SIZE)
ilen = F2FS_CRYPTO_BLOCK_SIZE;
return f2fs_fname_crypto_round_up(ilen, padding);
}
/** /**
* f2fs_fname_crypto_alloc_obuff() - * f2fs_fname_crypto_alloc_obuff() -
* *
...@@ -266,15 +278,8 @@ u32 f2fs_fname_crypto_round_up(u32 size, u32 blksize) ...@@ -266,15 +278,8 @@ u32 f2fs_fname_crypto_round_up(u32 size, u32 blksize)
int f2fs_fname_crypto_alloc_buffer(struct inode *inode, int f2fs_fname_crypto_alloc_buffer(struct inode *inode,
u32 ilen, struct f2fs_str *crypto_str) u32 ilen, struct f2fs_str *crypto_str)
{ {
unsigned int olen; unsigned int olen = f2fs_fname_encrypted_size(inode, ilen);
int padding = 32;
struct f2fs_crypt_info *ci = F2FS_I(inode)->i_crypt_info;
if (ci)
padding = 4 << (ci->ci_flags & F2FS_POLICY_FLAGS_PAD_MASK);
if (ilen < F2FS_CRYPTO_BLOCK_SIZE)
ilen = F2FS_CRYPTO_BLOCK_SIZE;
olen = f2fs_fname_crypto_round_up(ilen, padding);
crypto_str->len = olen; crypto_str->len = olen;
if (olen < F2FS_FNAME_CRYPTO_DIGEST_SIZE * 2) if (olen < F2FS_FNAME_CRYPTO_DIGEST_SIZE * 2)
olen = F2FS_FNAME_CRYPTO_DIGEST_SIZE * 2; olen = F2FS_FNAME_CRYPTO_DIGEST_SIZE * 2;
......
...@@ -2226,6 +2226,7 @@ int _f2fs_get_encryption_info(struct inode *inode); ...@@ -2226,6 +2226,7 @@ int _f2fs_get_encryption_info(struct inode *inode);
/* crypto_fname.c */ /* crypto_fname.c */
bool f2fs_valid_filenames_enc_mode(uint32_t); bool f2fs_valid_filenames_enc_mode(uint32_t);
u32 f2fs_fname_crypto_round_up(u32, u32); u32 f2fs_fname_crypto_round_up(u32, u32);
unsigned f2fs_fname_encrypted_size(struct inode *, u32);
int f2fs_fname_crypto_alloc_buffer(struct inode *, u32, struct f2fs_str *); int f2fs_fname_crypto_alloc_buffer(struct inode *, u32, struct f2fs_str *);
int f2fs_fname_disk_to_usr(struct inode *, f2fs_hash_t *, int f2fs_fname_disk_to_usr(struct inode *, f2fs_hash_t *,
const struct f2fs_str *, struct f2fs_str *); const struct f2fs_str *, struct f2fs_str *);
......
...@@ -345,13 +345,23 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -345,13 +345,23 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
struct f2fs_sb_info *sbi = F2FS_I_SB(dir); struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
struct inode *inode; struct inode *inode;
size_t len = strlen(symname); size_t len = strlen(symname);
size_t p_len; struct f2fs_str disk_link = FSTR_INIT((char *)symname, len + 1);
char *p_str;
struct f2fs_str disk_link = FSTR_INIT(NULL, 0);
struct f2fs_encrypted_symlink_data *sd = NULL; struct f2fs_encrypted_symlink_data *sd = NULL;
int err; int err;
if (len > dir->i_sb->s_blocksize) if (f2fs_encrypted_inode(dir)) {
err = f2fs_get_encryption_info(dir);
if (err)
return err;
if (!f2fs_encrypted_inode(dir))
return -EPERM;
disk_link.len = (f2fs_fname_encrypted_size(dir, len) +
sizeof(struct f2fs_encrypted_symlink_data));
}
if (disk_link.len > dir->i_sb->s_blocksize)
return -ENAMETOOLONG; return -ENAMETOOLONG;
inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO); inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
...@@ -374,42 +384,36 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -374,42 +384,36 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
alloc_nid_done(sbi, inode->i_ino); alloc_nid_done(sbi, inode->i_ino);
if (f2fs_encrypted_inode(dir)) { if (f2fs_encrypted_inode(inode)) {
struct qstr istr = QSTR_INIT(symname, len); struct qstr istr = QSTR_INIT(symname, len);
struct f2fs_str ostr;
err = f2fs_get_encryption_info(inode); sd = kzalloc(disk_link.len, GFP_NOFS);
if (err) if (!sd) {
err = -ENOMEM;
goto err_out; goto err_out;
}
err = f2fs_fname_crypto_alloc_buffer(inode, len, &disk_link); err = f2fs_get_encryption_info(inode);
if (err) if (err)
goto err_out; goto err_out;
err = f2fs_fname_usr_to_disk(inode, &istr, &disk_link); if (!f2fs_encrypted_inode(inode)) {
if (err < 0) err = -EPERM;
goto err_out;
p_len = encrypted_symlink_data_len(disk_link.len) + 1;
if (p_len > dir->i_sb->s_blocksize) {
err = -ENAMETOOLONG;
goto err_out; goto err_out;
} }
sd = kzalloc(p_len, GFP_NOFS); ostr.name = sd->encrypted_path;
if (!sd) { ostr.len = disk_link.len;
err = -ENOMEM; err = f2fs_fname_usr_to_disk(inode, &istr, &ostr);
if (err < 0)
goto err_out; goto err_out;
}
memcpy(sd->encrypted_path, disk_link.name, disk_link.len); sd->len = cpu_to_le16(ostr.len);
sd->len = cpu_to_le16(disk_link.len); disk_link.name = (char *)sd;
p_str = (char *)sd;
} else {
p_len = len + 1;
p_str = (char *)symname;
} }
err = page_symlink(inode, p_str, p_len); err = page_symlink(inode, disk_link.name, disk_link.len);
err_out: err_out:
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
...@@ -425,7 +429,8 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -425,7 +429,8 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
* performance regression. * performance regression.
*/ */
if (!err) { if (!err) {
filemap_write_and_wait_range(inode->i_mapping, 0, p_len - 1); filemap_write_and_wait_range(inode->i_mapping, 0,
disk_link.len - 1);
if (IS_DIRSYNC(dir)) if (IS_DIRSYNC(dir))
f2fs_sync_fs(sbi->sb, 1); f2fs_sync_fs(sbi->sb, 1);
...@@ -434,7 +439,6 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -434,7 +439,6 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
} }
kfree(sd); kfree(sd);
f2fs_fname_crypto_free_buffer(&disk_link);
return err; return err;
out: out:
handle_failed_inode(inode); handle_failed_inode(inode);
...@@ -966,6 +970,7 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry, ...@@ -966,6 +970,7 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
/* Symlink is encrypted */ /* Symlink is encrypted */
sd = (struct f2fs_encrypted_symlink_data *)caddr; sd = (struct f2fs_encrypted_symlink_data *)caddr;
cstr.name = sd->encrypted_path;
cstr.len = le16_to_cpu(sd->len); cstr.len = le16_to_cpu(sd->len);
/* this is broken symlink case */ /* this is broken symlink case */
...@@ -973,12 +978,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry, ...@@ -973,12 +978,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
res = -ENOENT; res = -ENOENT;
goto errout; goto errout;
} }
cstr.name = kmalloc(cstr.len, GFP_NOFS);
if (!cstr.name) {
res = -ENOMEM;
goto errout;
}
memcpy(cstr.name, sd->encrypted_path, cstr.len);
/* this is broken symlink case */ /* this is broken symlink case */
if (unlikely(cstr.name[0] == 0)) { if (unlikely(cstr.name[0] == 0)) {
...@@ -1000,8 +999,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry, ...@@ -1000,8 +999,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
if (res < 0) if (res < 0)
goto errout; goto errout;
kfree(cstr.name);
paddr = pstr.name; paddr = pstr.name;
/* Null-terminate the name */ /* Null-terminate the name */
...@@ -1011,7 +1008,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry, ...@@ -1011,7 +1008,6 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry,
set_delayed_call(done, kfree_link, paddr); set_delayed_call(done, kfree_link, paddr);
return paddr; return paddr;
errout: errout:
kfree(cstr.name);
f2fs_fname_crypto_free_buffer(&pstr); f2fs_fname_crypto_free_buffer(&pstr);
page_cache_release(cpage); page_cache_release(cpage);
return ERR_PTR(res); return ERR_PTR(res);
......
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