aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShuoran Liu <liushuoran@huawei.com>2016-08-28 23:27:56 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2016-09-07 20:27:40 -0400
commite7ba108a06216dae89a64c0243560502276b92d8 (patch)
treeee03ce54770cc7de009a11b4efd961671131fd18
parentbbf156f7afa7f3cc07177f1119878f6f60855fd1 (diff)
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: 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>
-rw-r--r--fs/f2fs/dir.c79
-rw-r--r--fs/f2fs/f2fs.h4
-rw-r--r--fs/f2fs/file.c2
-rw-r--r--fs/f2fs/recovery.c23
4 files changed, 66 insertions, 42 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index fbc8ede062bf..9316d8a0ed95 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -215,31 +215,17 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
215 return de; 215 return de;
216} 216}
217 217
218/* 218struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
219 * Find an entry in the specified directory with the wanted name. 219 struct fscrypt_name *fname, struct page **res_page)
220 * It returns the page where the entry was found (as a parameter - res_page),
221 * and the entry itself. Page is returned mapped and unlocked.
222 * Entry is guaranteed to be valid.
223 */
224struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
225 const struct qstr *child, struct page **res_page)
226{ 220{
227 unsigned long npages = dir_blocks(dir); 221 unsigned long npages = dir_blocks(dir);
228 struct f2fs_dir_entry *de = NULL; 222 struct f2fs_dir_entry *de = NULL;
229 unsigned int max_depth; 223 unsigned int max_depth;
230 unsigned int level; 224 unsigned int level;
231 struct fscrypt_name fname;
232 int err;
233
234 err = fscrypt_setup_filename(dir, child, 1, &fname);
235 if (err) {
236 *res_page = ERR_PTR(err);
237 return NULL;
238 }
239 225
240 if (f2fs_has_inline_dentry(dir)) { 226 if (f2fs_has_inline_dentry(dir)) {
241 *res_page = NULL; 227 *res_page = NULL;
242 de = find_in_inline_dir(dir, &fname, res_page); 228 de = find_in_inline_dir(dir, fname, res_page);
243 goto out; 229 goto out;
244 } 230 }
245 231
@@ -259,11 +245,35 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
259 245
260 for (level = 0; level < max_depth; level++) { 246 for (level = 0; level < max_depth; level++) {
261 *res_page = NULL; 247 *res_page = NULL;
262 de = find_in_level(dir, level, &fname, res_page); 248 de = find_in_level(dir, level, fname, res_page);
263 if (de || IS_ERR(*res_page)) 249 if (de || IS_ERR(*res_page))
264 break; 250 break;
265 } 251 }
266out: 252out:
253 return de;
254}
255
256/*
257 * Find an entry in the specified directory with the wanted name.
258 * It returns the page where the entry was found (as a parameter - res_page),
259 * and the entry itself. Page is returned mapped and unlocked.
260 * Entry is guaranteed to be valid.
261 */
262struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
263 const struct qstr *child, struct page **res_page)
264{
265 struct f2fs_dir_entry *de = NULL;
266 struct fscrypt_name fname;
267 int err;
268
269 err = fscrypt_setup_filename(dir, child, 1, &fname);
270 if (err) {
271 *res_page = ERR_PTR(err);
272 return NULL;
273 }
274
275 de = __f2fs_find_entry(dir, &fname, res_page);
276
267 fscrypt_free_filename(&fname); 277 fscrypt_free_filename(&fname);
268 return de; 278 return de;
269} 279}
@@ -605,6 +615,26 @@ fail:
605 return err; 615 return err;
606} 616}
607 617
618int __f2fs_do_add_link(struct inode *dir, struct fscrypt_name *fname,
619 struct inode *inode, nid_t ino, umode_t mode)
620{
621 struct qstr new_name;
622 int err = -EAGAIN;
623
624 new_name.name = fname_name(fname);
625 new_name.len = fname_len(fname);
626
627 if (f2fs_has_inline_dentry(dir))
628 err = f2fs_add_inline_entry(dir, &new_name, fname->usr_fname,
629 inode, ino, mode);
630 if (err == -EAGAIN)
631 err = f2fs_add_regular_entry(dir, &new_name, fname->usr_fname,
632 inode, ino, mode);
633
634 f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
635 return err;
636}
637
608/* 638/*
609 * Caller should grab and release a rwsem by calling f2fs_lock_op() and 639 * Caller should grab and release a rwsem by calling f2fs_lock_op() and
610 * f2fs_unlock_op(). 640 * f2fs_unlock_op().
@@ -613,26 +643,15 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
613 struct inode *inode, nid_t ino, umode_t mode) 643 struct inode *inode, nid_t ino, umode_t mode)
614{ 644{
615 struct fscrypt_name fname; 645 struct fscrypt_name fname;
616 struct qstr new_name;
617 int err; 646 int err;
618 647
619 err = fscrypt_setup_filename(dir, name, 0, &fname); 648 err = fscrypt_setup_filename(dir, name, 0, &fname);
620 if (err) 649 if (err)
621 return err; 650 return err;
622 651
623 new_name.name = fname_name(&fname); 652 err = __f2fs_do_add_link(dir, &fname, inode, ino, mode);
624 new_name.len = fname_len(&fname);
625
626 err = -EAGAIN;
627 if (f2fs_has_inline_dentry(dir))
628 err = f2fs_add_inline_entry(dir, &new_name, fname.usr_fname,
629 inode, ino, mode);
630 if (err == -EAGAIN)
631 err = f2fs_add_regular_entry(dir, &new_name, fname.usr_fname,
632 inode, ino, mode);
633 653
634 fscrypt_free_filename(&fname); 654 fscrypt_free_filename(&fname);
635 f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
636 return err; 655 return err;
637} 656}
638 657
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index b9611d4cb49c..2064dc3918ca 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1939,6 +1939,8 @@ struct page *init_inode_metadata(struct inode *, struct inode *,
1939void update_parent_metadata(struct inode *, struct inode *, unsigned int); 1939void update_parent_metadata(struct inode *, struct inode *, unsigned int);
1940int room_for_filename(const void *, int, int); 1940int room_for_filename(const void *, int, int);
1941void f2fs_drop_nlink(struct inode *, struct inode *); 1941void f2fs_drop_nlink(struct inode *, struct inode *);
1942struct f2fs_dir_entry *__f2fs_find_entry(struct inode *, struct fscrypt_name *,
1943 struct page **);
1942struct f2fs_dir_entry *f2fs_find_entry(struct inode *, const struct qstr *, 1944struct f2fs_dir_entry *f2fs_find_entry(struct inode *, const struct qstr *,
1943 struct page **); 1945 struct page **);
1944struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **); 1946struct 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 *,
1950 const struct qstr *, f2fs_hash_t , unsigned int); 1952 const struct qstr *, f2fs_hash_t , unsigned int);
1951int f2fs_add_regular_entry(struct inode *, const struct qstr *, 1953int f2fs_add_regular_entry(struct inode *, const struct qstr *,
1952 const struct qstr *, struct inode *, nid_t, umode_t); 1954 const struct qstr *, struct inode *, nid_t, umode_t);
1955int __f2fs_do_add_link(struct inode *, struct fscrypt_name*, struct inode *,
1956 nid_t, umode_t);
1953int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *, nid_t, 1957int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *, nid_t,
1954 umode_t); 1958 umode_t);
1955void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *, 1959void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *,
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 21aa99b220d7..b74e985213f4 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -137,8 +137,6 @@ static inline bool need_do_checkpoint(struct inode *inode)
137 need_cp = true; 137 need_cp = true;
138 else if (is_sbi_flag_set(sbi, SBI_NEED_CP)) 138 else if (is_sbi_flag_set(sbi, SBI_NEED_CP))
139 need_cp = true; 139 need_cp = true;
140 else if (file_enc_name(inode) && need_dentry_mark(sbi, inode->i_ino))
141 need_cp = true;
142 else if (file_wrong_pino(inode)) 140 else if (file_wrong_pino(inode))
143 need_cp = true; 141 need_cp = true;
144 else if (!space_for_roll_forward(sbi)) 142 else if (!space_for_roll_forward(sbi))
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 2f38bbbeec2c..ba0fc2ec7caf 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -96,11 +96,12 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
96 struct f2fs_inode *raw_inode = F2FS_INODE(ipage); 96 struct f2fs_inode *raw_inode = F2FS_INODE(ipage);
97 nid_t pino = le32_to_cpu(raw_inode->i_pino); 97 nid_t pino = le32_to_cpu(raw_inode->i_pino);
98 struct f2fs_dir_entry *de; 98 struct f2fs_dir_entry *de;
99 struct qstr name; 99 struct fscrypt_name fname;
100 struct page *page; 100 struct page *page;
101 struct inode *dir, *einode; 101 struct inode *dir, *einode;
102 struct fsync_inode_entry *entry; 102 struct fsync_inode_entry *entry;
103 int err = 0; 103 int err = 0;
104 char *name;
104 105
105 entry = get_fsync_inode(dir_list, pino); 106 entry = get_fsync_inode(dir_list, pino);
106 if (!entry) { 107 if (!entry) {
@@ -120,19 +121,17 @@ static int recover_dentry(struct inode *inode, struct page *ipage,
120 121
121 dir = entry->inode; 122 dir = entry->inode;
122 123
123 if (file_enc_name(inode)) 124 memset(&fname, 0, sizeof(struct fscrypt_name));
124 return 0; 125 fname.disk_name.len = le32_to_cpu(raw_inode->i_namelen);
125 126 fname.disk_name.name = raw_inode->i_name;
126 name.len = le32_to_cpu(raw_inode->i_namelen);
127 name.name = raw_inode->i_name;
128 127
129 if (unlikely(name.len > F2FS_NAME_LEN)) { 128 if (unlikely(fname.disk_name.len > F2FS_NAME_LEN)) {
130 WARN_ON(1); 129 WARN_ON(1);
131 err = -ENAMETOOLONG; 130 err = -ENAMETOOLONG;
132 goto out; 131 goto out;
133 } 132 }
134retry: 133retry:
135 de = f2fs_find_entry(dir, &name, &page); 134 de = __f2fs_find_entry(dir, &fname, &page);
136 if (de && inode->i_ino == le32_to_cpu(de->ino)) 135 if (de && inode->i_ino == le32_to_cpu(de->ino))
137 goto out_unmap_put; 136 goto out_unmap_put;
138 137
@@ -156,7 +155,7 @@ retry:
156 } else if (IS_ERR(page)) { 155 } else if (IS_ERR(page)) {
157 err = PTR_ERR(page); 156 err = PTR_ERR(page);
158 } else { 157 } else {
159 err = __f2fs_add_link(dir, &name, inode, 158 err = __f2fs_do_add_link(dir, &fname, inode,
160 inode->i_ino, inode->i_mode); 159 inode->i_ino, inode->i_mode);
161 } 160 }
162 goto out; 161 goto out;
@@ -165,9 +164,13 @@ out_unmap_put:
165 f2fs_dentry_kunmap(dir, page); 164 f2fs_dentry_kunmap(dir, page);
166 f2fs_put_page(page, 0); 165 f2fs_put_page(page, 0);
167out: 166out:
167 if (file_enc_name(inode))
168 name = "<encrypted>";
169 else
170 name = raw_inode->i_name;
168 f2fs_msg(inode->i_sb, KERN_NOTICE, 171 f2fs_msg(inode->i_sb, KERN_NOTICE,
169 "%s: ino = %x, name = %s, dir = %lx, err = %d", 172 "%s: ino = %x, name = %s, dir = %lx, err = %d",
170 __func__, ino_of_node(ipage), raw_inode->i_name, 173 __func__, ino_of_node(ipage), name,
171 IS_ERR(dir) ? 0 : dir->i_ino, err); 174 IS_ERR(dir) ? 0 : dir->i_ino, err);
172 return err; 175 return err;
173} 176}