Commit e7ba108a authored by Shuoran Liu's avatar Shuoran Liu Committed by Jaegeuk Kim

f2fs: add roll-forward recovery process for encrypted dentry

Add roll-forward recovery process for encrypted dentry, so the first fsync
issued to an encrypted file does not need writing checkpoint.

This improves the performance of the following test at thousands of small
files: open -> write -> fsync -> close
Signed-off-by: default avatarShuoran Liu <liushuoran@huawei.com>
Acked-by: default avatarChao Yu <yuchao0@huawei.com>
[Jaegeuk Kim: modify kernel message to show encrypted names]
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent bbf156f7
......@@ -215,31 +215,17 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
return de;
}
/*
* Find an entry in the specified directory with the wanted name.
* It returns the page where the entry was found (as a parameter - res_page),
* and the entry itself. Page is returned mapped and unlocked.
* Entry is guaranteed to be valid.
*/
struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
const struct qstr *child, struct page **res_page)
struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
struct fscrypt_name *fname, struct page **res_page)
{
unsigned long npages = dir_blocks(dir);
struct f2fs_dir_entry *de = NULL;
unsigned int max_depth;
unsigned int level;
struct fscrypt_name fname;
int err;
err = fscrypt_setup_filename(dir, child, 1, &fname);
if (err) {
*res_page = ERR_PTR(err);
return NULL;
}
if (f2fs_has_inline_dentry(dir)) {
*res_page = NULL;
de = find_in_inline_dir(dir, &fname, res_page);
de = find_in_inline_dir(dir, fname, res_page);
goto out;
}
......@@ -259,11 +245,35 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
for (level = 0; level < max_depth; level++) {
*res_page = NULL;
de = find_in_level(dir, level, &fname, res_page);
de = find_in_level(dir, level, fname, res_page);
if (de || IS_ERR(*res_page))
break;
}
out:
return de;
}
/*
* Find an entry in the specified directory with the wanted name.
* It returns the page where the entry was found (as a parameter - res_page),
* and the entry itself. Page is returned mapped and unlocked.
* Entry is guaranteed to be valid.
*/
struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
const struct qstr *child, struct page **res_page)
{
struct f2fs_dir_entry *de = NULL;
struct fscrypt_name fname;
int err;
err = fscrypt_setup_filename(dir, child, 1, &fname);
if (err) {
*res_page = ERR_PTR(err);
return NULL;
}
de = __f2fs_find_entry(dir, &fname, res_page);
fscrypt_free_filename(&fname);
return de;
}
......@@ -605,6 +615,26 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
return err;
}
int __f2fs_do_add_link(struct inode *dir, struct fscrypt_name *fname,
struct inode *inode, nid_t ino, umode_t mode)
{
struct qstr new_name;
int err = -EAGAIN;
new_name.name = fname_name(fname);
new_name.len = fname_len(fname);
if (f2fs_has_inline_dentry(dir))
err = f2fs_add_inline_entry(dir, &new_name, fname->usr_fname,
inode, ino, mode);
if (err == -EAGAIN)
err = f2fs_add_regular_entry(dir, &new_name, fname->usr_fname,
inode, ino, mode);
f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
return err;
}
/*
* Caller should grab and release a rwsem by calling f2fs_lock_op() and
* f2fs_unlock_op().
......@@ -613,26 +643,15 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
struct inode *inode, nid_t ino, umode_t mode)
{
struct fscrypt_name fname;
struct qstr new_name;
int err;
err = fscrypt_setup_filename(dir, name, 0, &fname);
if (err)
return err;
new_name.name = fname_name(&fname);
new_name.len = fname_len(&fname);
err = -EAGAIN;
if (f2fs_has_inline_dentry(dir))
err = f2fs_add_inline_entry(dir, &new_name, fname.usr_fname,
inode, ino, mode);
if (err == -EAGAIN)
err = f2fs_add_regular_entry(dir, &new_name, fname.usr_fname,
inode, ino, mode);
err = __f2fs_do_add_link(dir, &fname, inode, ino, mode);
fscrypt_free_filename(&fname);
f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
return err;
}
......
......@@ -1939,6 +1939,8 @@ struct page *init_inode_metadata(struct inode *, struct inode *,
void update_parent_metadata(struct inode *, struct inode *, unsigned int);
int room_for_filename(const void *, int, int);
void f2fs_drop_nlink(struct inode *, struct inode *);
struct f2fs_dir_entry *__f2fs_find_entry(struct inode *, struct fscrypt_name *,
struct page **);
struct f2fs_dir_entry *f2fs_find_entry(struct inode *, const struct qstr *,
struct page **);
struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
......@@ -1950,6 +1952,8 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *,
const struct qstr *, f2fs_hash_t , unsigned int);
int f2fs_add_regular_entry(struct inode *, const struct qstr *,
const struct qstr *, struct inode *, nid_t, umode_t);
int __f2fs_do_add_link(struct inode *, struct fscrypt_name*, struct inode *,
nid_t, umode_t);
int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *, nid_t,
umode_t);
void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *,
......
......@@ -137,8 +137,6 @@ static inline bool need_do_checkpoint(struct inode *inode)
need_cp = true;
else if (is_sbi_flag_set(sbi, SBI_NEED_CP))
need_cp = true;
else if (file_enc_name(inode) && need_dentry_mark(sbi, inode->i_ino))
need_cp = true;
else if (file_wrong_pino(inode))
need_cp = true;
else if (!space_for_roll_forward(sbi))
......
......@@ -96,11 +96,12 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
struct f2fs_inode *raw_inode = F2FS_INODE(ipage);
nid_t pino = le32_to_cpu(raw_inode->i_pino);
struct f2fs_dir_entry *de;
struct qstr name;
struct fscrypt_name fname;
struct page *page;
struct inode *dir, *einode;
struct fsync_inode_entry *entry;
int err = 0;
char *name;
entry = get_fsync_inode(dir_list, pino);
if (!entry) {
......@@ -120,19 +121,17 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
dir = entry->inode;
if (file_enc_name(inode))
return 0;
name.len = le32_to_cpu(raw_inode->i_namelen);
name.name = raw_inode->i_name;
memset(&fname, 0, sizeof(struct fscrypt_name));
fname.disk_name.len = le32_to_cpu(raw_inode->i_namelen);
fname.disk_name.name = raw_inode->i_name;
if (unlikely(name.len > F2FS_NAME_LEN)) {
if (unlikely(fname.disk_name.len > F2FS_NAME_LEN)) {
WARN_ON(1);
err = -ENAMETOOLONG;
goto out;
}
retry:
de = f2fs_find_entry(dir, &name, &page);
de = __f2fs_find_entry(dir, &fname, &page);
if (de && inode->i_ino == le32_to_cpu(de->ino))
goto out_unmap_put;
......@@ -156,7 +155,7 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
} else if (IS_ERR(page)) {
err = PTR_ERR(page);
} else {
err = __f2fs_add_link(dir, &name, inode,
err = __f2fs_do_add_link(dir, &fname, inode,
inode->i_ino, inode->i_mode);
}
goto out;
......@@ -165,9 +164,13 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
f2fs_dentry_kunmap(dir, page);
f2fs_put_page(page, 0);
out:
if (file_enc_name(inode))
name = "<encrypted>";
else
name = raw_inode->i_name;
f2fs_msg(inode->i_sb, KERN_NOTICE,
"%s: ino = %x, name = %s, dir = %lx, err = %d",
__func__, ino_of_node(ipage), raw_inode->i_name,
__func__, ino_of_node(ipage), name,
IS_ERR(dir) ? 0 : dir->i_ino, err);
return err;
}
......
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