]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
f2fs: add roll-forward recovery process for encrypted dentry
authorShuoran Liu <liushuoran@huawei.com>
Mon, 29 Aug 2016 03:27:56 +0000 (11:27 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Thu, 8 Sep 2016 00:27:40 +0000 (17:27 -0700)
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: Shuoran Liu <liushuoran@huawei.com>
Acked-by: Chao Yu <yuchao0@huawei.com>
[Jaegeuk Kim: modify kernel message to show encrypted names]
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/dir.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/recovery.c

index fbc8ede062bf9ea0784d0679f48966d957640203..9316d8a0ed9531ea4794d600ec73ed1d20abcec0 100644 (file)
@@ -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 @@ fail:
        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;
 }
 
index b9611d4cb49ce0df6a61714aae338d9b521b1bed..2064dc3918ca7fbaf4f7475b808306a73bd28d8e 100644 (file)
@@ -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 *,
index 21aa99b220d7f82ea7a9f23d442baa85bf10a35a..b74e985213f46bfcba16f62a1dbeb8778ffe4025 100644 (file)
@@ -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))
index 2f38bbbeec2c3bdb7c7318f717fbcc2642c81c38..ba0fc2ec7caf2152864fbdbe4ef5a7ea8b5b7a61 100644 (file)
@@ -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 @@ retry:
        } 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 @@ out_unmap_put:
        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;
 }