diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 01:24:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 01:24:40 -0500 |
commit | dd1d1399f2884102172f761816c32aa311bceafb (patch) | |
tree | f3c350bd0a1c43bc61d6aefde32d5d5a8aa22011 | |
parent | a9986464564609dd0962e6023513f7d3d313dc80 (diff) | |
parent | 29e59c14ae5c21d25db1580d9651b5855d656a30 (diff) |
Merge tag 'for-f2fs-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim:
"This patch-set includes the following major enhancement patches.
- add a sysfs to control reclaiming free segments
- enhance the f2fs global lock procedures
- enhance the victim selection flow
- wait for selected node blocks during fsync
- add some tracepoints
- add a config to remove abundant BUG_ONs
The other bug fixes are as follows.
- fix deadlock on acl operations
- fix some bugs with respect to orphan inodes
And, there are a bunch of cleanups"
* tag 'for-f2fs-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (42 commits)
f2fs: issue more large discard command
f2fs: fix memory leak after kobject init failed in fill_super
f2fs: cleanup waiting routine for writeback pages in cp
f2fs: avoid to use a NULL point in destroy_segment_manager
f2fs: remove unnecessary TestClearPageError when wait pages writeback
f2fs: update f2fs document
f2fs: avoid to wait all the node blocks during fsync
f2fs: check all ones or zeros bitmap with bitops for better mount performance
f2fs: change the method of calculating the number summary blocks
f2fs: fix calculating incorrect free size when update xattr in __f2fs_setxattr
f2fs: add an option to avoid unnecessary BUG_ONs
f2fs: introduce CONFIG_F2FS_CHECK_FS for BUG_ON control
f2fs: fix a deadlock during init_acl procedure
f2fs: clean up acl flow for better readability
f2fs: remove unnecessary segment bitmap updates
f2fs: add tracepoint for vm_page_mkwrite
f2fs: add tracepoint for set_page_dirty
f2fs: remove redundant set_page_dirty from write_compacted_summaries
f2fs: add reclaiming control by sysfs
f2fs: introduce f2fs_balance_fs_bg for some background jobs
...
-rw-r--r-- | Documentation/filesystems/f2fs.txt | 7 | ||||
-rw-r--r-- | fs/f2fs/Kconfig | 8 | ||||
-rw-r--r-- | fs/f2fs/acl.c | 36 | ||||
-rw-r--r-- | fs/f2fs/acl.h | 9 | ||||
-rw-r--r-- | fs/f2fs/checkpoint.c | 75 | ||||
-rw-r--r-- | fs/f2fs/data.c | 29 | ||||
-rw-r--r-- | fs/f2fs/dir.c | 4 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 117 | ||||
-rw-r--r-- | fs/f2fs/file.c | 45 | ||||
-rw-r--r-- | fs/f2fs/gc.c | 31 | ||||
-rw-r--r-- | fs/f2fs/inode.c | 62 | ||||
-rw-r--r-- | fs/f2fs/namei.c | 52 | ||||
-rw-r--r-- | fs/f2fs/node.c | 142 | ||||
-rw-r--r-- | fs/f2fs/recovery.c | 45 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 133 | ||||
-rw-r--r-- | fs/f2fs/segment.h | 38 | ||||
-rw-r--r-- | fs/f2fs/super.c | 143 | ||||
-rw-r--r-- | fs/f2fs/xattr.c | 36 | ||||
-rw-r--r-- | include/trace/events/f2fs.h | 51 |
19 files changed, 651 insertions, 412 deletions
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 3cd27bed6349..a3fe811bbdbc 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt | |||
@@ -119,6 +119,7 @@ active_logs=%u Support configuring the number of active logs. In the | |||
119 | Default number is 6. | 119 | Default number is 6. |
120 | disable_ext_identify Disable the extension list configured by mkfs, so f2fs | 120 | disable_ext_identify Disable the extension list configured by mkfs, so f2fs |
121 | does not aware of cold files such as media files. | 121 | does not aware of cold files such as media files. |
122 | inline_xattr Enable the inline xattrs feature. | ||
122 | 123 | ||
123 | ================================================================================ | 124 | ================================================================================ |
124 | DEBUGFS ENTRIES | 125 | DEBUGFS ENTRIES |
@@ -164,6 +165,12 @@ Files in /sys/fs/f2fs/<devname> | |||
164 | gc_idle = 1 will select the Cost Benefit approach | 165 | gc_idle = 1 will select the Cost Benefit approach |
165 | & setting gc_idle = 2 will select the greedy aproach. | 166 | & setting gc_idle = 2 will select the greedy aproach. |
166 | 167 | ||
168 | reclaim_segments This parameter controls the number of prefree | ||
169 | segments to be reclaimed. If the number of prefree | ||
170 | segments is larger than this number, f2fs tries to | ||
171 | conduct checkpoint to reclaim the prefree segments | ||
172 | to free segments. By default, 100 segments, 200MB. | ||
173 | |||
167 | ================================================================================ | 174 | ================================================================================ |
168 | USAGE | 175 | USAGE |
169 | ================================================================================ | 176 | ================================================================================ |
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig index e06e0995e00f..214fe1054fce 100644 --- a/fs/f2fs/Kconfig +++ b/fs/f2fs/Kconfig | |||
@@ -63,3 +63,11 @@ config F2FS_FS_SECURITY | |||
63 | the extended attribute support in advance. | 63 | the extended attribute support in advance. |
64 | 64 | ||
65 | If you are not using a security module, say N. | 65 | If you are not using a security module, say N. |
66 | |||
67 | config F2FS_CHECK_FS | ||
68 | bool "F2FS consistency checking feature" | ||
69 | depends on F2FS_FS | ||
70 | help | ||
71 | Enables BUG_ONs which check the file system consistency in runtime. | ||
72 | |||
73 | If you want to improve the performance, say N. | ||
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index b7826ec1b470..d0fc287efeff 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c | |||
@@ -205,7 +205,8 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type) | |||
205 | return acl; | 205 | return acl; |
206 | } | 206 | } |
207 | 207 | ||
208 | static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | 208 | static int f2fs_set_acl(struct inode *inode, int type, |
209 | struct posix_acl *acl, struct page *ipage) | ||
209 | { | 210 | { |
210 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 211 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
211 | struct f2fs_inode_info *fi = F2FS_I(inode); | 212 | struct f2fs_inode_info *fi = F2FS_I(inode); |
@@ -250,7 +251,7 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
250 | } | 251 | } |
251 | } | 252 | } |
252 | 253 | ||
253 | error = f2fs_setxattr(inode, name_index, "", value, size, NULL); | 254 | error = f2fs_setxattr(inode, name_index, "", value, size, ipage); |
254 | 255 | ||
255 | kfree(value); | 256 | kfree(value); |
256 | if (!error) | 257 | if (!error) |
@@ -260,10 +261,10 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
260 | return error; | 261 | return error; |
261 | } | 262 | } |
262 | 263 | ||
263 | int f2fs_init_acl(struct inode *inode, struct inode *dir) | 264 | int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage) |
264 | { | 265 | { |
265 | struct posix_acl *acl = NULL; | ||
266 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); | 266 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); |
267 | struct posix_acl *acl = NULL; | ||
267 | int error = 0; | 268 | int error = 0; |
268 | 269 | ||
269 | if (!S_ISLNK(inode->i_mode)) { | 270 | if (!S_ISLNK(inode->i_mode)) { |
@@ -276,19 +277,19 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir) | |||
276 | inode->i_mode &= ~current_umask(); | 277 | inode->i_mode &= ~current_umask(); |
277 | } | 278 | } |
278 | 279 | ||
279 | if (test_opt(sbi, POSIX_ACL) && acl) { | 280 | if (!test_opt(sbi, POSIX_ACL) || !acl) |
281 | goto cleanup; | ||
280 | 282 | ||
281 | if (S_ISDIR(inode->i_mode)) { | 283 | if (S_ISDIR(inode->i_mode)) { |
282 | error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl); | 284 | error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl, ipage); |
283 | if (error) | 285 | if (error) |
284 | goto cleanup; | 286 | goto cleanup; |
285 | } | ||
286 | error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode); | ||
287 | if (error < 0) | ||
288 | return error; | ||
289 | if (error > 0) | ||
290 | error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl); | ||
291 | } | 287 | } |
288 | error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode); | ||
289 | if (error < 0) | ||
290 | return error; | ||
291 | if (error > 0) | ||
292 | error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, ipage); | ||
292 | cleanup: | 293 | cleanup: |
293 | posix_acl_release(acl); | 294 | posix_acl_release(acl); |
294 | return error; | 295 | return error; |
@@ -313,7 +314,8 @@ int f2fs_acl_chmod(struct inode *inode) | |||
313 | error = posix_acl_chmod(&acl, GFP_KERNEL, mode); | 314 | error = posix_acl_chmod(&acl, GFP_KERNEL, mode); |
314 | if (error) | 315 | if (error) |
315 | return error; | 316 | return error; |
316 | error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl); | 317 | |
318 | error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, NULL); | ||
317 | posix_acl_release(acl); | 319 | posix_acl_release(acl); |
318 | return error; | 320 | return error; |
319 | } | 321 | } |
@@ -388,7 +390,7 @@ static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name, | |||
388 | acl = NULL; | 390 | acl = NULL; |
389 | } | 391 | } |
390 | 392 | ||
391 | error = f2fs_set_acl(inode, type, acl); | 393 | error = f2fs_set_acl(inode, type, acl, NULL); |
392 | 394 | ||
393 | release_and_out: | 395 | release_and_out: |
394 | posix_acl_release(acl); | 396 | posix_acl_release(acl); |
diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h index 80f430674417..49633131e038 100644 --- a/fs/f2fs/acl.h +++ b/fs/f2fs/acl.h | |||
@@ -36,9 +36,9 @@ struct f2fs_acl_header { | |||
36 | 36 | ||
37 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | 37 | #ifdef CONFIG_F2FS_FS_POSIX_ACL |
38 | 38 | ||
39 | extern struct posix_acl *f2fs_get_acl(struct inode *inode, int type); | 39 | extern struct posix_acl *f2fs_get_acl(struct inode *, int); |
40 | extern int f2fs_acl_chmod(struct inode *inode); | 40 | extern int f2fs_acl_chmod(struct inode *); |
41 | extern int f2fs_init_acl(struct inode *inode, struct inode *dir); | 41 | extern int f2fs_init_acl(struct inode *, struct inode *, struct page *); |
42 | #else | 42 | #else |
43 | #define f2fs_check_acl NULL | 43 | #define f2fs_check_acl NULL |
44 | #define f2fs_get_acl NULL | 44 | #define f2fs_get_acl NULL |
@@ -49,7 +49,8 @@ static inline int f2fs_acl_chmod(struct inode *inode) | |||
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
52 | static inline int f2fs_init_acl(struct inode *inode, struct inode *dir) | 52 | static inline int f2fs_init_acl(struct inode *inode, struct inode *dir, |
53 | struct page *page) | ||
53 | { | 54 | { |
54 | return 0; | 55 | return 0; |
55 | } | 56 | } |
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index bb312201ca95..5716e5eb4e8e 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -81,7 +81,7 @@ static int f2fs_write_meta_page(struct page *page, | |||
81 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 81 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
82 | 82 | ||
83 | /* Should not write any meta pages, if any IO error was occurred */ | 83 | /* Should not write any meta pages, if any IO error was occurred */ |
84 | if (wbc->for_reclaim || | 84 | if (wbc->for_reclaim || sbi->por_doing || |
85 | is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)) { | 85 | is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)) { |
86 | dec_page_count(sbi, F2FS_DIRTY_META); | 86 | dec_page_count(sbi, F2FS_DIRTY_META); |
87 | wbc->pages_skipped++; | 87 | wbc->pages_skipped++; |
@@ -142,8 +142,8 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, | |||
142 | for (i = 0; i < nr_pages; i++) { | 142 | for (i = 0; i < nr_pages; i++) { |
143 | struct page *page = pvec.pages[i]; | 143 | struct page *page = pvec.pages[i]; |
144 | lock_page(page); | 144 | lock_page(page); |
145 | BUG_ON(page->mapping != mapping); | 145 | f2fs_bug_on(page->mapping != mapping); |
146 | BUG_ON(!PageDirty(page)); | 146 | f2fs_bug_on(!PageDirty(page)); |
147 | clear_page_dirty_for_io(page); | 147 | clear_page_dirty_for_io(page); |
148 | if (f2fs_write_meta_page(page, &wbc)) { | 148 | if (f2fs_write_meta_page(page, &wbc)) { |
149 | unlock_page(page); | 149 | unlock_page(page); |
@@ -167,6 +167,8 @@ static int f2fs_set_meta_page_dirty(struct page *page) | |||
167 | struct address_space *mapping = page->mapping; | 167 | struct address_space *mapping = page->mapping; |
168 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); | 168 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); |
169 | 169 | ||
170 | trace_f2fs_set_page_dirty(page, META); | ||
171 | |||
170 | SetPageUptodate(page); | 172 | SetPageUptodate(page); |
171 | if (!PageDirty(page)) { | 173 | if (!PageDirty(page)) { |
172 | __set_page_dirty_nobuffers(page); | 174 | __set_page_dirty_nobuffers(page); |
@@ -206,6 +208,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi) | |||
206 | void release_orphan_inode(struct f2fs_sb_info *sbi) | 208 | void release_orphan_inode(struct f2fs_sb_info *sbi) |
207 | { | 209 | { |
208 | mutex_lock(&sbi->orphan_inode_mutex); | 210 | mutex_lock(&sbi->orphan_inode_mutex); |
211 | f2fs_bug_on(sbi->n_orphans == 0); | ||
209 | sbi->n_orphans--; | 212 | sbi->n_orphans--; |
210 | mutex_unlock(&sbi->orphan_inode_mutex); | 213 | mutex_unlock(&sbi->orphan_inode_mutex); |
211 | } | 214 | } |
@@ -225,12 +228,8 @@ void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | |||
225 | break; | 228 | break; |
226 | orphan = NULL; | 229 | orphan = NULL; |
227 | } | 230 | } |
228 | retry: | 231 | |
229 | new = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC); | 232 | new = f2fs_kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC); |
230 | if (!new) { | ||
231 | cond_resched(); | ||
232 | goto retry; | ||
233 | } | ||
234 | new->ino = ino; | 233 | new->ino = ino; |
235 | 234 | ||
236 | /* add new_oentry into list which is sorted by inode number */ | 235 | /* add new_oentry into list which is sorted by inode number */ |
@@ -253,6 +252,7 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | |||
253 | if (orphan->ino == ino) { | 252 | if (orphan->ino == ino) { |
254 | list_del(&orphan->list); | 253 | list_del(&orphan->list); |
255 | kmem_cache_free(orphan_entry_slab, orphan); | 254 | kmem_cache_free(orphan_entry_slab, orphan); |
255 | f2fs_bug_on(sbi->n_orphans == 0); | ||
256 | sbi->n_orphans--; | 256 | sbi->n_orphans--; |
257 | break; | 257 | break; |
258 | } | 258 | } |
@@ -263,7 +263,7 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | |||
263 | static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 263 | static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
264 | { | 264 | { |
265 | struct inode *inode = f2fs_iget(sbi->sb, ino); | 265 | struct inode *inode = f2fs_iget(sbi->sb, ino); |
266 | BUG_ON(IS_ERR(inode)); | 266 | f2fs_bug_on(IS_ERR(inode)); |
267 | clear_nlink(inode); | 267 | clear_nlink(inode); |
268 | 268 | ||
269 | /* truncate all the data during iput */ | 269 | /* truncate all the data during iput */ |
@@ -277,7 +277,7 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi) | |||
277 | if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG)) | 277 | if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG)) |
278 | return 0; | 278 | return 0; |
279 | 279 | ||
280 | sbi->por_doing = 1; | 280 | sbi->por_doing = true; |
281 | start_blk = __start_cp_addr(sbi) + 1; | 281 | start_blk = __start_cp_addr(sbi) + 1; |
282 | orphan_blkaddr = __start_sum_addr(sbi) - 1; | 282 | orphan_blkaddr = __start_sum_addr(sbi) - 1; |
283 | 283 | ||
@@ -294,7 +294,7 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi) | |||
294 | } | 294 | } |
295 | /* clear Orphan Flag */ | 295 | /* clear Orphan Flag */ |
296 | clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG); | 296 | clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG); |
297 | sbi->por_doing = 0; | 297 | sbi->por_doing = false; |
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
@@ -469,9 +469,7 @@ static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new) | |||
469 | return -EEXIST; | 469 | return -EEXIST; |
470 | } | 470 | } |
471 | list_add_tail(&new->list, head); | 471 | list_add_tail(&new->list, head); |
472 | #ifdef CONFIG_F2FS_STAT_FS | 472 | stat_inc_dirty_dir(sbi); |
473 | sbi->n_dirty_dirs++; | ||
474 | #endif | ||
475 | return 0; | 473 | return 0; |
476 | } | 474 | } |
477 | 475 | ||
@@ -482,12 +480,8 @@ void set_dirty_dir_page(struct inode *inode, struct page *page) | |||
482 | 480 | ||
483 | if (!S_ISDIR(inode->i_mode)) | 481 | if (!S_ISDIR(inode->i_mode)) |
484 | return; | 482 | return; |
485 | retry: | 483 | |
486 | new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS); | 484 | new = f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); |
487 | if (!new) { | ||
488 | cond_resched(); | ||
489 | goto retry; | ||
490 | } | ||
491 | new->inode = inode; | 485 | new->inode = inode; |
492 | INIT_LIST_HEAD(&new->list); | 486 | INIT_LIST_HEAD(&new->list); |
493 | 487 | ||
@@ -504,13 +498,9 @@ retry: | |||
504 | void add_dirty_dir_inode(struct inode *inode) | 498 | void add_dirty_dir_inode(struct inode *inode) |
505 | { | 499 | { |
506 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 500 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
507 | struct dir_inode_entry *new; | 501 | struct dir_inode_entry *new = |
508 | retry: | 502 | f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); |
509 | new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS); | 503 | |
510 | if (!new) { | ||
511 | cond_resched(); | ||
512 | goto retry; | ||
513 | } | ||
514 | new->inode = inode; | 504 | new->inode = inode; |
515 | INIT_LIST_HEAD(&new->list); | 505 | INIT_LIST_HEAD(&new->list); |
516 | 506 | ||
@@ -541,9 +531,7 @@ void remove_dirty_dir_inode(struct inode *inode) | |||
541 | if (entry->inode == inode) { | 531 | if (entry->inode == inode) { |
542 | list_del(&entry->list); | 532 | list_del(&entry->list); |
543 | kmem_cache_free(inode_entry_slab, entry); | 533 | kmem_cache_free(inode_entry_slab, entry); |
544 | #ifdef CONFIG_F2FS_STAT_FS | 534 | stat_dec_dirty_dir(sbi); |
545 | sbi->n_dirty_dirs--; | ||
546 | #endif | ||
547 | break; | 535 | break; |
548 | } | 536 | } |
549 | } | 537 | } |
@@ -617,11 +605,10 @@ static void block_operations(struct f2fs_sb_info *sbi) | |||
617 | blk_start_plug(&plug); | 605 | blk_start_plug(&plug); |
618 | 606 | ||
619 | retry_flush_dents: | 607 | retry_flush_dents: |
620 | mutex_lock_all(sbi); | 608 | f2fs_lock_all(sbi); |
621 | |||
622 | /* write all the dirty dentry pages */ | 609 | /* write all the dirty dentry pages */ |
623 | if (get_pages(sbi, F2FS_DIRTY_DENTS)) { | 610 | if (get_pages(sbi, F2FS_DIRTY_DENTS)) { |
624 | mutex_unlock_all(sbi); | 611 | f2fs_unlock_all(sbi); |
625 | sync_dirty_dir_inodes(sbi); | 612 | sync_dirty_dir_inodes(sbi); |
626 | goto retry_flush_dents; | 613 | goto retry_flush_dents; |
627 | } | 614 | } |
@@ -644,7 +631,22 @@ retry_flush_nodes: | |||
644 | static void unblock_operations(struct f2fs_sb_info *sbi) | 631 | static void unblock_operations(struct f2fs_sb_info *sbi) |
645 | { | 632 | { |
646 | mutex_unlock(&sbi->node_write); | 633 | mutex_unlock(&sbi->node_write); |
647 | mutex_unlock_all(sbi); | 634 | f2fs_unlock_all(sbi); |
635 | } | ||
636 | |||
637 | static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi) | ||
638 | { | ||
639 | DEFINE_WAIT(wait); | ||
640 | |||
641 | for (;;) { | ||
642 | prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); | ||
643 | |||
644 | if (!get_pages(sbi, F2FS_WRITEBACK)) | ||
645 | break; | ||
646 | |||
647 | io_schedule(); | ||
648 | } | ||
649 | finish_wait(&sbi->cp_wait, &wait); | ||
648 | } | 650 | } |
649 | 651 | ||
650 | static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | 652 | static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) |
@@ -756,8 +758,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
756 | f2fs_put_page(cp_page, 1); | 758 | f2fs_put_page(cp_page, 1); |
757 | 759 | ||
758 | /* wait for previous submitted node/meta pages writeback */ | 760 | /* wait for previous submitted node/meta pages writeback */ |
759 | while (get_pages(sbi, F2FS_WRITEBACK)) | 761 | wait_on_all_pages_writeback(sbi); |
760 | congestion_wait(BLK_RW_ASYNC, HZ / 50); | ||
761 | 762 | ||
762 | filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX); | 763 | filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX); |
763 | filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX); | 764 | filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX); |
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 941f9b9ca3a5..aa3438c571fa 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -68,9 +68,6 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, | |||
68 | struct buffer_head *bh_result) | 68 | struct buffer_head *bh_result) |
69 | { | 69 | { |
70 | struct f2fs_inode_info *fi = F2FS_I(inode); | 70 | struct f2fs_inode_info *fi = F2FS_I(inode); |
71 | #ifdef CONFIG_F2FS_STAT_FS | ||
72 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
73 | #endif | ||
74 | pgoff_t start_fofs, end_fofs; | 71 | pgoff_t start_fofs, end_fofs; |
75 | block_t start_blkaddr; | 72 | block_t start_blkaddr; |
76 | 73 | ||
@@ -80,9 +77,8 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, | |||
80 | return 0; | 77 | return 0; |
81 | } | 78 | } |
82 | 79 | ||
83 | #ifdef CONFIG_F2FS_STAT_FS | 80 | stat_inc_total_hit(inode->i_sb); |
84 | sbi->total_hit_ext++; | 81 | |
85 | #endif | ||
86 | start_fofs = fi->ext.fofs; | 82 | start_fofs = fi->ext.fofs; |
87 | end_fofs = fi->ext.fofs + fi->ext.len - 1; | 83 | end_fofs = fi->ext.fofs + fi->ext.len - 1; |
88 | start_blkaddr = fi->ext.blk_addr; | 84 | start_blkaddr = fi->ext.blk_addr; |
@@ -100,9 +96,7 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, | |||
100 | else | 96 | else |
101 | bh_result->b_size = UINT_MAX; | 97 | bh_result->b_size = UINT_MAX; |
102 | 98 | ||
103 | #ifdef CONFIG_F2FS_STAT_FS | 99 | stat_inc_read_hit(inode->i_sb); |
104 | sbi->read_hit_ext++; | ||
105 | #endif | ||
106 | read_unlock(&fi->ext.ext_lock); | 100 | read_unlock(&fi->ext.ext_lock); |
107 | return 1; | 101 | return 1; |
108 | } | 102 | } |
@@ -116,7 +110,7 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn) | |||
116 | pgoff_t fofs, start_fofs, end_fofs; | 110 | pgoff_t fofs, start_fofs, end_fofs; |
117 | block_t start_blkaddr, end_blkaddr; | 111 | block_t start_blkaddr, end_blkaddr; |
118 | 112 | ||
119 | BUG_ON(blk_addr == NEW_ADDR); | 113 | f2fs_bug_on(blk_addr == NEW_ADDR); |
120 | fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) + | 114 | fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) + |
121 | dn->ofs_in_node; | 115 | dn->ofs_in_node; |
122 | 116 | ||
@@ -442,7 +436,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock, | |||
442 | } | 436 | } |
443 | 437 | ||
444 | /* It does not support data allocation */ | 438 | /* It does not support data allocation */ |
445 | BUG_ON(create); | 439 | f2fs_bug_on(create); |
446 | 440 | ||
447 | if (dn.data_blkaddr != NEW_ADDR && dn.data_blkaddr != NULL_ADDR) { | 441 | if (dn.data_blkaddr != NEW_ADDR && dn.data_blkaddr != NULL_ADDR) { |
448 | int i; | 442 | int i; |
@@ -560,9 +554,9 @@ write: | |||
560 | inode_dec_dirty_dents(inode); | 554 | inode_dec_dirty_dents(inode); |
561 | err = do_write_data_page(page); | 555 | err = do_write_data_page(page); |
562 | } else { | 556 | } else { |
563 | int ilock = mutex_lock_op(sbi); | 557 | f2fs_lock_op(sbi); |
564 | err = do_write_data_page(page); | 558 | err = do_write_data_page(page); |
565 | mutex_unlock_op(sbi, ilock); | 559 | f2fs_unlock_op(sbi); |
566 | need_balance_fs = true; | 560 | need_balance_fs = true; |
567 | } | 561 | } |
568 | if (err == -ENOENT) | 562 | if (err == -ENOENT) |
@@ -641,7 +635,6 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, | |||
641 | pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT; | 635 | pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT; |
642 | struct dnode_of_data dn; | 636 | struct dnode_of_data dn; |
643 | int err = 0; | 637 | int err = 0; |
644 | int ilock; | ||
645 | 638 | ||
646 | f2fs_balance_fs(sbi); | 639 | f2fs_balance_fs(sbi); |
647 | repeat: | 640 | repeat: |
@@ -650,7 +643,7 @@ repeat: | |||
650 | return -ENOMEM; | 643 | return -ENOMEM; |
651 | *pagep = page; | 644 | *pagep = page; |
652 | 645 | ||
653 | ilock = mutex_lock_op(sbi); | 646 | f2fs_lock_op(sbi); |
654 | 647 | ||
655 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 648 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
656 | err = get_dnode_of_data(&dn, index, ALLOC_NODE); | 649 | err = get_dnode_of_data(&dn, index, ALLOC_NODE); |
@@ -664,7 +657,7 @@ repeat: | |||
664 | if (err) | 657 | if (err) |
665 | goto err; | 658 | goto err; |
666 | 659 | ||
667 | mutex_unlock_op(sbi, ilock); | 660 | f2fs_unlock_op(sbi); |
668 | 661 | ||
669 | if ((len == PAGE_CACHE_SIZE) || PageUptodate(page)) | 662 | if ((len == PAGE_CACHE_SIZE) || PageUptodate(page)) |
670 | return 0; | 663 | return 0; |
@@ -700,7 +693,7 @@ out: | |||
700 | return 0; | 693 | return 0; |
701 | 694 | ||
702 | err: | 695 | err: |
703 | mutex_unlock_op(sbi, ilock); | 696 | f2fs_unlock_op(sbi); |
704 | f2fs_put_page(page, 1); | 697 | f2fs_put_page(page, 1); |
705 | return err; | 698 | return err; |
706 | } | 699 | } |
@@ -763,6 +756,8 @@ static int f2fs_set_data_page_dirty(struct page *page) | |||
763 | struct address_space *mapping = page->mapping; | 756 | struct address_space *mapping = page->mapping; |
764 | struct inode *inode = mapping->host; | 757 | struct inode *inode = mapping->host; |
765 | 758 | ||
759 | trace_f2fs_set_page_dirty(page, DATA); | ||
760 | |||
766 | SetPageUptodate(page); | 761 | SetPageUptodate(page); |
767 | if (!PageDirty(page)) { | 762 | if (!PageDirty(page)) { |
768 | __set_page_dirty_nobuffers(page); | 763 | __set_page_dirty_nobuffers(page); |
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 384c6daf9a89..594fc1bb64ef 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -139,7 +139,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir, | |||
139 | bool room = false; | 139 | bool room = false; |
140 | int max_slots = 0; | 140 | int max_slots = 0; |
141 | 141 | ||
142 | BUG_ON(level > MAX_DIR_HASH_DEPTH); | 142 | f2fs_bug_on(level > MAX_DIR_HASH_DEPTH); |
143 | 143 | ||
144 | nbucket = dir_buckets(level); | 144 | nbucket = dir_buckets(level); |
145 | nblock = bucket_blocks(level); | 145 | nblock = bucket_blocks(level); |
@@ -346,7 +346,7 @@ static struct page *init_inode_metadata(struct inode *inode, | |||
346 | goto error; | 346 | goto error; |
347 | } | 347 | } |
348 | 348 | ||
349 | err = f2fs_init_acl(inode, dir); | 349 | err = f2fs_init_acl(inode, dir, page); |
350 | if (err) | 350 | if (err) |
351 | goto error; | 351 | goto error; |
352 | 352 | ||
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 608f0df5b919..89dc7508faf2 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -18,6 +18,13 @@ | |||
18 | #include <linux/crc32.h> | 18 | #include <linux/crc32.h> |
19 | #include <linux/magic.h> | 19 | #include <linux/magic.h> |
20 | #include <linux/kobject.h> | 20 | #include <linux/kobject.h> |
21 | #include <linux/sched.h> | ||
22 | |||
23 | #ifdef CONFIG_F2FS_CHECK_FS | ||
24 | #define f2fs_bug_on(condition) BUG_ON(condition) | ||
25 | #else | ||
26 | #define f2fs_bug_on(condition) | ||
27 | #endif | ||
21 | 28 | ||
22 | /* | 29 | /* |
23 | * For mount options | 30 | * For mount options |
@@ -298,6 +305,9 @@ struct f2fs_sm_info { | |||
298 | unsigned int main_segments; /* # of segments in main area */ | 305 | unsigned int main_segments; /* # of segments in main area */ |
299 | unsigned int reserved_segments; /* # of reserved segments */ | 306 | unsigned int reserved_segments; /* # of reserved segments */ |
300 | unsigned int ovp_segments; /* # of overprovision segments */ | 307 | unsigned int ovp_segments; /* # of overprovision segments */ |
308 | |||
309 | /* a threshold to reclaim prefree segments */ | ||
310 | unsigned int rec_prefree_segments; | ||
301 | }; | 311 | }; |
302 | 312 | ||
303 | /* | 313 | /* |
@@ -318,14 +328,6 @@ enum count_type { | |||
318 | }; | 328 | }; |
319 | 329 | ||
320 | /* | 330 | /* |
321 | * Uses as sbi->fs_lock[NR_GLOBAL_LOCKS]. | ||
322 | * The checkpoint procedure blocks all the locks in this fs_lock array. | ||
323 | * Some FS operations grab free locks, and if there is no free lock, | ||
324 | * then wait to grab a lock in a round-robin manner. | ||
325 | */ | ||
326 | #define NR_GLOBAL_LOCKS 8 | ||
327 | |||
328 | /* | ||
329 | * The below are the page types of bios used in submti_bio(). | 331 | * The below are the page types of bios used in submti_bio(). |
330 | * The available types are: | 332 | * The available types are: |
331 | * DATA User data pages. It operates as async mode. | 333 | * DATA User data pages. It operates as async mode. |
@@ -365,12 +367,12 @@ struct f2fs_sb_info { | |||
365 | struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */ | 367 | struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */ |
366 | struct inode *meta_inode; /* cache meta blocks */ | 368 | struct inode *meta_inode; /* cache meta blocks */ |
367 | struct mutex cp_mutex; /* checkpoint procedure lock */ | 369 | struct mutex cp_mutex; /* checkpoint procedure lock */ |
368 | struct mutex fs_lock[NR_GLOBAL_LOCKS]; /* blocking FS operations */ | 370 | struct rw_semaphore cp_rwsem; /* blocking FS operations */ |
369 | struct mutex node_write; /* locking node writes */ | 371 | struct mutex node_write; /* locking node writes */ |
370 | struct mutex writepages; /* mutex for writepages() */ | 372 | struct mutex writepages; /* mutex for writepages() */ |
371 | unsigned char next_lock_num; /* round-robin global locks */ | 373 | bool por_doing; /* recovery is doing or not */ |
372 | int por_doing; /* recovery is doing or not */ | 374 | bool on_build_free_nids; /* build_free_nids is doing */ |
373 | int on_build_free_nids; /* build_free_nids is doing */ | 375 | wait_queue_head_t cp_wait; |
374 | 376 | ||
375 | /* for orphan inode management */ | 377 | /* for orphan inode management */ |
376 | struct list_head orphan_inode_list; /* orphan inode list */ | 378 | struct list_head orphan_inode_list; /* orphan inode list */ |
@@ -520,48 +522,24 @@ static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f) | |||
520 | cp->ckpt_flags = cpu_to_le32(ckpt_flags); | 522 | cp->ckpt_flags = cpu_to_le32(ckpt_flags); |
521 | } | 523 | } |
522 | 524 | ||
523 | static inline void mutex_lock_all(struct f2fs_sb_info *sbi) | 525 | static inline void f2fs_lock_op(struct f2fs_sb_info *sbi) |
524 | { | 526 | { |
525 | int i; | 527 | down_read(&sbi->cp_rwsem); |
526 | |||
527 | for (i = 0; i < NR_GLOBAL_LOCKS; i++) { | ||
528 | /* | ||
529 | * This is the only time we take multiple fs_lock[] | ||
530 | * instances; the order is immaterial since we | ||
531 | * always hold cp_mutex, which serializes multiple | ||
532 | * such operations. | ||
533 | */ | ||
534 | mutex_lock_nest_lock(&sbi->fs_lock[i], &sbi->cp_mutex); | ||
535 | } | ||
536 | } | 528 | } |
537 | 529 | ||
538 | static inline void mutex_unlock_all(struct f2fs_sb_info *sbi) | 530 | static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi) |
539 | { | 531 | { |
540 | int i = 0; | 532 | up_read(&sbi->cp_rwsem); |
541 | for (; i < NR_GLOBAL_LOCKS; i++) | ||
542 | mutex_unlock(&sbi->fs_lock[i]); | ||
543 | } | 533 | } |
544 | 534 | ||
545 | static inline int mutex_lock_op(struct f2fs_sb_info *sbi) | 535 | static inline void f2fs_lock_all(struct f2fs_sb_info *sbi) |
546 | { | 536 | { |
547 | unsigned char next_lock = sbi->next_lock_num % NR_GLOBAL_LOCKS; | 537 | down_write_nest_lock(&sbi->cp_rwsem, &sbi->cp_mutex); |
548 | int i = 0; | ||
549 | |||
550 | for (; i < NR_GLOBAL_LOCKS; i++) | ||
551 | if (mutex_trylock(&sbi->fs_lock[i])) | ||
552 | return i; | ||
553 | |||
554 | mutex_lock(&sbi->fs_lock[next_lock]); | ||
555 | sbi->next_lock_num++; | ||
556 | return next_lock; | ||
557 | } | 538 | } |
558 | 539 | ||
559 | static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, int ilock) | 540 | static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi) |
560 | { | 541 | { |
561 | if (ilock < 0) | 542 | up_write(&sbi->cp_rwsem); |
562 | return; | ||
563 | BUG_ON(ilock >= NR_GLOBAL_LOCKS); | ||
564 | mutex_unlock(&sbi->fs_lock[ilock]); | ||
565 | } | 543 | } |
566 | 544 | ||
567 | /* | 545 | /* |
@@ -612,8 +590,8 @@ static inline int dec_valid_block_count(struct f2fs_sb_info *sbi, | |||
612 | blkcnt_t count) | 590 | blkcnt_t count) |
613 | { | 591 | { |
614 | spin_lock(&sbi->stat_lock); | 592 | spin_lock(&sbi->stat_lock); |
615 | BUG_ON(sbi->total_valid_block_count < (block_t) count); | 593 | f2fs_bug_on(sbi->total_valid_block_count < (block_t) count); |
616 | BUG_ON(inode->i_blocks < count); | 594 | f2fs_bug_on(inode->i_blocks < count); |
617 | inode->i_blocks -= count; | 595 | inode->i_blocks -= count; |
618 | sbi->total_valid_block_count -= (block_t)count; | 596 | sbi->total_valid_block_count -= (block_t)count; |
619 | spin_unlock(&sbi->stat_lock); | 597 | spin_unlock(&sbi->stat_lock); |
@@ -745,9 +723,9 @@ static inline void dec_valid_node_count(struct f2fs_sb_info *sbi, | |||
745 | { | 723 | { |
746 | spin_lock(&sbi->stat_lock); | 724 | spin_lock(&sbi->stat_lock); |
747 | 725 | ||
748 | BUG_ON(sbi->total_valid_block_count < count); | 726 | f2fs_bug_on(sbi->total_valid_block_count < count); |
749 | BUG_ON(sbi->total_valid_node_count < count); | 727 | f2fs_bug_on(sbi->total_valid_node_count < count); |
750 | BUG_ON(inode->i_blocks < count); | 728 | f2fs_bug_on(inode->i_blocks < count); |
751 | 729 | ||
752 | inode->i_blocks -= count; | 730 | inode->i_blocks -= count; |
753 | sbi->total_valid_node_count -= count; | 731 | sbi->total_valid_node_count -= count; |
@@ -768,7 +746,7 @@ static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi) | |||
768 | static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi) | 746 | static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi) |
769 | { | 747 | { |
770 | spin_lock(&sbi->stat_lock); | 748 | spin_lock(&sbi->stat_lock); |
771 | BUG_ON(sbi->total_valid_inode_count == sbi->total_node_count); | 749 | f2fs_bug_on(sbi->total_valid_inode_count == sbi->total_node_count); |
772 | sbi->total_valid_inode_count++; | 750 | sbi->total_valid_inode_count++; |
773 | spin_unlock(&sbi->stat_lock); | 751 | spin_unlock(&sbi->stat_lock); |
774 | } | 752 | } |
@@ -776,7 +754,7 @@ static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi) | |||
776 | static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi) | 754 | static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi) |
777 | { | 755 | { |
778 | spin_lock(&sbi->stat_lock); | 756 | spin_lock(&sbi->stat_lock); |
779 | BUG_ON(!sbi->total_valid_inode_count); | 757 | f2fs_bug_on(!sbi->total_valid_inode_count); |
780 | sbi->total_valid_inode_count--; | 758 | sbi->total_valid_inode_count--; |
781 | spin_unlock(&sbi->stat_lock); | 759 | spin_unlock(&sbi->stat_lock); |
782 | return 0; | 760 | return 0; |
@@ -797,7 +775,7 @@ static inline void f2fs_put_page(struct page *page, int unlock) | |||
797 | return; | 775 | return; |
798 | 776 | ||
799 | if (unlock) { | 777 | if (unlock) { |
800 | BUG_ON(!PageLocked(page)); | 778 | f2fs_bug_on(!PageLocked(page)); |
801 | unlock_page(page); | 779 | unlock_page(page); |
802 | } | 780 | } |
803 | page_cache_release(page); | 781 | page_cache_release(page); |
@@ -819,6 +797,20 @@ static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name, | |||
819 | return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, ctor); | 797 | return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, ctor); |
820 | } | 798 | } |
821 | 799 | ||
800 | static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep, | ||
801 | gfp_t flags) | ||
802 | { | ||
803 | void *entry; | ||
804 | retry: | ||
805 | entry = kmem_cache_alloc(cachep, flags); | ||
806 | if (!entry) { | ||
807 | cond_resched(); | ||
808 | goto retry; | ||
809 | } | ||
810 | |||
811 | return entry; | ||
812 | } | ||
813 | |||
822 | #define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino) | 814 | #define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino) |
823 | 815 | ||
824 | static inline bool IS_INODE(struct page *page) | 816 | static inline bool IS_INODE(struct page *page) |
@@ -979,6 +971,7 @@ long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long); | |||
979 | */ | 971 | */ |
980 | void f2fs_set_inode_flags(struct inode *); | 972 | void f2fs_set_inode_flags(struct inode *); |
981 | struct inode *f2fs_iget(struct super_block *, unsigned long); | 973 | struct inode *f2fs_iget(struct super_block *, unsigned long); |
974 | int try_to_free_nats(struct f2fs_sb_info *, int); | ||
982 | void update_inode(struct inode *, struct page *); | 975 | void update_inode(struct inode *, struct page *); |
983 | int update_inode_page(struct inode *); | 976 | int update_inode_page(struct inode *); |
984 | int f2fs_write_inode(struct inode *, struct writeback_control *); | 977 | int f2fs_write_inode(struct inode *, struct writeback_control *); |
@@ -1033,6 +1026,7 @@ void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); | |||
1033 | int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); | 1026 | int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); |
1034 | int truncate_inode_blocks(struct inode *, pgoff_t); | 1027 | int truncate_inode_blocks(struct inode *, pgoff_t); |
1035 | int truncate_xattr_node(struct inode *, struct page *); | 1028 | int truncate_xattr_node(struct inode *, struct page *); |
1029 | int wait_on_node_pages_writeback(struct f2fs_sb_info *, nid_t); | ||
1036 | int remove_inode_page(struct inode *); | 1030 | int remove_inode_page(struct inode *); |
1037 | struct page *new_inode_page(struct inode *, const struct qstr *); | 1031 | struct page *new_inode_page(struct inode *, const struct qstr *); |
1038 | struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *); | 1032 | struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *); |
@@ -1059,6 +1053,7 @@ void destroy_node_manager_caches(void); | |||
1059 | * segment.c | 1053 | * segment.c |
1060 | */ | 1054 | */ |
1061 | void f2fs_balance_fs(struct f2fs_sb_info *); | 1055 | void f2fs_balance_fs(struct f2fs_sb_info *); |
1056 | void f2fs_balance_fs_bg(struct f2fs_sb_info *); | ||
1062 | void invalidate_blocks(struct f2fs_sb_info *, block_t); | 1057 | void invalidate_blocks(struct f2fs_sb_info *, block_t); |
1063 | void clear_prefree_segments(struct f2fs_sb_info *); | 1058 | void clear_prefree_segments(struct f2fs_sb_info *); |
1064 | int npages_for_summary_flush(struct f2fs_sb_info *); | 1059 | int npages_for_summary_flush(struct f2fs_sb_info *); |
@@ -1172,7 +1167,16 @@ static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi) | |||
1172 | return (struct f2fs_stat_info*)sbi->stat_info; | 1167 | return (struct f2fs_stat_info*)sbi->stat_info; |
1173 | } | 1168 | } |
1174 | 1169 | ||
1175 | #define stat_inc_call_count(si) ((si)->call_count++) | 1170 | #define stat_inc_call_count(si) ((si)->call_count++) |
1171 | #define stat_inc_bggc_count(sbi) ((sbi)->bg_gc++) | ||
1172 | #define stat_inc_dirty_dir(sbi) ((sbi)->n_dirty_dirs++) | ||
1173 | #define stat_dec_dirty_dir(sbi) ((sbi)->n_dirty_dirs--) | ||
1174 | #define stat_inc_total_hit(sb) ((F2FS_SB(sb))->total_hit_ext++) | ||
1175 | #define stat_inc_read_hit(sb) ((F2FS_SB(sb))->read_hit_ext++) | ||
1176 | #define stat_inc_seg_type(sbi, curseg) \ | ||
1177 | ((sbi)->segment_count[(curseg)->alloc_type]++) | ||
1178 | #define stat_inc_block_count(sbi, curseg) \ | ||
1179 | ((sbi)->block_count[(curseg)->alloc_type]++) | ||
1176 | 1180 | ||
1177 | #define stat_inc_seg_count(sbi, type) \ | 1181 | #define stat_inc_seg_count(sbi, type) \ |
1178 | do { \ | 1182 | do { \ |
@@ -1207,6 +1211,13 @@ void __init f2fs_create_root_stats(void); | |||
1207 | void f2fs_destroy_root_stats(void); | 1211 | void f2fs_destroy_root_stats(void); |
1208 | #else | 1212 | #else |
1209 | #define stat_inc_call_count(si) | 1213 | #define stat_inc_call_count(si) |
1214 | #define stat_inc_bggc_count(si) | ||
1215 | #define stat_inc_dirty_dir(sbi) | ||
1216 | #define stat_dec_dirty_dir(sbi) | ||
1217 | #define stat_inc_total_hit(sb) | ||
1218 | #define stat_inc_read_hit(sb) | ||
1219 | #define stat_inc_seg_type(sbi, curseg) | ||
1220 | #define stat_inc_block_count(sbi, curseg) | ||
1210 | #define stat_inc_seg_count(si, type) | 1221 | #define stat_inc_seg_count(si, type) |
1211 | #define stat_inc_tot_blk_count(si, blks) | 1222 | #define stat_inc_tot_blk_count(si, blks) |
1212 | #define stat_inc_data_blk_count(si, blks) | 1223 | #define stat_inc_data_blk_count(si, blks) |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 02c906971cc6..7d714f4972d5 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -35,18 +35,18 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
35 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 35 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
36 | block_t old_blk_addr; | 36 | block_t old_blk_addr; |
37 | struct dnode_of_data dn; | 37 | struct dnode_of_data dn; |
38 | int err, ilock; | 38 | int err; |
39 | 39 | ||
40 | f2fs_balance_fs(sbi); | 40 | f2fs_balance_fs(sbi); |
41 | 41 | ||
42 | sb_start_pagefault(inode->i_sb); | 42 | sb_start_pagefault(inode->i_sb); |
43 | 43 | ||
44 | /* block allocation */ | 44 | /* block allocation */ |
45 | ilock = mutex_lock_op(sbi); | 45 | f2fs_lock_op(sbi); |
46 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 46 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
47 | err = get_dnode_of_data(&dn, page->index, ALLOC_NODE); | 47 | err = get_dnode_of_data(&dn, page->index, ALLOC_NODE); |
48 | if (err) { | 48 | if (err) { |
49 | mutex_unlock_op(sbi, ilock); | 49 | f2fs_unlock_op(sbi); |
50 | goto out; | 50 | goto out; |
51 | } | 51 | } |
52 | 52 | ||
@@ -56,12 +56,12 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
56 | err = reserve_new_block(&dn); | 56 | err = reserve_new_block(&dn); |
57 | if (err) { | 57 | if (err) { |
58 | f2fs_put_dnode(&dn); | 58 | f2fs_put_dnode(&dn); |
59 | mutex_unlock_op(sbi, ilock); | 59 | f2fs_unlock_op(sbi); |
60 | goto out; | 60 | goto out; |
61 | } | 61 | } |
62 | } | 62 | } |
63 | f2fs_put_dnode(&dn); | 63 | f2fs_put_dnode(&dn); |
64 | mutex_unlock_op(sbi, ilock); | 64 | f2fs_unlock_op(sbi); |
65 | 65 | ||
66 | file_update_time(vma->vm_file); | 66 | file_update_time(vma->vm_file); |
67 | lock_page(page); | 67 | lock_page(page); |
@@ -88,6 +88,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
88 | set_page_dirty(page); | 88 | set_page_dirty(page); |
89 | SetPageUptodate(page); | 89 | SetPageUptodate(page); |
90 | 90 | ||
91 | trace_f2fs_vm_page_mkwrite(page, DATA); | ||
91 | mapped: | 92 | mapped: |
92 | /* fill the page */ | 93 | /* fill the page */ |
93 | wait_on_page_writeback(page); | 94 | wait_on_page_writeback(page); |
@@ -188,8 +189,9 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
188 | if (ret) | 189 | if (ret) |
189 | goto out; | 190 | goto out; |
190 | } | 191 | } |
191 | filemap_fdatawait_range(sbi->node_inode->i_mapping, | 192 | ret = wait_on_node_pages_writeback(sbi, inode->i_ino); |
192 | 0, LONG_MAX); | 193 | if (ret) |
194 | goto out; | ||
193 | ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); | 195 | ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); |
194 | } | 196 | } |
195 | out: | 197 | out: |
@@ -270,7 +272,7 @@ static int truncate_blocks(struct inode *inode, u64 from) | |||
270 | unsigned int blocksize = inode->i_sb->s_blocksize; | 272 | unsigned int blocksize = inode->i_sb->s_blocksize; |
271 | struct dnode_of_data dn; | 273 | struct dnode_of_data dn; |
272 | pgoff_t free_from; | 274 | pgoff_t free_from; |
273 | int count = 0, ilock = -1; | 275 | int count = 0; |
274 | int err; | 276 | int err; |
275 | 277 | ||
276 | trace_f2fs_truncate_blocks_enter(inode, from); | 278 | trace_f2fs_truncate_blocks_enter(inode, from); |
@@ -278,13 +280,13 @@ static int truncate_blocks(struct inode *inode, u64 from) | |||
278 | free_from = (pgoff_t) | 280 | free_from = (pgoff_t) |
279 | ((from + blocksize - 1) >> (sbi->log_blocksize)); | 281 | ((from + blocksize - 1) >> (sbi->log_blocksize)); |
280 | 282 | ||
281 | ilock = mutex_lock_op(sbi); | 283 | f2fs_lock_op(sbi); |
282 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 284 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
283 | err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE); | 285 | err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE); |
284 | if (err) { | 286 | if (err) { |
285 | if (err == -ENOENT) | 287 | if (err == -ENOENT) |
286 | goto free_next; | 288 | goto free_next; |
287 | mutex_unlock_op(sbi, ilock); | 289 | f2fs_unlock_op(sbi); |
288 | trace_f2fs_truncate_blocks_exit(inode, err); | 290 | trace_f2fs_truncate_blocks_exit(inode, err); |
289 | return err; | 291 | return err; |
290 | } | 292 | } |
@@ -295,7 +297,7 @@ static int truncate_blocks(struct inode *inode, u64 from) | |||
295 | count = ADDRS_PER_BLOCK; | 297 | count = ADDRS_PER_BLOCK; |
296 | 298 | ||
297 | count -= dn.ofs_in_node; | 299 | count -= dn.ofs_in_node; |
298 | BUG_ON(count < 0); | 300 | f2fs_bug_on(count < 0); |
299 | 301 | ||
300 | if (dn.ofs_in_node || IS_INODE(dn.node_page)) { | 302 | if (dn.ofs_in_node || IS_INODE(dn.node_page)) { |
301 | truncate_data_blocks_range(&dn, count); | 303 | truncate_data_blocks_range(&dn, count); |
@@ -305,7 +307,7 @@ static int truncate_blocks(struct inode *inode, u64 from) | |||
305 | f2fs_put_dnode(&dn); | 307 | f2fs_put_dnode(&dn); |
306 | free_next: | 308 | free_next: |
307 | err = truncate_inode_blocks(inode, free_from); | 309 | err = truncate_inode_blocks(inode, free_from); |
308 | mutex_unlock_op(sbi, ilock); | 310 | f2fs_unlock_op(sbi); |
309 | 311 | ||
310 | /* lastly zero out the first data page */ | 312 | /* lastly zero out the first data page */ |
311 | truncate_partial_data_page(inode, from); | 313 | truncate_partial_data_page(inode, from); |
@@ -416,16 +418,15 @@ static void fill_zero(struct inode *inode, pgoff_t index, | |||
416 | { | 418 | { |
417 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 419 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
418 | struct page *page; | 420 | struct page *page; |
419 | int ilock; | ||
420 | 421 | ||
421 | if (!len) | 422 | if (!len) |
422 | return; | 423 | return; |
423 | 424 | ||
424 | f2fs_balance_fs(sbi); | 425 | f2fs_balance_fs(sbi); |
425 | 426 | ||
426 | ilock = mutex_lock_op(sbi); | 427 | f2fs_lock_op(sbi); |
427 | page = get_new_data_page(inode, NULL, index, false); | 428 | page = get_new_data_page(inode, NULL, index, false); |
428 | mutex_unlock_op(sbi, ilock); | 429 | f2fs_unlock_op(sbi); |
429 | 430 | ||
430 | if (!IS_ERR(page)) { | 431 | if (!IS_ERR(page)) { |
431 | wait_on_page_writeback(page); | 432 | wait_on_page_writeback(page); |
@@ -484,7 +485,6 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode) | |||
484 | struct address_space *mapping = inode->i_mapping; | 485 | struct address_space *mapping = inode->i_mapping; |
485 | loff_t blk_start, blk_end; | 486 | loff_t blk_start, blk_end; |
486 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 487 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
487 | int ilock; | ||
488 | 488 | ||
489 | f2fs_balance_fs(sbi); | 489 | f2fs_balance_fs(sbi); |
490 | 490 | ||
@@ -493,9 +493,9 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode) | |||
493 | truncate_inode_pages_range(mapping, blk_start, | 493 | truncate_inode_pages_range(mapping, blk_start, |
494 | blk_end - 1); | 494 | blk_end - 1); |
495 | 495 | ||
496 | ilock = mutex_lock_op(sbi); | 496 | f2fs_lock_op(sbi); |
497 | ret = truncate_hole(inode, pg_start, pg_end); | 497 | ret = truncate_hole(inode, pg_start, pg_end); |
498 | mutex_unlock_op(sbi, ilock); | 498 | f2fs_unlock_op(sbi); |
499 | } | 499 | } |
500 | } | 500 | } |
501 | 501 | ||
@@ -529,13 +529,12 @@ static int expand_inode_data(struct inode *inode, loff_t offset, | |||
529 | 529 | ||
530 | for (index = pg_start; index <= pg_end; index++) { | 530 | for (index = pg_start; index <= pg_end; index++) { |
531 | struct dnode_of_data dn; | 531 | struct dnode_of_data dn; |
532 | int ilock; | ||
533 | 532 | ||
534 | ilock = mutex_lock_op(sbi); | 533 | f2fs_lock_op(sbi); |
535 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 534 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
536 | ret = get_dnode_of_data(&dn, index, ALLOC_NODE); | 535 | ret = get_dnode_of_data(&dn, index, ALLOC_NODE); |
537 | if (ret) { | 536 | if (ret) { |
538 | mutex_unlock_op(sbi, ilock); | 537 | f2fs_unlock_op(sbi); |
539 | break; | 538 | break; |
540 | } | 539 | } |
541 | 540 | ||
@@ -543,12 +542,12 @@ static int expand_inode_data(struct inode *inode, loff_t offset, | |||
543 | ret = reserve_new_block(&dn); | 542 | ret = reserve_new_block(&dn); |
544 | if (ret) { | 543 | if (ret) { |
545 | f2fs_put_dnode(&dn); | 544 | f2fs_put_dnode(&dn); |
546 | mutex_unlock_op(sbi, ilock); | 545 | f2fs_unlock_op(sbi); |
547 | break; | 546 | break; |
548 | } | 547 | } |
549 | } | 548 | } |
550 | f2fs_put_dnode(&dn); | 549 | f2fs_put_dnode(&dn); |
551 | mutex_unlock_op(sbi, ilock); | 550 | f2fs_unlock_op(sbi); |
552 | 551 | ||
553 | if (pg_start == pg_end) | 552 | if (pg_start == pg_end) |
554 | new_size = offset + len; | 553 | new_size = offset + len; |
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 2f157e883687..b7ad1ec7e4cc 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -77,13 +77,15 @@ static int gc_thread_func(void *data) | |||
77 | else | 77 | else |
78 | wait_ms = increase_sleep_time(gc_th, wait_ms); | 78 | wait_ms = increase_sleep_time(gc_th, wait_ms); |
79 | 79 | ||
80 | #ifdef CONFIG_F2FS_STAT_FS | 80 | stat_inc_bggc_count(sbi); |
81 | sbi->bg_gc++; | ||
82 | #endif | ||
83 | 81 | ||
84 | /* if return value is not zero, no victim was selected */ | 82 | /* if return value is not zero, no victim was selected */ |
85 | if (f2fs_gc(sbi)) | 83 | if (f2fs_gc(sbi)) |
86 | wait_ms = gc_th->no_gc_sleep_time; | 84 | wait_ms = gc_th->no_gc_sleep_time; |
85 | |||
86 | /* balancing f2fs's metadata periodically */ | ||
87 | f2fs_balance_fs_bg(sbi); | ||
88 | |||
87 | } while (!kthread_should_stop()); | 89 | } while (!kthread_should_stop()); |
88 | return 0; | 90 | return 0; |
89 | } | 91 | } |
@@ -236,8 +238,8 @@ static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno) | |||
236 | return UINT_MAX - ((100 * (100 - u) * age) / (100 + u)); | 238 | return UINT_MAX - ((100 * (100 - u) * age) / (100 + u)); |
237 | } | 239 | } |
238 | 240 | ||
239 | static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno, | 241 | static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi, |
240 | struct victim_sel_policy *p) | 242 | unsigned int segno, struct victim_sel_policy *p) |
241 | { | 243 | { |
242 | if (p->alloc_mode == SSR) | 244 | if (p->alloc_mode == SSR) |
243 | return get_seg_entry(sbi, segno)->ckpt_valid_blocks; | 245 | return get_seg_entry(sbi, segno)->ckpt_valid_blocks; |
@@ -293,7 +295,11 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
293 | } | 295 | } |
294 | break; | 296 | break; |
295 | } | 297 | } |
296 | p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit; | 298 | |
299 | p.offset = segno + p.ofs_unit; | ||
300 | if (p.ofs_unit > 1) | ||
301 | p.offset -= segno % p.ofs_unit; | ||
302 | |||
297 | secno = GET_SECNO(sbi, segno); | 303 | secno = GET_SECNO(sbi, segno); |
298 | 304 | ||
299 | if (sec_usage_check(sbi, secno)) | 305 | if (sec_usage_check(sbi, secno)) |
@@ -306,10 +312,9 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
306 | if (p.min_cost > cost) { | 312 | if (p.min_cost > cost) { |
307 | p.min_segno = segno; | 313 | p.min_segno = segno; |
308 | p.min_cost = cost; | 314 | p.min_cost = cost; |
309 | } | 315 | } else if (unlikely(cost == max_cost)) { |
310 | |||
311 | if (cost == max_cost) | ||
312 | continue; | 316 | continue; |
317 | } | ||
313 | 318 | ||
314 | if (nsearched++ >= p.max_search) { | 319 | if (nsearched++ >= p.max_search) { |
315 | sbi->last_victim[p.gc_mode] = segno; | 320 | sbi->last_victim[p.gc_mode] = segno; |
@@ -358,12 +363,8 @@ static void add_gc_inode(struct inode *inode, struct list_head *ilist) | |||
358 | iput(inode); | 363 | iput(inode); |
359 | return; | 364 | return; |
360 | } | 365 | } |
361 | repeat: | 366 | |
362 | new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS); | 367 | new_ie = f2fs_kmem_cache_alloc(winode_slab, GFP_NOFS); |
363 | if (!new_ie) { | ||
364 | cond_resched(); | ||
365 | goto repeat; | ||
366 | } | ||
367 | new_ie->inode = inode; | 368 | new_ie->inode = inode; |
368 | list_add_tail(&new_ie->list, ilist); | 369 | list_add_tail(&new_ie->list, ilist); |
369 | } | 370 | } |
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 9339cd292047..d0eaa9faeca0 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c | |||
@@ -37,6 +37,31 @@ void f2fs_set_inode_flags(struct inode *inode) | |||
37 | inode->i_flags |= S_DIRSYNC; | 37 | inode->i_flags |= S_DIRSYNC; |
38 | } | 38 | } |
39 | 39 | ||
40 | static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri) | ||
41 | { | ||
42 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || | ||
43 | S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { | ||
44 | if (ri->i_addr[0]) | ||
45 | inode->i_rdev = old_decode_dev(le32_to_cpu(ri->i_addr[0])); | ||
46 | else | ||
47 | inode->i_rdev = new_decode_dev(le32_to_cpu(ri->i_addr[1])); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static void __set_inode_rdev(struct inode *inode, struct f2fs_inode *ri) | ||
52 | { | ||
53 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { | ||
54 | if (old_valid_dev(inode->i_rdev)) { | ||
55 | ri->i_addr[0] = cpu_to_le32(old_encode_dev(inode->i_rdev)); | ||
56 | ri->i_addr[1] = 0; | ||
57 | } else { | ||
58 | ri->i_addr[0] = 0; | ||
59 | ri->i_addr[1] = cpu_to_le32(new_encode_dev(inode->i_rdev)); | ||
60 | ri->i_addr[2] = 0; | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | |||
40 | static int do_read_inode(struct inode *inode) | 65 | static int do_read_inode(struct inode *inode) |
41 | { | 66 | { |
42 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 67 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
@@ -73,10 +98,6 @@ static int do_read_inode(struct inode *inode) | |||
73 | inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec); | 98 | inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec); |
74 | inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec); | 99 | inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec); |
75 | inode->i_generation = le32_to_cpu(ri->i_generation); | 100 | inode->i_generation = le32_to_cpu(ri->i_generation); |
76 | if (ri->i_addr[0]) | ||
77 | inode->i_rdev = old_decode_dev(le32_to_cpu(ri->i_addr[0])); | ||
78 | else | ||
79 | inode->i_rdev = new_decode_dev(le32_to_cpu(ri->i_addr[1])); | ||
80 | 101 | ||
81 | fi->i_current_depth = le32_to_cpu(ri->i_current_depth); | 102 | fi->i_current_depth = le32_to_cpu(ri->i_current_depth); |
82 | fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid); | 103 | fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid); |
@@ -84,8 +105,13 @@ static int do_read_inode(struct inode *inode) | |||
84 | fi->flags = 0; | 105 | fi->flags = 0; |
85 | fi->i_advise = ri->i_advise; | 106 | fi->i_advise = ri->i_advise; |
86 | fi->i_pino = le32_to_cpu(ri->i_pino); | 107 | fi->i_pino = le32_to_cpu(ri->i_pino); |
108 | |||
87 | get_extent_info(&fi->ext, ri->i_ext); | 109 | get_extent_info(&fi->ext, ri->i_ext); |
88 | get_inline_info(fi, ri); | 110 | get_inline_info(fi, ri); |
111 | |||
112 | /* get rdev by using inline_info */ | ||
113 | __get_inode_rdev(inode, ri); | ||
114 | |||
89 | f2fs_put_page(node_page, 1); | 115 | f2fs_put_page(node_page, 1); |
90 | return 0; | 116 | return 0; |
91 | } | 117 | } |
@@ -179,21 +205,10 @@ void update_inode(struct inode *inode, struct page *node_page) | |||
179 | ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino); | 205 | ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino); |
180 | ri->i_generation = cpu_to_le32(inode->i_generation); | 206 | ri->i_generation = cpu_to_le32(inode->i_generation); |
181 | 207 | ||
182 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { | 208 | __set_inode_rdev(inode, ri); |
183 | if (old_valid_dev(inode->i_rdev)) { | ||
184 | ri->i_addr[0] = | ||
185 | cpu_to_le32(old_encode_dev(inode->i_rdev)); | ||
186 | ri->i_addr[1] = 0; | ||
187 | } else { | ||
188 | ri->i_addr[0] = 0; | ||
189 | ri->i_addr[1] = | ||
190 | cpu_to_le32(new_encode_dev(inode->i_rdev)); | ||
191 | ri->i_addr[2] = 0; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | set_cold_node(inode, node_page); | 209 | set_cold_node(inode, node_page); |
196 | set_page_dirty(node_page); | 210 | set_page_dirty(node_page); |
211 | |||
197 | clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); | 212 | clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); |
198 | } | 213 | } |
199 | 214 | ||
@@ -214,7 +229,7 @@ int update_inode_page(struct inode *inode) | |||
214 | int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | 229 | int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) |
215 | { | 230 | { |
216 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 231 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
217 | int ret, ilock; | 232 | int ret; |
218 | 233 | ||
219 | if (inode->i_ino == F2FS_NODE_INO(sbi) || | 234 | if (inode->i_ino == F2FS_NODE_INO(sbi) || |
220 | inode->i_ino == F2FS_META_INO(sbi)) | 235 | inode->i_ino == F2FS_META_INO(sbi)) |
@@ -227,9 +242,9 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
227 | * We need to lock here to prevent from producing dirty node pages | 242 | * We need to lock here to prevent from producing dirty node pages |
228 | * during the urgent cleaning time when runing out of free sections. | 243 | * during the urgent cleaning time when runing out of free sections. |
229 | */ | 244 | */ |
230 | ilock = mutex_lock_op(sbi); | 245 | f2fs_lock_op(sbi); |
231 | ret = update_inode_page(inode); | 246 | ret = update_inode_page(inode); |
232 | mutex_unlock_op(sbi, ilock); | 247 | f2fs_unlock_op(sbi); |
233 | 248 | ||
234 | if (wbc) | 249 | if (wbc) |
235 | f2fs_balance_fs(sbi); | 250 | f2fs_balance_fs(sbi); |
@@ -243,7 +258,6 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
243 | void f2fs_evict_inode(struct inode *inode) | 258 | void f2fs_evict_inode(struct inode *inode) |
244 | { | 259 | { |
245 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 260 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
246 | int ilock; | ||
247 | 261 | ||
248 | trace_f2fs_evict_inode(inode); | 262 | trace_f2fs_evict_inode(inode); |
249 | truncate_inode_pages(&inode->i_data, 0); | 263 | truncate_inode_pages(&inode->i_data, 0); |
@@ -252,7 +266,7 @@ void f2fs_evict_inode(struct inode *inode) | |||
252 | inode->i_ino == F2FS_META_INO(sbi)) | 266 | inode->i_ino == F2FS_META_INO(sbi)) |
253 | goto no_delete; | 267 | goto no_delete; |
254 | 268 | ||
255 | BUG_ON(atomic_read(&F2FS_I(inode)->dirty_dents)); | 269 | f2fs_bug_on(atomic_read(&F2FS_I(inode)->dirty_dents)); |
256 | remove_dirty_dir_inode(inode); | 270 | remove_dirty_dir_inode(inode); |
257 | 271 | ||
258 | if (inode->i_nlink || is_bad_inode(inode)) | 272 | if (inode->i_nlink || is_bad_inode(inode)) |
@@ -265,9 +279,9 @@ void f2fs_evict_inode(struct inode *inode) | |||
265 | if (F2FS_HAS_BLOCKS(inode)) | 279 | if (F2FS_HAS_BLOCKS(inode)) |
266 | f2fs_truncate(inode); | 280 | f2fs_truncate(inode); |
267 | 281 | ||
268 | ilock = mutex_lock_op(sbi); | 282 | f2fs_lock_op(sbi); |
269 | remove_inode_page(inode); | 283 | remove_inode_page(inode); |
270 | mutex_unlock_op(sbi, ilock); | 284 | f2fs_unlock_op(sbi); |
271 | 285 | ||
272 | sb_end_intwrite(inode->i_sb); | 286 | sb_end_intwrite(inode->i_sb); |
273 | no_delete: | 287 | no_delete: |
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 2a5359c990fc..575adac17f8b 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c | |||
@@ -27,19 +27,19 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) | |||
27 | nid_t ino; | 27 | nid_t ino; |
28 | struct inode *inode; | 28 | struct inode *inode; |
29 | bool nid_free = false; | 29 | bool nid_free = false; |
30 | int err, ilock; | 30 | int err; |
31 | 31 | ||
32 | inode = new_inode(sb); | 32 | inode = new_inode(sb); |
33 | if (!inode) | 33 | if (!inode) |
34 | return ERR_PTR(-ENOMEM); | 34 | return ERR_PTR(-ENOMEM); |
35 | 35 | ||
36 | ilock = mutex_lock_op(sbi); | 36 | f2fs_lock_op(sbi); |
37 | if (!alloc_nid(sbi, &ino)) { | 37 | if (!alloc_nid(sbi, &ino)) { |
38 | mutex_unlock_op(sbi, ilock); | 38 | f2fs_unlock_op(sbi); |
39 | err = -ENOSPC; | 39 | err = -ENOSPC; |
40 | goto fail; | 40 | goto fail; |
41 | } | 41 | } |
42 | mutex_unlock_op(sbi, ilock); | 42 | f2fs_unlock_op(sbi); |
43 | 43 | ||
44 | inode->i_uid = current_fsuid(); | 44 | inode->i_uid = current_fsuid(); |
45 | 45 | ||
@@ -115,7 +115,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
115 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | 115 | struct f2fs_sb_info *sbi = F2FS_SB(sb); |
116 | struct inode *inode; | 116 | struct inode *inode; |
117 | nid_t ino = 0; | 117 | nid_t ino = 0; |
118 | int err, ilock; | 118 | int err; |
119 | 119 | ||
120 | f2fs_balance_fs(sbi); | 120 | f2fs_balance_fs(sbi); |
121 | 121 | ||
@@ -131,9 +131,9 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
131 | inode->i_mapping->a_ops = &f2fs_dblock_aops; | 131 | inode->i_mapping->a_ops = &f2fs_dblock_aops; |
132 | ino = inode->i_ino; | 132 | ino = inode->i_ino; |
133 | 133 | ||
134 | ilock = mutex_lock_op(sbi); | 134 | f2fs_lock_op(sbi); |
135 | err = f2fs_add_link(dentry, inode); | 135 | err = f2fs_add_link(dentry, inode); |
136 | mutex_unlock_op(sbi, ilock); | 136 | f2fs_unlock_op(sbi); |
137 | if (err) | 137 | if (err) |
138 | goto out; | 138 | goto out; |
139 | 139 | ||
@@ -157,7 +157,7 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, | |||
157 | struct inode *inode = old_dentry->d_inode; | 157 | struct inode *inode = old_dentry->d_inode; |
158 | struct super_block *sb = dir->i_sb; | 158 | struct super_block *sb = dir->i_sb; |
159 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | 159 | struct f2fs_sb_info *sbi = F2FS_SB(sb); |
160 | int err, ilock; | 160 | int err; |
161 | 161 | ||
162 | f2fs_balance_fs(sbi); | 162 | f2fs_balance_fs(sbi); |
163 | 163 | ||
@@ -165,9 +165,9 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, | |||
165 | ihold(inode); | 165 | ihold(inode); |
166 | 166 | ||
167 | set_inode_flag(F2FS_I(inode), FI_INC_LINK); | 167 | set_inode_flag(F2FS_I(inode), FI_INC_LINK); |
168 | ilock = mutex_lock_op(sbi); | 168 | f2fs_lock_op(sbi); |
169 | err = f2fs_add_link(dentry, inode); | 169 | err = f2fs_add_link(dentry, inode); |
170 | mutex_unlock_op(sbi, ilock); | 170 | f2fs_unlock_op(sbi); |
171 | if (err) | 171 | if (err) |
172 | goto out; | 172 | goto out; |
173 | 173 | ||
@@ -220,7 +220,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) | |||
220 | struct f2fs_dir_entry *de; | 220 | struct f2fs_dir_entry *de; |
221 | struct page *page; | 221 | struct page *page; |
222 | int err = -ENOENT; | 222 | int err = -ENOENT; |
223 | int ilock; | ||
224 | 223 | ||
225 | trace_f2fs_unlink_enter(dir, dentry); | 224 | trace_f2fs_unlink_enter(dir, dentry); |
226 | f2fs_balance_fs(sbi); | 225 | f2fs_balance_fs(sbi); |
@@ -229,16 +228,16 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) | |||
229 | if (!de) | 228 | if (!de) |
230 | goto fail; | 229 | goto fail; |
231 | 230 | ||
231 | f2fs_lock_op(sbi); | ||
232 | err = acquire_orphan_inode(sbi); | 232 | err = acquire_orphan_inode(sbi); |
233 | if (err) { | 233 | if (err) { |
234 | f2fs_unlock_op(sbi); | ||
234 | kunmap(page); | 235 | kunmap(page); |
235 | f2fs_put_page(page, 0); | 236 | f2fs_put_page(page, 0); |
236 | goto fail; | 237 | goto fail; |
237 | } | 238 | } |
238 | |||
239 | ilock = mutex_lock_op(sbi); | ||
240 | f2fs_delete_entry(de, page, inode); | 239 | f2fs_delete_entry(de, page, inode); |
241 | mutex_unlock_op(sbi, ilock); | 240 | f2fs_unlock_op(sbi); |
242 | 241 | ||
243 | /* In order to evict this inode, we set it dirty */ | 242 | /* In order to evict this inode, we set it dirty */ |
244 | mark_inode_dirty(inode); | 243 | mark_inode_dirty(inode); |
@@ -254,7 +253,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, | |||
254 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | 253 | struct f2fs_sb_info *sbi = F2FS_SB(sb); |
255 | struct inode *inode; | 254 | struct inode *inode; |
256 | size_t symlen = strlen(symname) + 1; | 255 | size_t symlen = strlen(symname) + 1; |
257 | int err, ilock; | 256 | int err; |
258 | 257 | ||
259 | f2fs_balance_fs(sbi); | 258 | f2fs_balance_fs(sbi); |
260 | 259 | ||
@@ -265,9 +264,9 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, | |||
265 | inode->i_op = &f2fs_symlink_inode_operations; | 264 | inode->i_op = &f2fs_symlink_inode_operations; |
266 | inode->i_mapping->a_ops = &f2fs_dblock_aops; | 265 | inode->i_mapping->a_ops = &f2fs_dblock_aops; |
267 | 266 | ||
268 | ilock = mutex_lock_op(sbi); | 267 | f2fs_lock_op(sbi); |
269 | err = f2fs_add_link(dentry, inode); | 268 | err = f2fs_add_link(dentry, inode); |
270 | mutex_unlock_op(sbi, ilock); | 269 | f2fs_unlock_op(sbi); |
271 | if (err) | 270 | if (err) |
272 | goto out; | 271 | goto out; |
273 | 272 | ||
@@ -290,7 +289,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
290 | { | 289 | { |
291 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); | 290 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); |
292 | struct inode *inode; | 291 | struct inode *inode; |
293 | int err, ilock; | 292 | int err; |
294 | 293 | ||
295 | f2fs_balance_fs(sbi); | 294 | f2fs_balance_fs(sbi); |
296 | 295 | ||
@@ -304,9 +303,9 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
304 | mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); | 303 | mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); |
305 | 304 | ||
306 | set_inode_flag(F2FS_I(inode), FI_INC_LINK); | 305 | set_inode_flag(F2FS_I(inode), FI_INC_LINK); |
307 | ilock = mutex_lock_op(sbi); | 306 | f2fs_lock_op(sbi); |
308 | err = f2fs_add_link(dentry, inode); | 307 | err = f2fs_add_link(dentry, inode); |
309 | mutex_unlock_op(sbi, ilock); | 308 | f2fs_unlock_op(sbi); |
310 | if (err) | 309 | if (err) |
311 | goto out_fail; | 310 | goto out_fail; |
312 | 311 | ||
@@ -342,7 +341,6 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry, | |||
342 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | 341 | struct f2fs_sb_info *sbi = F2FS_SB(sb); |
343 | struct inode *inode; | 342 | struct inode *inode; |
344 | int err = 0; | 343 | int err = 0; |
345 | int ilock; | ||
346 | 344 | ||
347 | if (!new_valid_dev(rdev)) | 345 | if (!new_valid_dev(rdev)) |
348 | return -EINVAL; | 346 | return -EINVAL; |
@@ -356,9 +354,9 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry, | |||
356 | init_special_inode(inode, inode->i_mode, rdev); | 354 | init_special_inode(inode, inode->i_mode, rdev); |
357 | inode->i_op = &f2fs_special_inode_operations; | 355 | inode->i_op = &f2fs_special_inode_operations; |
358 | 356 | ||
359 | ilock = mutex_lock_op(sbi); | 357 | f2fs_lock_op(sbi); |
360 | err = f2fs_add_link(dentry, inode); | 358 | err = f2fs_add_link(dentry, inode); |
361 | mutex_unlock_op(sbi, ilock); | 359 | f2fs_unlock_op(sbi); |
362 | if (err) | 360 | if (err) |
363 | goto out; | 361 | goto out; |
364 | 362 | ||
@@ -387,7 +385,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
387 | struct f2fs_dir_entry *old_dir_entry = NULL; | 385 | struct f2fs_dir_entry *old_dir_entry = NULL; |
388 | struct f2fs_dir_entry *old_entry; | 386 | struct f2fs_dir_entry *old_entry; |
389 | struct f2fs_dir_entry *new_entry; | 387 | struct f2fs_dir_entry *new_entry; |
390 | int err = -ENOENT, ilock = -1; | 388 | int err = -ENOENT; |
391 | 389 | ||
392 | f2fs_balance_fs(sbi); | 390 | f2fs_balance_fs(sbi); |
393 | 391 | ||
@@ -402,7 +400,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
402 | goto out_old; | 400 | goto out_old; |
403 | } | 401 | } |
404 | 402 | ||
405 | ilock = mutex_lock_op(sbi); | 403 | f2fs_lock_op(sbi); |
406 | 404 | ||
407 | if (new_inode) { | 405 | if (new_inode) { |
408 | 406 | ||
@@ -467,7 +465,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
467 | update_inode_page(old_dir); | 465 | update_inode_page(old_dir); |
468 | } | 466 | } |
469 | 467 | ||
470 | mutex_unlock_op(sbi, ilock); | 468 | f2fs_unlock_op(sbi); |
471 | return 0; | 469 | return 0; |
472 | 470 | ||
473 | put_out_dir: | 471 | put_out_dir: |
@@ -477,7 +475,7 @@ out_dir: | |||
477 | kunmap(old_dir_page); | 475 | kunmap(old_dir_page); |
478 | f2fs_put_page(old_dir_page, 0); | 476 | f2fs_put_page(old_dir_page, 0); |
479 | } | 477 | } |
480 | mutex_unlock_op(sbi, ilock); | 478 | f2fs_unlock_op(sbi); |
481 | out_old: | 479 | out_old: |
482 | kunmap(old_page); | 480 | kunmap(old_page); |
483 | f2fs_put_page(old_page, 0); | 481 | f2fs_put_page(old_page, 0); |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 51ef27894433..4ac4150d421d 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -204,7 +204,7 @@ retry: | |||
204 | } | 204 | } |
205 | e->ni = *ni; | 205 | e->ni = *ni; |
206 | e->checkpointed = true; | 206 | e->checkpointed = true; |
207 | BUG_ON(ni->blk_addr == NEW_ADDR); | 207 | f2fs_bug_on(ni->blk_addr == NEW_ADDR); |
208 | } else if (new_blkaddr == NEW_ADDR) { | 208 | } else if (new_blkaddr == NEW_ADDR) { |
209 | /* | 209 | /* |
210 | * when nid is reallocated, | 210 | * when nid is reallocated, |
@@ -212,19 +212,19 @@ retry: | |||
212 | * So, reinitialize it with new information. | 212 | * So, reinitialize it with new information. |
213 | */ | 213 | */ |
214 | e->ni = *ni; | 214 | e->ni = *ni; |
215 | BUG_ON(ni->blk_addr != NULL_ADDR); | 215 | f2fs_bug_on(ni->blk_addr != NULL_ADDR); |
216 | } | 216 | } |
217 | 217 | ||
218 | if (new_blkaddr == NEW_ADDR) | 218 | if (new_blkaddr == NEW_ADDR) |
219 | e->checkpointed = false; | 219 | e->checkpointed = false; |
220 | 220 | ||
221 | /* sanity check */ | 221 | /* sanity check */ |
222 | BUG_ON(nat_get_blkaddr(e) != ni->blk_addr); | 222 | f2fs_bug_on(nat_get_blkaddr(e) != ni->blk_addr); |
223 | BUG_ON(nat_get_blkaddr(e) == NULL_ADDR && | 223 | f2fs_bug_on(nat_get_blkaddr(e) == NULL_ADDR && |
224 | new_blkaddr == NULL_ADDR); | 224 | new_blkaddr == NULL_ADDR); |
225 | BUG_ON(nat_get_blkaddr(e) == NEW_ADDR && | 225 | f2fs_bug_on(nat_get_blkaddr(e) == NEW_ADDR && |
226 | new_blkaddr == NEW_ADDR); | 226 | new_blkaddr == NEW_ADDR); |
227 | BUG_ON(nat_get_blkaddr(e) != NEW_ADDR && | 227 | f2fs_bug_on(nat_get_blkaddr(e) != NEW_ADDR && |
228 | nat_get_blkaddr(e) != NULL_ADDR && | 228 | nat_get_blkaddr(e) != NULL_ADDR && |
229 | new_blkaddr == NEW_ADDR); | 229 | new_blkaddr == NEW_ADDR); |
230 | 230 | ||
@@ -240,7 +240,7 @@ retry: | |||
240 | write_unlock(&nm_i->nat_tree_lock); | 240 | write_unlock(&nm_i->nat_tree_lock); |
241 | } | 241 | } |
242 | 242 | ||
243 | static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) | 243 | int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) |
244 | { | 244 | { |
245 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 245 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
246 | 246 | ||
@@ -495,10 +495,10 @@ static void truncate_node(struct dnode_of_data *dn) | |||
495 | 495 | ||
496 | get_node_info(sbi, dn->nid, &ni); | 496 | get_node_info(sbi, dn->nid, &ni); |
497 | if (dn->inode->i_blocks == 0) { | 497 | if (dn->inode->i_blocks == 0) { |
498 | BUG_ON(ni.blk_addr != NULL_ADDR); | 498 | f2fs_bug_on(ni.blk_addr != NULL_ADDR); |
499 | goto invalidate; | 499 | goto invalidate; |
500 | } | 500 | } |
501 | BUG_ON(ni.blk_addr == NULL_ADDR); | 501 | f2fs_bug_on(ni.blk_addr == NULL_ADDR); |
502 | 502 | ||
503 | /* Deallocate node address */ | 503 | /* Deallocate node address */ |
504 | invalidate_blocks(sbi, ni.blk_addr); | 504 | invalidate_blocks(sbi, ni.blk_addr); |
@@ -822,7 +822,7 @@ int remove_inode_page(struct inode *inode) | |||
822 | } | 822 | } |
823 | 823 | ||
824 | /* 0 is possible, after f2fs_new_inode() is failed */ | 824 | /* 0 is possible, after f2fs_new_inode() is failed */ |
825 | BUG_ON(inode->i_blocks != 0 && inode->i_blocks != 1); | 825 | f2fs_bug_on(inode->i_blocks != 0 && inode->i_blocks != 1); |
826 | set_new_dnode(&dn, inode, page, page, ino); | 826 | set_new_dnode(&dn, inode, page, page, ino); |
827 | truncate_node(&dn); | 827 | truncate_node(&dn); |
828 | return 0; | 828 | return 0; |
@@ -863,7 +863,7 @@ struct page *new_node_page(struct dnode_of_data *dn, | |||
863 | get_node_info(sbi, dn->nid, &old_ni); | 863 | get_node_info(sbi, dn->nid, &old_ni); |
864 | 864 | ||
865 | /* Reinitialize old_ni with new node page */ | 865 | /* Reinitialize old_ni with new node page */ |
866 | BUG_ON(old_ni.blk_addr != NULL_ADDR); | 866 | f2fs_bug_on(old_ni.blk_addr != NULL_ADDR); |
867 | new_ni = old_ni; | 867 | new_ni = old_ni; |
868 | new_ni.ino = dn->inode->i_ino; | 868 | new_ni.ino = dn->inode->i_ino; |
869 | set_node_addr(sbi, &new_ni, NEW_ADDR); | 869 | set_node_addr(sbi, &new_ni, NEW_ADDR); |
@@ -969,7 +969,7 @@ repeat: | |||
969 | goto repeat; | 969 | goto repeat; |
970 | } | 970 | } |
971 | got_it: | 971 | got_it: |
972 | BUG_ON(nid != nid_of_node(page)); | 972 | f2fs_bug_on(nid != nid_of_node(page)); |
973 | mark_page_accessed(page); | 973 | mark_page_accessed(page); |
974 | return page; | 974 | return page; |
975 | } | 975 | } |
@@ -1148,6 +1148,47 @@ continue_unlock: | |||
1148 | return nwritten; | 1148 | return nwritten; |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino) | ||
1152 | { | ||
1153 | struct address_space *mapping = sbi->node_inode->i_mapping; | ||
1154 | pgoff_t index = 0, end = LONG_MAX; | ||
1155 | struct pagevec pvec; | ||
1156 | int nr_pages; | ||
1157 | int ret2 = 0, ret = 0; | ||
1158 | |||
1159 | pagevec_init(&pvec, 0); | ||
1160 | while ((index <= end) && | ||
1161 | (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, | ||
1162 | PAGECACHE_TAG_WRITEBACK, | ||
1163 | min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1)) != 0) { | ||
1164 | unsigned i; | ||
1165 | |||
1166 | for (i = 0; i < nr_pages; i++) { | ||
1167 | struct page *page = pvec.pages[i]; | ||
1168 | |||
1169 | /* until radix tree lookup accepts end_index */ | ||
1170 | if (page->index > end) | ||
1171 | continue; | ||
1172 | |||
1173 | if (ino && ino_of_node(page) == ino) { | ||
1174 | wait_on_page_writeback(page); | ||
1175 | if (TestClearPageError(page)) | ||
1176 | ret = -EIO; | ||
1177 | } | ||
1178 | } | ||
1179 | pagevec_release(&pvec); | ||
1180 | cond_resched(); | ||
1181 | } | ||
1182 | |||
1183 | if (test_and_clear_bit(AS_ENOSPC, &mapping->flags)) | ||
1184 | ret2 = -ENOSPC; | ||
1185 | if (test_and_clear_bit(AS_EIO, &mapping->flags)) | ||
1186 | ret2 = -EIO; | ||
1187 | if (!ret) | ||
1188 | ret = ret2; | ||
1189 | return ret; | ||
1190 | } | ||
1191 | |||
1151 | static int f2fs_write_node_page(struct page *page, | 1192 | static int f2fs_write_node_page(struct page *page, |
1152 | struct writeback_control *wbc) | 1193 | struct writeback_control *wbc) |
1153 | { | 1194 | { |
@@ -1156,11 +1197,14 @@ static int f2fs_write_node_page(struct page *page, | |||
1156 | block_t new_addr; | 1197 | block_t new_addr; |
1157 | struct node_info ni; | 1198 | struct node_info ni; |
1158 | 1199 | ||
1200 | if (sbi->por_doing) | ||
1201 | goto redirty_out; | ||
1202 | |||
1159 | wait_on_page_writeback(page); | 1203 | wait_on_page_writeback(page); |
1160 | 1204 | ||
1161 | /* get old block addr of this node page */ | 1205 | /* get old block addr of this node page */ |
1162 | nid = nid_of_node(page); | 1206 | nid = nid_of_node(page); |
1163 | BUG_ON(page->index != nid); | 1207 | f2fs_bug_on(page->index != nid); |
1164 | 1208 | ||
1165 | get_node_info(sbi, nid, &ni); | 1209 | get_node_info(sbi, nid, &ni); |
1166 | 1210 | ||
@@ -1171,12 +1215,8 @@ static int f2fs_write_node_page(struct page *page, | |||
1171 | return 0; | 1215 | return 0; |
1172 | } | 1216 | } |
1173 | 1217 | ||
1174 | if (wbc->for_reclaim) { | 1218 | if (wbc->for_reclaim) |
1175 | dec_page_count(sbi, F2FS_DIRTY_NODES); | 1219 | goto redirty_out; |
1176 | wbc->pages_skipped++; | ||
1177 | set_page_dirty(page); | ||
1178 | return AOP_WRITEPAGE_ACTIVATE; | ||
1179 | } | ||
1180 | 1220 | ||
1181 | mutex_lock(&sbi->node_write); | 1221 | mutex_lock(&sbi->node_write); |
1182 | set_page_writeback(page); | 1222 | set_page_writeback(page); |
@@ -1186,6 +1226,12 @@ static int f2fs_write_node_page(struct page *page, | |||
1186 | mutex_unlock(&sbi->node_write); | 1226 | mutex_unlock(&sbi->node_write); |
1187 | unlock_page(page); | 1227 | unlock_page(page); |
1188 | return 0; | 1228 | return 0; |
1229 | |||
1230 | redirty_out: | ||
1231 | dec_page_count(sbi, F2FS_DIRTY_NODES); | ||
1232 | wbc->pages_skipped++; | ||
1233 | set_page_dirty(page); | ||
1234 | return AOP_WRITEPAGE_ACTIVATE; | ||
1189 | } | 1235 | } |
1190 | 1236 | ||
1191 | /* | 1237 | /* |
@@ -1200,11 +1246,8 @@ static int f2fs_write_node_pages(struct address_space *mapping, | |||
1200 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); | 1246 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); |
1201 | long nr_to_write = wbc->nr_to_write; | 1247 | long nr_to_write = wbc->nr_to_write; |
1202 | 1248 | ||
1203 | /* First check balancing cached NAT entries */ | 1249 | /* balancing f2fs's metadata in background */ |
1204 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) { | 1250 | f2fs_balance_fs_bg(sbi); |
1205 | f2fs_sync_fs(sbi->sb, true); | ||
1206 | return 0; | ||
1207 | } | ||
1208 | 1251 | ||
1209 | /* collect a number of dirty node pages and write together */ | 1252 | /* collect a number of dirty node pages and write together */ |
1210 | if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES) | 1253 | if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES) |
@@ -1223,6 +1266,8 @@ static int f2fs_set_node_page_dirty(struct page *page) | |||
1223 | struct address_space *mapping = page->mapping; | 1266 | struct address_space *mapping = page->mapping; |
1224 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); | 1267 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); |
1225 | 1268 | ||
1269 | trace_f2fs_set_page_dirty(page, NODE); | ||
1270 | |||
1226 | SetPageUptodate(page); | 1271 | SetPageUptodate(page); |
1227 | if (!PageDirty(page)) { | 1272 | if (!PageDirty(page)) { |
1228 | __set_page_dirty_nobuffers(page); | 1273 | __set_page_dirty_nobuffers(page); |
@@ -1291,23 +1336,18 @@ static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build) | |||
1291 | if (nid == 0) | 1336 | if (nid == 0) |
1292 | return 0; | 1337 | return 0; |
1293 | 1338 | ||
1294 | if (!build) | 1339 | if (build) { |
1295 | goto retry; | 1340 | /* do not add allocated nids */ |
1296 | 1341 | read_lock(&nm_i->nat_tree_lock); | |
1297 | /* do not add allocated nids */ | 1342 | ne = __lookup_nat_cache(nm_i, nid); |
1298 | read_lock(&nm_i->nat_tree_lock); | 1343 | if (ne && nat_get_blkaddr(ne) != NULL_ADDR) |
1299 | ne = __lookup_nat_cache(nm_i, nid); | 1344 | allocated = true; |
1300 | if (ne && nat_get_blkaddr(ne) != NULL_ADDR) | 1345 | read_unlock(&nm_i->nat_tree_lock); |
1301 | allocated = true; | 1346 | if (allocated) |
1302 | read_unlock(&nm_i->nat_tree_lock); | 1347 | return 0; |
1303 | if (allocated) | ||
1304 | return 0; | ||
1305 | retry: | ||
1306 | i = kmem_cache_alloc(free_nid_slab, GFP_NOFS); | ||
1307 | if (!i) { | ||
1308 | cond_resched(); | ||
1309 | goto retry; | ||
1310 | } | 1348 | } |
1349 | |||
1350 | i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS); | ||
1311 | i->nid = nid; | 1351 | i->nid = nid; |
1312 | i->state = NID_NEW; | 1352 | i->state = NID_NEW; |
1313 | 1353 | ||
@@ -1350,7 +1390,7 @@ static void scan_nat_page(struct f2fs_nm_info *nm_i, | |||
1350 | break; | 1390 | break; |
1351 | 1391 | ||
1352 | blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); | 1392 | blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); |
1353 | BUG_ON(blk_addr == NEW_ADDR); | 1393 | f2fs_bug_on(blk_addr == NEW_ADDR); |
1354 | if (blk_addr == NULL_ADDR) { | 1394 | if (blk_addr == NULL_ADDR) { |
1355 | if (add_free_nid(nm_i, start_nid, true) < 0) | 1395 | if (add_free_nid(nm_i, start_nid, true) < 0) |
1356 | break; | 1396 | break; |
@@ -1421,14 +1461,14 @@ retry: | |||
1421 | 1461 | ||
1422 | /* We should not use stale free nids created by build_free_nids */ | 1462 | /* We should not use stale free nids created by build_free_nids */ |
1423 | if (nm_i->fcnt && !sbi->on_build_free_nids) { | 1463 | if (nm_i->fcnt && !sbi->on_build_free_nids) { |
1424 | BUG_ON(list_empty(&nm_i->free_nid_list)); | 1464 | f2fs_bug_on(list_empty(&nm_i->free_nid_list)); |
1425 | list_for_each(this, &nm_i->free_nid_list) { | 1465 | list_for_each(this, &nm_i->free_nid_list) { |
1426 | i = list_entry(this, struct free_nid, list); | 1466 | i = list_entry(this, struct free_nid, list); |
1427 | if (i->state == NID_NEW) | 1467 | if (i->state == NID_NEW) |
1428 | break; | 1468 | break; |
1429 | } | 1469 | } |
1430 | 1470 | ||
1431 | BUG_ON(i->state != NID_NEW); | 1471 | f2fs_bug_on(i->state != NID_NEW); |
1432 | *nid = i->nid; | 1472 | *nid = i->nid; |
1433 | i->state = NID_ALLOC; | 1473 | i->state = NID_ALLOC; |
1434 | nm_i->fcnt--; | 1474 | nm_i->fcnt--; |
@@ -1439,9 +1479,9 @@ retry: | |||
1439 | 1479 | ||
1440 | /* Let's scan nat pages and its caches to get free nids */ | 1480 | /* Let's scan nat pages and its caches to get free nids */ |
1441 | mutex_lock(&nm_i->build_lock); | 1481 | mutex_lock(&nm_i->build_lock); |
1442 | sbi->on_build_free_nids = 1; | 1482 | sbi->on_build_free_nids = true; |
1443 | build_free_nids(sbi); | 1483 | build_free_nids(sbi); |
1444 | sbi->on_build_free_nids = 0; | 1484 | sbi->on_build_free_nids = false; |
1445 | mutex_unlock(&nm_i->build_lock); | 1485 | mutex_unlock(&nm_i->build_lock); |
1446 | goto retry; | 1486 | goto retry; |
1447 | } | 1487 | } |
@@ -1456,7 +1496,7 @@ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) | |||
1456 | 1496 | ||
1457 | spin_lock(&nm_i->free_nid_list_lock); | 1497 | spin_lock(&nm_i->free_nid_list_lock); |
1458 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); | 1498 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); |
1459 | BUG_ON(!i || i->state != NID_ALLOC); | 1499 | f2fs_bug_on(!i || i->state != NID_ALLOC); |
1460 | __del_from_free_nid_list(i); | 1500 | __del_from_free_nid_list(i); |
1461 | spin_unlock(&nm_i->free_nid_list_lock); | 1501 | spin_unlock(&nm_i->free_nid_list_lock); |
1462 | } | 1502 | } |
@@ -1474,7 +1514,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) | |||
1474 | 1514 | ||
1475 | spin_lock(&nm_i->free_nid_list_lock); | 1515 | spin_lock(&nm_i->free_nid_list_lock); |
1476 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); | 1516 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); |
1477 | BUG_ON(!i || i->state != NID_ALLOC); | 1517 | f2fs_bug_on(!i || i->state != NID_ALLOC); |
1478 | if (nm_i->fcnt > 2 * MAX_FREE_NIDS) { | 1518 | if (nm_i->fcnt > 2 * MAX_FREE_NIDS) { |
1479 | __del_from_free_nid_list(i); | 1519 | __del_from_free_nid_list(i); |
1480 | } else { | 1520 | } else { |
@@ -1677,7 +1717,7 @@ to_nat_page: | |||
1677 | nat_blk = page_address(page); | 1717 | nat_blk = page_address(page); |
1678 | } | 1718 | } |
1679 | 1719 | ||
1680 | BUG_ON(!nat_blk); | 1720 | f2fs_bug_on(!nat_blk); |
1681 | raw_ne = nat_blk->entries[nid - start_nid]; | 1721 | raw_ne = nat_blk->entries[nid - start_nid]; |
1682 | flush_now: | 1722 | flush_now: |
1683 | new_blkaddr = nat_get_blkaddr(ne); | 1723 | new_blkaddr = nat_get_blkaddr(ne); |
@@ -1781,11 +1821,11 @@ void destroy_node_manager(struct f2fs_sb_info *sbi) | |||
1781 | /* destroy free nid list */ | 1821 | /* destroy free nid list */ |
1782 | spin_lock(&nm_i->free_nid_list_lock); | 1822 | spin_lock(&nm_i->free_nid_list_lock); |
1783 | list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) { | 1823 | list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) { |
1784 | BUG_ON(i->state == NID_ALLOC); | 1824 | f2fs_bug_on(i->state == NID_ALLOC); |
1785 | __del_from_free_nid_list(i); | 1825 | __del_from_free_nid_list(i); |
1786 | nm_i->fcnt--; | 1826 | nm_i->fcnt--; |
1787 | } | 1827 | } |
1788 | BUG_ON(nm_i->fcnt); | 1828 | f2fs_bug_on(nm_i->fcnt); |
1789 | spin_unlock(&nm_i->free_nid_list_lock); | 1829 | spin_unlock(&nm_i->free_nid_list_lock); |
1790 | 1830 | ||
1791 | /* destroy nat cache */ | 1831 | /* destroy nat cache */ |
@@ -1799,7 +1839,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi) | |||
1799 | __del_from_nat_cache(nm_i, e); | 1839 | __del_from_nat_cache(nm_i, e); |
1800 | } | 1840 | } |
1801 | } | 1841 | } |
1802 | BUG_ON(nm_i->nat_cnt); | 1842 | f2fs_bug_on(nm_i->nat_cnt); |
1803 | write_unlock(&nm_i->nat_tree_lock); | 1843 | write_unlock(&nm_i->nat_tree_lock); |
1804 | 1844 | ||
1805 | kfree(nm_i->nat_bitmap); | 1845 | kfree(nm_i->nat_bitmap); |
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 51ef5eec33d7..fdc81161f254 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -64,24 +64,31 @@ static int recover_dentry(struct page *ipage, struct inode *inode) | |||
64 | name.name = raw_inode->i_name; | 64 | name.name = raw_inode->i_name; |
65 | retry: | 65 | retry: |
66 | de = f2fs_find_entry(dir, &name, &page); | 66 | de = f2fs_find_entry(dir, &name, &page); |
67 | if (de && inode->i_ino == le32_to_cpu(de->ino)) { | 67 | if (de && inode->i_ino == le32_to_cpu(de->ino)) |
68 | kunmap(page); | 68 | goto out_unmap_put; |
69 | f2fs_put_page(page, 0); | ||
70 | goto out; | ||
71 | } | ||
72 | if (de) { | 69 | if (de) { |
73 | einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); | 70 | einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); |
74 | if (IS_ERR(einode)) { | 71 | if (IS_ERR(einode)) { |
75 | WARN_ON(1); | 72 | WARN_ON(1); |
76 | if (PTR_ERR(einode) == -ENOENT) | 73 | if (PTR_ERR(einode) == -ENOENT) |
77 | err = -EEXIST; | 74 | err = -EEXIST; |
78 | goto out; | 75 | goto out_unmap_put; |
76 | } | ||
77 | err = acquire_orphan_inode(F2FS_SB(inode->i_sb)); | ||
78 | if (err) { | ||
79 | iput(einode); | ||
80 | goto out_unmap_put; | ||
79 | } | 81 | } |
80 | f2fs_delete_entry(de, page, einode); | 82 | f2fs_delete_entry(de, page, einode); |
81 | iput(einode); | 83 | iput(einode); |
82 | goto retry; | 84 | goto retry; |
83 | } | 85 | } |
84 | err = __f2fs_add_link(dir, &name, inode); | 86 | err = __f2fs_add_link(dir, &name, inode); |
87 | goto out; | ||
88 | |||
89 | out_unmap_put: | ||
90 | kunmap(page); | ||
91 | f2fs_put_page(page, 0); | ||
85 | out: | 92 | out: |
86 | f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode and its dentry: " | 93 | f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode and its dentry: " |
87 | "ino = %x, name = %s, dir = %lx, err = %d", | 94 | "ino = %x, name = %s, dir = %lx, err = %d", |
@@ -285,7 +292,6 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
285 | struct f2fs_summary sum; | 292 | struct f2fs_summary sum; |
286 | struct node_info ni; | 293 | struct node_info ni; |
287 | int err = 0, recovered = 0; | 294 | int err = 0, recovered = 0; |
288 | int ilock; | ||
289 | 295 | ||
290 | start = start_bidx_of_node(ofs_of_node(page), fi); | 296 | start = start_bidx_of_node(ofs_of_node(page), fi); |
291 | if (IS_INODE(page)) | 297 | if (IS_INODE(page)) |
@@ -293,20 +299,20 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
293 | else | 299 | else |
294 | end = start + ADDRS_PER_BLOCK; | 300 | end = start + ADDRS_PER_BLOCK; |
295 | 301 | ||
296 | ilock = mutex_lock_op(sbi); | 302 | f2fs_lock_op(sbi); |
297 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 303 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
298 | 304 | ||
299 | err = get_dnode_of_data(&dn, start, ALLOC_NODE); | 305 | err = get_dnode_of_data(&dn, start, ALLOC_NODE); |
300 | if (err) { | 306 | if (err) { |
301 | mutex_unlock_op(sbi, ilock); | 307 | f2fs_unlock_op(sbi); |
302 | return err; | 308 | return err; |
303 | } | 309 | } |
304 | 310 | ||
305 | wait_on_page_writeback(dn.node_page); | 311 | wait_on_page_writeback(dn.node_page); |
306 | 312 | ||
307 | get_node_info(sbi, dn.nid, &ni); | 313 | get_node_info(sbi, dn.nid, &ni); |
308 | BUG_ON(ni.ino != ino_of_node(page)); | 314 | f2fs_bug_on(ni.ino != ino_of_node(page)); |
309 | BUG_ON(ofs_of_node(dn.node_page) != ofs_of_node(page)); | 315 | f2fs_bug_on(ofs_of_node(dn.node_page) != ofs_of_node(page)); |
310 | 316 | ||
311 | for (; start < end; start++) { | 317 | for (; start < end; start++) { |
312 | block_t src, dest; | 318 | block_t src, dest; |
@@ -316,9 +322,9 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
316 | 322 | ||
317 | if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) { | 323 | if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) { |
318 | if (src == NULL_ADDR) { | 324 | if (src == NULL_ADDR) { |
319 | int err = reserve_new_block(&dn); | 325 | err = reserve_new_block(&dn); |
320 | /* We should not get -ENOSPC */ | 326 | /* We should not get -ENOSPC */ |
321 | BUG_ON(err); | 327 | f2fs_bug_on(err); |
322 | } | 328 | } |
323 | 329 | ||
324 | /* Check the previous node page having this index */ | 330 | /* Check the previous node page having this index */ |
@@ -349,7 +355,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
349 | recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr); | 355 | recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr); |
350 | err: | 356 | err: |
351 | f2fs_put_dnode(&dn); | 357 | f2fs_put_dnode(&dn); |
352 | mutex_unlock_op(sbi, ilock); | 358 | f2fs_unlock_op(sbi); |
353 | 359 | ||
354 | f2fs_msg(sbi->sb, KERN_NOTICE, "recover_data: ino = %lx, " | 360 | f2fs_msg(sbi->sb, KERN_NOTICE, "recover_data: ino = %lx, " |
355 | "recovered_data = %d blocks, err = %d", | 361 | "recovered_data = %d blocks, err = %d", |
@@ -419,6 +425,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) | |||
419 | { | 425 | { |
420 | struct list_head inode_list; | 426 | struct list_head inode_list; |
421 | int err; | 427 | int err; |
428 | bool need_writecp = false; | ||
422 | 429 | ||
423 | fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry", | 430 | fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry", |
424 | sizeof(struct fsync_inode_entry), NULL); | 431 | sizeof(struct fsync_inode_entry), NULL); |
@@ -428,7 +435,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) | |||
428 | INIT_LIST_HEAD(&inode_list); | 435 | INIT_LIST_HEAD(&inode_list); |
429 | 436 | ||
430 | /* step #1: find fsynced inode numbers */ | 437 | /* step #1: find fsynced inode numbers */ |
431 | sbi->por_doing = 1; | 438 | sbi->por_doing = true; |
432 | err = find_fsync_dnodes(sbi, &inode_list); | 439 | err = find_fsync_dnodes(sbi, &inode_list); |
433 | if (err) | 440 | if (err) |
434 | goto out; | 441 | goto out; |
@@ -436,14 +443,16 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) | |||
436 | if (list_empty(&inode_list)) | 443 | if (list_empty(&inode_list)) |
437 | goto out; | 444 | goto out; |
438 | 445 | ||
446 | need_writecp = true; | ||
447 | |||
439 | /* step #2: recover data */ | 448 | /* step #2: recover data */ |
440 | err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE); | 449 | err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE); |
441 | BUG_ON(!list_empty(&inode_list)); | 450 | f2fs_bug_on(!list_empty(&inode_list)); |
442 | out: | 451 | out: |
443 | destroy_fsync_dnodes(&inode_list); | 452 | destroy_fsync_dnodes(&inode_list); |
444 | kmem_cache_destroy(fsync_entry_slab); | 453 | kmem_cache_destroy(fsync_entry_slab); |
445 | sbi->por_doing = 0; | 454 | sbi->por_doing = false; |
446 | if (!err) | 455 | if (!err && need_writecp) |
447 | write_checkpoint(sbi, false); | 456 | write_checkpoint(sbi, false); |
448 | return err; | 457 | return err; |
449 | } | 458 | } |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 09af9c7b0f52..fa284d397199 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -36,6 +36,14 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi) | |||
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
39 | void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) | ||
40 | { | ||
41 | /* check the # of cached NAT entries and prefree segments */ | ||
42 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK) || | ||
43 | excess_prefree_segs(sbi)) | ||
44 | f2fs_sync_fs(sbi->sb, true); | ||
45 | } | ||
46 | |||
39 | static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, | 47 | static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, |
40 | enum dirty_type dirty_type) | 48 | enum dirty_type dirty_type) |
41 | { | 49 | { |
@@ -50,20 +58,10 @@ static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, | |||
50 | 58 | ||
51 | if (dirty_type == DIRTY) { | 59 | if (dirty_type == DIRTY) { |
52 | struct seg_entry *sentry = get_seg_entry(sbi, segno); | 60 | struct seg_entry *sentry = get_seg_entry(sbi, segno); |
53 | enum dirty_type t = DIRTY_HOT_DATA; | 61 | enum dirty_type t = sentry->type; |
54 | |||
55 | dirty_type = sentry->type; | ||
56 | |||
57 | if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type])) | ||
58 | dirty_i->nr_dirty[dirty_type]++; | ||
59 | 62 | ||
60 | /* Only one bitmap should be set */ | 63 | if (!test_and_set_bit(segno, dirty_i->dirty_segmap[t])) |
61 | for (; t <= DIRTY_COLD_NODE; t++) { | 64 | dirty_i->nr_dirty[t]++; |
62 | if (t == dirty_type) | ||
63 | continue; | ||
64 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) | ||
65 | dirty_i->nr_dirty[t]--; | ||
66 | } | ||
67 | } | 65 | } |
68 | } | 66 | } |
69 | 67 | ||
@@ -76,12 +74,11 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, | |||
76 | dirty_i->nr_dirty[dirty_type]--; | 74 | dirty_i->nr_dirty[dirty_type]--; |
77 | 75 | ||
78 | if (dirty_type == DIRTY) { | 76 | if (dirty_type == DIRTY) { |
79 | enum dirty_type t = DIRTY_HOT_DATA; | 77 | struct seg_entry *sentry = get_seg_entry(sbi, segno); |
78 | enum dirty_type t = sentry->type; | ||
80 | 79 | ||
81 | /* clear all the bitmaps */ | 80 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) |
82 | for (; t <= DIRTY_COLD_NODE; t++) | 81 | dirty_i->nr_dirty[t]--; |
83 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) | ||
84 | dirty_i->nr_dirty[t]--; | ||
85 | 82 | ||
86 | if (get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0) | 83 | if (get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0) |
87 | clear_bit(GET_SECNO(sbi, segno), | 84 | clear_bit(GET_SECNO(sbi, segno), |
@@ -142,27 +139,33 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) | |||
142 | void clear_prefree_segments(struct f2fs_sb_info *sbi) | 139 | void clear_prefree_segments(struct f2fs_sb_info *sbi) |
143 | { | 140 | { |
144 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 141 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
145 | unsigned int segno = -1; | 142 | unsigned long *prefree_map = dirty_i->dirty_segmap[PRE]; |
146 | unsigned int total_segs = TOTAL_SEGS(sbi); | 143 | unsigned int total_segs = TOTAL_SEGS(sbi); |
144 | unsigned int start = 0, end = -1; | ||
147 | 145 | ||
148 | mutex_lock(&dirty_i->seglist_lock); | 146 | mutex_lock(&dirty_i->seglist_lock); |
147 | |||
149 | while (1) { | 148 | while (1) { |
150 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, | 149 | int i; |
151 | segno + 1); | 150 | start = find_next_bit(prefree_map, total_segs, end + 1); |
152 | if (segno >= total_segs) | 151 | if (start >= total_segs) |
153 | break; | 152 | break; |
153 | end = find_next_zero_bit(prefree_map, total_segs, start + 1); | ||
154 | |||
155 | for (i = start; i < end; i++) | ||
156 | clear_bit(i, prefree_map); | ||
154 | 157 | ||
155 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE])) | 158 | dirty_i->nr_dirty[PRE] -= end - start; |
156 | dirty_i->nr_dirty[PRE]--; | 159 | |
157 | 160 | if (!test_opt(sbi, DISCARD)) | |
158 | /* Let's use trim */ | 161 | continue; |
159 | if (test_opt(sbi, DISCARD)) | 162 | |
160 | blkdev_issue_discard(sbi->sb->s_bdev, | 163 | blkdev_issue_discard(sbi->sb->s_bdev, |
161 | START_BLOCK(sbi, segno) << | 164 | START_BLOCK(sbi, start) << |
162 | sbi->log_sectors_per_block, | 165 | sbi->log_sectors_per_block, |
163 | 1 << (sbi->log_sectors_per_block + | 166 | (1 << (sbi->log_sectors_per_block + |
164 | sbi->log_blocks_per_seg), | 167 | sbi->log_blocks_per_seg)) * (end - start), |
165 | GFP_NOFS, 0); | 168 | GFP_NOFS, 0); |
166 | } | 169 | } |
167 | mutex_unlock(&dirty_i->seglist_lock); | 170 | mutex_unlock(&dirty_i->seglist_lock); |
168 | } | 171 | } |
@@ -195,7 +198,7 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) | |||
195 | new_vblocks = se->valid_blocks + del; | 198 | new_vblocks = se->valid_blocks + del; |
196 | offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1); | 199 | offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1); |
197 | 200 | ||
198 | BUG_ON((new_vblocks >> (sizeof(unsigned short) << 3) || | 201 | f2fs_bug_on((new_vblocks >> (sizeof(unsigned short) << 3) || |
199 | (new_vblocks > sbi->blocks_per_seg))); | 202 | (new_vblocks > sbi->blocks_per_seg))); |
200 | 203 | ||
201 | se->valid_blocks = new_vblocks; | 204 | se->valid_blocks = new_vblocks; |
@@ -235,7 +238,7 @@ void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr) | |||
235 | unsigned int segno = GET_SEGNO(sbi, addr); | 238 | unsigned int segno = GET_SEGNO(sbi, addr); |
236 | struct sit_info *sit_i = SIT_I(sbi); | 239 | struct sit_info *sit_i = SIT_I(sbi); |
237 | 240 | ||
238 | BUG_ON(addr == NULL_ADDR); | 241 | f2fs_bug_on(addr == NULL_ADDR); |
239 | if (addr == NEW_ADDR) | 242 | if (addr == NEW_ADDR) |
240 | return; | 243 | return; |
241 | 244 | ||
@@ -267,9 +270,8 @@ static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, | |||
267 | */ | 270 | */ |
268 | int npages_for_summary_flush(struct f2fs_sb_info *sbi) | 271 | int npages_for_summary_flush(struct f2fs_sb_info *sbi) |
269 | { | 272 | { |
270 | int total_size_bytes = 0; | ||
271 | int valid_sum_count = 0; | 273 | int valid_sum_count = 0; |
272 | int i, sum_space; | 274 | int i, sum_in_page; |
273 | 275 | ||
274 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { | 276 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { |
275 | if (sbi->ckpt->alloc_type[i] == SSR) | 277 | if (sbi->ckpt->alloc_type[i] == SSR) |
@@ -278,13 +280,12 @@ int npages_for_summary_flush(struct f2fs_sb_info *sbi) | |||
278 | valid_sum_count += curseg_blkoff(sbi, i); | 280 | valid_sum_count += curseg_blkoff(sbi, i); |
279 | } | 281 | } |
280 | 282 | ||
281 | total_size_bytes = valid_sum_count * (SUMMARY_SIZE + 1) | 283 | sum_in_page = (PAGE_CACHE_SIZE - 2 * SUM_JOURNAL_SIZE - |
282 | + sizeof(struct nat_journal) + 2 | 284 | SUM_FOOTER_SIZE) / SUMMARY_SIZE; |
283 | + sizeof(struct sit_journal) + 2; | 285 | if (valid_sum_count <= sum_in_page) |
284 | sum_space = PAGE_CACHE_SIZE - SUM_FOOTER_SIZE; | ||
285 | if (total_size_bytes < sum_space) | ||
286 | return 1; | 286 | return 1; |
287 | else if (total_size_bytes < 2 * sum_space) | 287 | else if ((valid_sum_count - sum_in_page) <= |
288 | (PAGE_CACHE_SIZE - SUM_FOOTER_SIZE) / SUMMARY_SIZE) | ||
288 | return 2; | 289 | return 2; |
289 | return 3; | 290 | return 3; |
290 | } | 291 | } |
@@ -350,7 +351,7 @@ find_other_zone: | |||
350 | if (dir == ALLOC_RIGHT) { | 351 | if (dir == ALLOC_RIGHT) { |
351 | secno = find_next_zero_bit(free_i->free_secmap, | 352 | secno = find_next_zero_bit(free_i->free_secmap, |
352 | TOTAL_SECS(sbi), 0); | 353 | TOTAL_SECS(sbi), 0); |
353 | BUG_ON(secno >= TOTAL_SECS(sbi)); | 354 | f2fs_bug_on(secno >= TOTAL_SECS(sbi)); |
354 | } else { | 355 | } else { |
355 | go_left = 1; | 356 | go_left = 1; |
356 | left_start = hint - 1; | 357 | left_start = hint - 1; |
@@ -366,7 +367,7 @@ find_other_zone: | |||
366 | } | 367 | } |
367 | left_start = find_next_zero_bit(free_i->free_secmap, | 368 | left_start = find_next_zero_bit(free_i->free_secmap, |
368 | TOTAL_SECS(sbi), 0); | 369 | TOTAL_SECS(sbi), 0); |
369 | BUG_ON(left_start >= TOTAL_SECS(sbi)); | 370 | f2fs_bug_on(left_start >= TOTAL_SECS(sbi)); |
370 | break; | 371 | break; |
371 | } | 372 | } |
372 | secno = left_start; | 373 | secno = left_start; |
@@ -405,7 +406,7 @@ skip_left: | |||
405 | } | 406 | } |
406 | got_it: | 407 | got_it: |
407 | /* set it as dirty segment in free segmap */ | 408 | /* set it as dirty segment in free segmap */ |
408 | BUG_ON(test_bit(segno, free_i->free_segmap)); | 409 | f2fs_bug_on(test_bit(segno, free_i->free_segmap)); |
409 | __set_inuse(sbi, segno); | 410 | __set_inuse(sbi, segno); |
410 | *newseg = segno; | 411 | *newseg = segno; |
411 | write_unlock(&free_i->segmap_lock); | 412 | write_unlock(&free_i->segmap_lock); |
@@ -550,9 +551,8 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi, | |||
550 | change_curseg(sbi, type, true); | 551 | change_curseg(sbi, type, true); |
551 | else | 552 | else |
552 | new_curseg(sbi, type, false); | 553 | new_curseg(sbi, type, false); |
553 | #ifdef CONFIG_F2FS_STAT_FS | 554 | |
554 | sbi->segment_count[curseg->alloc_type]++; | 555 | stat_inc_seg_type(sbi, curseg); |
555 | #endif | ||
556 | } | 556 | } |
557 | 557 | ||
558 | void allocate_new_segments(struct f2fs_sb_info *sbi) | 558 | void allocate_new_segments(struct f2fs_sb_info *sbi) |
@@ -597,6 +597,11 @@ static void f2fs_end_io_write(struct bio *bio, int err) | |||
597 | 597 | ||
598 | if (p->is_sync) | 598 | if (p->is_sync) |
599 | complete(p->wait); | 599 | complete(p->wait); |
600 | |||
601 | if (!get_pages(p->sbi, F2FS_WRITEBACK) && | ||
602 | !list_empty(&p->sbi->cp_wait.task_list)) | ||
603 | wake_up(&p->sbi->cp_wait); | ||
604 | |||
600 | kfree(p); | 605 | kfree(p); |
601 | bio_put(bio); | 606 | bio_put(bio); |
602 | } | 607 | } |
@@ -657,6 +662,7 @@ static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page, | |||
657 | block_t blk_addr, enum page_type type) | 662 | block_t blk_addr, enum page_type type) |
658 | { | 663 | { |
659 | struct block_device *bdev = sbi->sb->s_bdev; | 664 | struct block_device *bdev = sbi->sb->s_bdev; |
665 | int bio_blocks; | ||
660 | 666 | ||
661 | verify_block_addr(sbi, blk_addr); | 667 | verify_block_addr(sbi, blk_addr); |
662 | 668 | ||
@@ -676,7 +682,8 @@ retry: | |||
676 | goto retry; | 682 | goto retry; |
677 | } | 683 | } |
678 | 684 | ||
679 | sbi->bio[type] = f2fs_bio_alloc(bdev, max_hw_blocks(sbi)); | 685 | bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); |
686 | sbi->bio[type] = f2fs_bio_alloc(bdev, bio_blocks); | ||
680 | sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); | 687 | sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); |
681 | sbi->bio[type]->bi_private = priv; | 688 | sbi->bio[type]->bi_private = priv; |
682 | /* | 689 | /* |
@@ -771,7 +778,7 @@ static int __get_segment_type(struct page *page, enum page_type p_type) | |||
771 | return __get_segment_type_4(page, p_type); | 778 | return __get_segment_type_4(page, p_type); |
772 | } | 779 | } |
773 | /* NR_CURSEG_TYPE(6) logs by default */ | 780 | /* NR_CURSEG_TYPE(6) logs by default */ |
774 | BUG_ON(sbi->active_logs != NR_CURSEG_TYPE); | 781 | f2fs_bug_on(sbi->active_logs != NR_CURSEG_TYPE); |
775 | return __get_segment_type_6(page, p_type); | 782 | return __get_segment_type_6(page, p_type); |
776 | } | 783 | } |
777 | 784 | ||
@@ -801,9 +808,8 @@ static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, | |||
801 | 808 | ||
802 | mutex_lock(&sit_i->sentry_lock); | 809 | mutex_lock(&sit_i->sentry_lock); |
803 | __refresh_next_blkoff(sbi, curseg); | 810 | __refresh_next_blkoff(sbi, curseg); |
804 | #ifdef CONFIG_F2FS_STAT_FS | 811 | |
805 | sbi->block_count[curseg->alloc_type]++; | 812 | stat_inc_block_count(sbi, curseg); |
806 | #endif | ||
807 | 813 | ||
808 | /* | 814 | /* |
809 | * SIT information should be updated before segment allocation, | 815 | * SIT information should be updated before segment allocation, |
@@ -849,7 +855,7 @@ void write_data_page(struct inode *inode, struct page *page, | |||
849 | struct f2fs_summary sum; | 855 | struct f2fs_summary sum; |
850 | struct node_info ni; | 856 | struct node_info ni; |
851 | 857 | ||
852 | BUG_ON(old_blkaddr == NULL_ADDR); | 858 | f2fs_bug_on(old_blkaddr == NULL_ADDR); |
853 | get_node_info(sbi, dn->nid, &ni); | 859 | get_node_info(sbi, dn->nid, &ni); |
854 | set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); | 860 | set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); |
855 | 861 | ||
@@ -1122,8 +1128,6 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr) | |||
1122 | SUM_JOURNAL_SIZE); | 1128 | SUM_JOURNAL_SIZE); |
1123 | written_size += SUM_JOURNAL_SIZE; | 1129 | written_size += SUM_JOURNAL_SIZE; |
1124 | 1130 | ||
1125 | set_page_dirty(page); | ||
1126 | |||
1127 | /* Step 3: write summary entries */ | 1131 | /* Step 3: write summary entries */ |
1128 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { | 1132 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { |
1129 | unsigned short blkoff; | 1133 | unsigned short blkoff; |
@@ -1142,18 +1146,20 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr) | |||
1142 | summary = (struct f2fs_summary *)(kaddr + written_size); | 1146 | summary = (struct f2fs_summary *)(kaddr + written_size); |
1143 | *summary = seg_i->sum_blk->entries[j]; | 1147 | *summary = seg_i->sum_blk->entries[j]; |
1144 | written_size += SUMMARY_SIZE; | 1148 | written_size += SUMMARY_SIZE; |
1145 | set_page_dirty(page); | ||
1146 | 1149 | ||
1147 | if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE - | 1150 | if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE - |
1148 | SUM_FOOTER_SIZE) | 1151 | SUM_FOOTER_SIZE) |
1149 | continue; | 1152 | continue; |
1150 | 1153 | ||
1154 | set_page_dirty(page); | ||
1151 | f2fs_put_page(page, 1); | 1155 | f2fs_put_page(page, 1); |
1152 | page = NULL; | 1156 | page = NULL; |
1153 | } | 1157 | } |
1154 | } | 1158 | } |
1155 | if (page) | 1159 | if (page) { |
1160 | set_page_dirty(page); | ||
1156 | f2fs_put_page(page, 1); | 1161 | f2fs_put_page(page, 1); |
1162 | } | ||
1157 | } | 1163 | } |
1158 | 1164 | ||
1159 | static void write_normal_summaries(struct f2fs_sb_info *sbi, | 1165 | static void write_normal_summaries(struct f2fs_sb_info *sbi, |
@@ -1239,7 +1245,7 @@ static struct page *get_next_sit_page(struct f2fs_sb_info *sbi, | |||
1239 | /* get current sit block page without lock */ | 1245 | /* get current sit block page without lock */ |
1240 | src_page = get_meta_page(sbi, src_off); | 1246 | src_page = get_meta_page(sbi, src_off); |
1241 | dst_page = grab_meta_page(sbi, dst_off); | 1247 | dst_page = grab_meta_page(sbi, dst_off); |
1242 | BUG_ON(PageDirty(src_page)); | 1248 | f2fs_bug_on(PageDirty(src_page)); |
1243 | 1249 | ||
1244 | src_addr = page_address(src_page); | 1250 | src_addr = page_address(src_page); |
1245 | dst_addr = page_address(dst_page); | 1251 | dst_addr = page_address(dst_page); |
@@ -1271,9 +1277,9 @@ static bool flush_sits_in_journal(struct f2fs_sb_info *sbi) | |||
1271 | __mark_sit_entry_dirty(sbi, segno); | 1277 | __mark_sit_entry_dirty(sbi, segno); |
1272 | } | 1278 | } |
1273 | update_sits_in_cursum(sum, -sits_in_cursum(sum)); | 1279 | update_sits_in_cursum(sum, -sits_in_cursum(sum)); |
1274 | return 1; | 1280 | return true; |
1275 | } | 1281 | } |
1276 | return 0; | 1282 | return false; |
1277 | } | 1283 | } |
1278 | 1284 | ||
1279 | /* | 1285 | /* |
@@ -1637,6 +1643,7 @@ int build_segment_manager(struct f2fs_sb_info *sbi) | |||
1637 | sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count); | 1643 | sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count); |
1638 | sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main); | 1644 | sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main); |
1639 | sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr); | 1645 | sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr); |
1646 | sm_info->rec_prefree_segments = DEF_RECLAIM_PREFREE_SEGMENTS; | ||
1640 | 1647 | ||
1641 | err = build_sit_info(sbi); | 1648 | err = build_sit_info(sbi); |
1642 | if (err) | 1649 | if (err) |
@@ -1744,6 +1751,8 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi) | |||
1744 | void destroy_segment_manager(struct f2fs_sb_info *sbi) | 1751 | void destroy_segment_manager(struct f2fs_sb_info *sbi) |
1745 | { | 1752 | { |
1746 | struct f2fs_sm_info *sm_info = SM_I(sbi); | 1753 | struct f2fs_sm_info *sm_info = SM_I(sbi); |
1754 | if (!sm_info) | ||
1755 | return; | ||
1747 | destroy_dirty_segmap(sbi); | 1756 | destroy_dirty_segmap(sbi); |
1748 | destroy_curseg(sbi); | 1757 | destroy_curseg(sbi); |
1749 | destroy_free_segmap(sbi); | 1758 | destroy_free_segmap(sbi); |
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index bdd10eab8c40..269f690b4e24 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h | |||
@@ -14,6 +14,8 @@ | |||
14 | #define NULL_SEGNO ((unsigned int)(~0)) | 14 | #define NULL_SEGNO ((unsigned int)(~0)) |
15 | #define NULL_SECNO ((unsigned int)(~0)) | 15 | #define NULL_SECNO ((unsigned int)(~0)) |
16 | 16 | ||
17 | #define DEF_RECLAIM_PREFREE_SEGMENTS 100 /* 200MB of prefree segments */ | ||
18 | |||
17 | /* L: Logical segment # in volume, R: Relative segment # in main area */ | 19 | /* L: Logical segment # in volume, R: Relative segment # in main area */ |
18 | #define GET_L2R_SEGNO(free_i, segno) (segno - free_i->start_segno) | 20 | #define GET_L2R_SEGNO(free_i, segno) (segno - free_i->start_segno) |
19 | #define GET_R2L_SEGNO(free_i, segno) (segno + free_i->start_segno) | 21 | #define GET_R2L_SEGNO(free_i, segno) (segno + free_i->start_segno) |
@@ -90,6 +92,8 @@ | |||
90 | (blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE)) | 92 | (blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE)) |
91 | #define SECTOR_TO_BLOCK(sbi, sectors) \ | 93 | #define SECTOR_TO_BLOCK(sbi, sectors) \ |
92 | (sectors >> ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE)) | 94 | (sectors >> ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE)) |
95 | #define MAX_BIO_BLOCKS(max_hw_blocks) \ | ||
96 | (min((int)max_hw_blocks, BIO_MAX_PAGES)) | ||
93 | 97 | ||
94 | /* during checkpoint, bio_private is used to synchronize the last bio */ | 98 | /* during checkpoint, bio_private is used to synchronize the last bio */ |
95 | struct bio_private { | 99 | struct bio_private { |
@@ -470,6 +474,11 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed) | |||
470 | reserved_sections(sbi))); | 474 | reserved_sections(sbi))); |
471 | } | 475 | } |
472 | 476 | ||
477 | static inline bool excess_prefree_segs(struct f2fs_sb_info *sbi) | ||
478 | { | ||
479 | return (prefree_segments(sbi) > SM_I(sbi)->rec_prefree_segments); | ||
480 | } | ||
481 | |||
473 | static inline int utilization(struct f2fs_sb_info *sbi) | 482 | static inline int utilization(struct f2fs_sb_info *sbi) |
474 | { | 483 | { |
475 | return div_u64((u64)valid_user_blocks(sbi) * 100, sbi->user_block_count); | 484 | return div_u64((u64)valid_user_blocks(sbi) * 100, sbi->user_block_count); |
@@ -513,16 +522,13 @@ static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type) | |||
513 | return curseg->next_blkoff; | 522 | return curseg->next_blkoff; |
514 | } | 523 | } |
515 | 524 | ||
525 | #ifdef CONFIG_F2FS_CHECK_FS | ||
516 | static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) | 526 | static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) |
517 | { | 527 | { |
518 | unsigned int end_segno = SM_I(sbi)->segment_count - 1; | 528 | unsigned int end_segno = SM_I(sbi)->segment_count - 1; |
519 | BUG_ON(segno > end_segno); | 529 | BUG_ON(segno > end_segno); |
520 | } | 530 | } |
521 | 531 | ||
522 | /* | ||
523 | * This function is used for only debugging. | ||
524 | * NOTE: In future, we have to remove this function. | ||
525 | */ | ||
526 | static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) | 532 | static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) |
527 | { | 533 | { |
528 | struct f2fs_sm_info *sm_info = SM_I(sbi); | 534 | struct f2fs_sm_info *sm_info = SM_I(sbi); |
@@ -541,8 +547,9 @@ static inline void check_block_count(struct f2fs_sb_info *sbi, | |||
541 | { | 547 | { |
542 | struct f2fs_sm_info *sm_info = SM_I(sbi); | 548 | struct f2fs_sm_info *sm_info = SM_I(sbi); |
543 | unsigned int end_segno = sm_info->segment_count - 1; | 549 | unsigned int end_segno = sm_info->segment_count - 1; |
550 | bool is_valid = test_bit_le(0, raw_sit->valid_map) ? true : false; | ||
544 | int valid_blocks = 0; | 551 | int valid_blocks = 0; |
545 | int i; | 552 | int cur_pos = 0, next_pos; |
546 | 553 | ||
547 | /* check segment usage */ | 554 | /* check segment usage */ |
548 | BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg); | 555 | BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg); |
@@ -551,11 +558,26 @@ static inline void check_block_count(struct f2fs_sb_info *sbi, | |||
551 | BUG_ON(segno > end_segno); | 558 | BUG_ON(segno > end_segno); |
552 | 559 | ||
553 | /* check bitmap with valid block count */ | 560 | /* check bitmap with valid block count */ |
554 | for (i = 0; i < sbi->blocks_per_seg; i++) | 561 | do { |
555 | if (f2fs_test_bit(i, raw_sit->valid_map)) | 562 | if (is_valid) { |
556 | valid_blocks++; | 563 | next_pos = find_next_zero_bit_le(&raw_sit->valid_map, |
564 | sbi->blocks_per_seg, | ||
565 | cur_pos); | ||
566 | valid_blocks += next_pos - cur_pos; | ||
567 | } else | ||
568 | next_pos = find_next_bit_le(&raw_sit->valid_map, | ||
569 | sbi->blocks_per_seg, | ||
570 | cur_pos); | ||
571 | cur_pos = next_pos; | ||
572 | is_valid = !is_valid; | ||
573 | } while (cur_pos < sbi->blocks_per_seg); | ||
557 | BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks); | 574 | BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks); |
558 | } | 575 | } |
576 | #else | ||
577 | #define check_seg_range(sbi, segno) | ||
578 | #define verify_block_addr(sbi, blk_addr) | ||
579 | #define check_block_count(sbi, segno, raw_sit) | ||
580 | #endif | ||
559 | 581 | ||
560 | static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, | 582 | static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, |
561 | unsigned int start) | 583 | unsigned int start) |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 13d0a0fe49dd..bafff72de8e8 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -43,7 +43,9 @@ enum { | |||
43 | Opt_disable_roll_forward, | 43 | Opt_disable_roll_forward, |
44 | Opt_discard, | 44 | Opt_discard, |
45 | Opt_noheap, | 45 | Opt_noheap, |
46 | Opt_user_xattr, | ||
46 | Opt_nouser_xattr, | 47 | Opt_nouser_xattr, |
48 | Opt_acl, | ||
47 | Opt_noacl, | 49 | Opt_noacl, |
48 | Opt_active_logs, | 50 | Opt_active_logs, |
49 | Opt_disable_ext_identify, | 51 | Opt_disable_ext_identify, |
@@ -56,7 +58,9 @@ static match_table_t f2fs_tokens = { | |||
56 | {Opt_disable_roll_forward, "disable_roll_forward"}, | 58 | {Opt_disable_roll_forward, "disable_roll_forward"}, |
57 | {Opt_discard, "discard"}, | 59 | {Opt_discard, "discard"}, |
58 | {Opt_noheap, "no_heap"}, | 60 | {Opt_noheap, "no_heap"}, |
61 | {Opt_user_xattr, "user_xattr"}, | ||
59 | {Opt_nouser_xattr, "nouser_xattr"}, | 62 | {Opt_nouser_xattr, "nouser_xattr"}, |
63 | {Opt_acl, "acl"}, | ||
60 | {Opt_noacl, "noacl"}, | 64 | {Opt_noacl, "noacl"}, |
61 | {Opt_active_logs, "active_logs=%u"}, | 65 | {Opt_active_logs, "active_logs=%u"}, |
62 | {Opt_disable_ext_identify, "disable_ext_identify"}, | 66 | {Opt_disable_ext_identify, "disable_ext_identify"}, |
@@ -65,24 +69,40 @@ static match_table_t f2fs_tokens = { | |||
65 | }; | 69 | }; |
66 | 70 | ||
67 | /* Sysfs support for f2fs */ | 71 | /* Sysfs support for f2fs */ |
72 | enum { | ||
73 | GC_THREAD, /* struct f2fs_gc_thread */ | ||
74 | SM_INFO, /* struct f2fs_sm_info */ | ||
75 | }; | ||
76 | |||
68 | struct f2fs_attr { | 77 | struct f2fs_attr { |
69 | struct attribute attr; | 78 | struct attribute attr; |
70 | ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *); | 79 | ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *); |
71 | ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *, | 80 | ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *, |
72 | const char *, size_t); | 81 | const char *, size_t); |
82 | int struct_type; | ||
73 | int offset; | 83 | int offset; |
74 | }; | 84 | }; |
75 | 85 | ||
86 | static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) | ||
87 | { | ||
88 | if (struct_type == GC_THREAD) | ||
89 | return (unsigned char *)sbi->gc_thread; | ||
90 | else if (struct_type == SM_INFO) | ||
91 | return (unsigned char *)SM_I(sbi); | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
76 | static ssize_t f2fs_sbi_show(struct f2fs_attr *a, | 95 | static ssize_t f2fs_sbi_show(struct f2fs_attr *a, |
77 | struct f2fs_sb_info *sbi, char *buf) | 96 | struct f2fs_sb_info *sbi, char *buf) |
78 | { | 97 | { |
79 | struct f2fs_gc_kthread *gc_kth = sbi->gc_thread; | 98 | unsigned char *ptr = NULL; |
80 | unsigned int *ui; | 99 | unsigned int *ui; |
81 | 100 | ||
82 | if (!gc_kth) | 101 | ptr = __struct_ptr(sbi, a->struct_type); |
102 | if (!ptr) | ||
83 | return -EINVAL; | 103 | return -EINVAL; |
84 | 104 | ||
85 | ui = (unsigned int *)(((char *)gc_kth) + a->offset); | 105 | ui = (unsigned int *)(ptr + a->offset); |
86 | 106 | ||
87 | return snprintf(buf, PAGE_SIZE, "%u\n", *ui); | 107 | return snprintf(buf, PAGE_SIZE, "%u\n", *ui); |
88 | } | 108 | } |
@@ -91,15 +111,16 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, | |||
91 | struct f2fs_sb_info *sbi, | 111 | struct f2fs_sb_info *sbi, |
92 | const char *buf, size_t count) | 112 | const char *buf, size_t count) |
93 | { | 113 | { |
94 | struct f2fs_gc_kthread *gc_kth = sbi->gc_thread; | 114 | unsigned char *ptr; |
95 | unsigned long t; | 115 | unsigned long t; |
96 | unsigned int *ui; | 116 | unsigned int *ui; |
97 | ssize_t ret; | 117 | ssize_t ret; |
98 | 118 | ||
99 | if (!gc_kth) | 119 | ptr = __struct_ptr(sbi, a->struct_type); |
120 | if (!ptr) | ||
100 | return -EINVAL; | 121 | return -EINVAL; |
101 | 122 | ||
102 | ui = (unsigned int *)(((char *)gc_kth) + a->offset); | 123 | ui = (unsigned int *)(ptr + a->offset); |
103 | 124 | ||
104 | ret = kstrtoul(skip_spaces(buf), 0, &t); | 125 | ret = kstrtoul(skip_spaces(buf), 0, &t); |
105 | if (ret < 0) | 126 | if (ret < 0) |
@@ -135,21 +156,25 @@ static void f2fs_sb_release(struct kobject *kobj) | |||
135 | complete(&sbi->s_kobj_unregister); | 156 | complete(&sbi->s_kobj_unregister); |
136 | } | 157 | } |
137 | 158 | ||
138 | #define F2FS_ATTR_OFFSET(_name, _mode, _show, _store, _elname) \ | 159 | #define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \ |
139 | static struct f2fs_attr f2fs_attr_##_name = { \ | 160 | static struct f2fs_attr f2fs_attr_##_name = { \ |
140 | .attr = {.name = __stringify(_name), .mode = _mode }, \ | 161 | .attr = {.name = __stringify(_name), .mode = _mode }, \ |
141 | .show = _show, \ | 162 | .show = _show, \ |
142 | .store = _store, \ | 163 | .store = _store, \ |
143 | .offset = offsetof(struct f2fs_gc_kthread, _elname), \ | 164 | .struct_type = _struct_type, \ |
165 | .offset = _offset \ | ||
144 | } | 166 | } |
145 | 167 | ||
146 | #define F2FS_RW_ATTR(name, elname) \ | 168 | #define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \ |
147 | F2FS_ATTR_OFFSET(name, 0644, f2fs_sbi_show, f2fs_sbi_store, elname) | 169 | F2FS_ATTR_OFFSET(struct_type, name, 0644, \ |
170 | f2fs_sbi_show, f2fs_sbi_store, \ | ||
171 | offsetof(struct struct_name, elname)) | ||
148 | 172 | ||
149 | F2FS_RW_ATTR(gc_min_sleep_time, min_sleep_time); | 173 | F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time); |
150 | F2FS_RW_ATTR(gc_max_sleep_time, max_sleep_time); | 174 | F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time); |
151 | F2FS_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time); | 175 | F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time); |
152 | F2FS_RW_ATTR(gc_idle, gc_idle); | 176 | F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle); |
177 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); | ||
153 | 178 | ||
154 | #define ATTR_LIST(name) (&f2fs_attr_##name.attr) | 179 | #define ATTR_LIST(name) (&f2fs_attr_##name.attr) |
155 | static struct attribute *f2fs_attrs[] = { | 180 | static struct attribute *f2fs_attrs[] = { |
@@ -157,6 +182,7 @@ static struct attribute *f2fs_attrs[] = { | |||
157 | ATTR_LIST(gc_max_sleep_time), | 182 | ATTR_LIST(gc_max_sleep_time), |
158 | ATTR_LIST(gc_no_gc_sleep_time), | 183 | ATTR_LIST(gc_no_gc_sleep_time), |
159 | ATTR_LIST(gc_idle), | 184 | ATTR_LIST(gc_idle), |
185 | ATTR_LIST(reclaim_segments), | ||
160 | NULL, | 186 | NULL, |
161 | }; | 187 | }; |
162 | 188 | ||
@@ -237,6 +263,9 @@ static int parse_options(struct super_block *sb, char *options) | |||
237 | set_opt(sbi, NOHEAP); | 263 | set_opt(sbi, NOHEAP); |
238 | break; | 264 | break; |
239 | #ifdef CONFIG_F2FS_FS_XATTR | 265 | #ifdef CONFIG_F2FS_FS_XATTR |
266 | case Opt_user_xattr: | ||
267 | set_opt(sbi, XATTR_USER); | ||
268 | break; | ||
240 | case Opt_nouser_xattr: | 269 | case Opt_nouser_xattr: |
241 | clear_opt(sbi, XATTR_USER); | 270 | clear_opt(sbi, XATTR_USER); |
242 | break; | 271 | break; |
@@ -244,6 +273,10 @@ static int parse_options(struct super_block *sb, char *options) | |||
244 | set_opt(sbi, INLINE_XATTR); | 273 | set_opt(sbi, INLINE_XATTR); |
245 | break; | 274 | break; |
246 | #else | 275 | #else |
276 | case Opt_user_xattr: | ||
277 | f2fs_msg(sb, KERN_INFO, | ||
278 | "user_xattr options not supported"); | ||
279 | break; | ||
247 | case Opt_nouser_xattr: | 280 | case Opt_nouser_xattr: |
248 | f2fs_msg(sb, KERN_INFO, | 281 | f2fs_msg(sb, KERN_INFO, |
249 | "nouser_xattr options not supported"); | 282 | "nouser_xattr options not supported"); |
@@ -254,10 +287,16 @@ static int parse_options(struct super_block *sb, char *options) | |||
254 | break; | 287 | break; |
255 | #endif | 288 | #endif |
256 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | 289 | #ifdef CONFIG_F2FS_FS_POSIX_ACL |
290 | case Opt_acl: | ||
291 | set_opt(sbi, POSIX_ACL); | ||
292 | break; | ||
257 | case Opt_noacl: | 293 | case Opt_noacl: |
258 | clear_opt(sbi, POSIX_ACL); | 294 | clear_opt(sbi, POSIX_ACL); |
259 | break; | 295 | break; |
260 | #else | 296 | #else |
297 | case Opt_acl: | ||
298 | f2fs_msg(sb, KERN_INFO, "acl options not supported"); | ||
299 | break; | ||
261 | case Opt_noacl: | 300 | case Opt_noacl: |
262 | f2fs_msg(sb, KERN_INFO, "noacl options not supported"); | 301 | f2fs_msg(sb, KERN_INFO, "noacl options not supported"); |
263 | break; | 302 | break; |
@@ -355,7 +394,9 @@ static void f2fs_put_super(struct super_block *sb) | |||
355 | f2fs_destroy_stats(sbi); | 394 | f2fs_destroy_stats(sbi); |
356 | stop_gc_thread(sbi); | 395 | stop_gc_thread(sbi); |
357 | 396 | ||
358 | write_checkpoint(sbi, true); | 397 | /* We don't need to do checkpoint when it's clean */ |
398 | if (sbi->s_dirty && get_pages(sbi, F2FS_DIRTY_NODES)) | ||
399 | write_checkpoint(sbi, true); | ||
359 | 400 | ||
360 | iput(sbi->node_inode); | 401 | iput(sbi->node_inode); |
361 | iput(sbi->meta_inode); | 402 | iput(sbi->meta_inode); |
@@ -727,30 +768,47 @@ static void init_sb_info(struct f2fs_sb_info *sbi) | |||
727 | atomic_set(&sbi->nr_pages[i], 0); | 768 | atomic_set(&sbi->nr_pages[i], 0); |
728 | } | 769 | } |
729 | 770 | ||
730 | static int validate_superblock(struct super_block *sb, | 771 | /* |
731 | struct f2fs_super_block **raw_super, | 772 | * Read f2fs raw super block. |
732 | struct buffer_head **raw_super_buf, sector_t block) | 773 | * Because we have two copies of super block, so read the first one at first, |
774 | * if the first one is invalid, move to read the second one. | ||
775 | */ | ||
776 | static int read_raw_super_block(struct super_block *sb, | ||
777 | struct f2fs_super_block **raw_super, | ||
778 | struct buffer_head **raw_super_buf) | ||
733 | { | 779 | { |
734 | const char *super = (block == 0 ? "first" : "second"); | 780 | int block = 0; |
735 | 781 | ||
736 | /* read f2fs raw super block */ | 782 | retry: |
737 | *raw_super_buf = sb_bread(sb, block); | 783 | *raw_super_buf = sb_bread(sb, block); |
738 | if (!*raw_super_buf) { | 784 | if (!*raw_super_buf) { |
739 | f2fs_msg(sb, KERN_ERR, "unable to read %s superblock", | 785 | f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock", |
740 | super); | 786 | block + 1); |
741 | return -EIO; | 787 | if (block == 0) { |
788 | block++; | ||
789 | goto retry; | ||
790 | } else { | ||
791 | return -EIO; | ||
792 | } | ||
742 | } | 793 | } |
743 | 794 | ||
744 | *raw_super = (struct f2fs_super_block *) | 795 | *raw_super = (struct f2fs_super_block *) |
745 | ((char *)(*raw_super_buf)->b_data + F2FS_SUPER_OFFSET); | 796 | ((char *)(*raw_super_buf)->b_data + F2FS_SUPER_OFFSET); |
746 | 797 | ||
747 | /* sanity checking of raw super */ | 798 | /* sanity checking of raw super */ |
748 | if (!sanity_check_raw_super(sb, *raw_super)) | 799 | if (sanity_check_raw_super(sb, *raw_super)) { |
749 | return 0; | 800 | brelse(*raw_super_buf); |
801 | f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem " | ||
802 | "in %dth superblock", block + 1); | ||
803 | if(block == 0) { | ||
804 | block++; | ||
805 | goto retry; | ||
806 | } else { | ||
807 | return -EINVAL; | ||
808 | } | ||
809 | } | ||
750 | 810 | ||
751 | f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem " | 811 | return 0; |
752 | "in %s superblock", super); | ||
753 | return -EINVAL; | ||
754 | } | 812 | } |
755 | 813 | ||
756 | static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | 814 | static int f2fs_fill_super(struct super_block *sb, void *data, int silent) |
@@ -760,7 +818,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
760 | struct buffer_head *raw_super_buf; | 818 | struct buffer_head *raw_super_buf; |
761 | struct inode *root; | 819 | struct inode *root; |
762 | long err = -EINVAL; | 820 | long err = -EINVAL; |
763 | int i; | ||
764 | 821 | ||
765 | /* allocate memory for f2fs-specific super block info */ | 822 | /* allocate memory for f2fs-specific super block info */ |
766 | sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL); | 823 | sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL); |
@@ -773,14 +830,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
773 | goto free_sbi; | 830 | goto free_sbi; |
774 | } | 831 | } |
775 | 832 | ||
776 | err = validate_superblock(sb, &raw_super, &raw_super_buf, 0); | 833 | err = read_raw_super_block(sb, &raw_super, &raw_super_buf); |
777 | if (err) { | 834 | if (err) |
778 | brelse(raw_super_buf); | 835 | goto free_sbi; |
779 | /* check secondary superblock when primary failed */ | 836 | |
780 | err = validate_superblock(sb, &raw_super, &raw_super_buf, 1); | ||
781 | if (err) | ||
782 | goto free_sb_buf; | ||
783 | } | ||
784 | sb->s_fs_info = sbi; | 837 | sb->s_fs_info = sbi; |
785 | /* init some FS parameters */ | 838 | /* init some FS parameters */ |
786 | sbi->active_logs = NR_CURSEG_TYPE; | 839 | sbi->active_logs = NR_CURSEG_TYPE; |
@@ -818,12 +871,12 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
818 | mutex_init(&sbi->gc_mutex); | 871 | mutex_init(&sbi->gc_mutex); |
819 | mutex_init(&sbi->writepages); | 872 | mutex_init(&sbi->writepages); |
820 | mutex_init(&sbi->cp_mutex); | 873 | mutex_init(&sbi->cp_mutex); |
821 | for (i = 0; i < NR_GLOBAL_LOCKS; i++) | ||
822 | mutex_init(&sbi->fs_lock[i]); | ||
823 | mutex_init(&sbi->node_write); | 874 | mutex_init(&sbi->node_write); |
824 | sbi->por_doing = 0; | 875 | sbi->por_doing = false; |
825 | spin_lock_init(&sbi->stat_lock); | 876 | spin_lock_init(&sbi->stat_lock); |
826 | init_rwsem(&sbi->bio_sem); | 877 | init_rwsem(&sbi->bio_sem); |
878 | init_rwsem(&sbi->cp_rwsem); | ||
879 | init_waitqueue_head(&sbi->cp_wait); | ||
827 | init_sb_info(sbi); | 880 | init_sb_info(sbi); |
828 | 881 | ||
829 | /* get an inode for meta space */ | 882 | /* get an inode for meta space */ |
@@ -922,12 +975,12 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
922 | /* After POR, we can run background GC thread.*/ | 975 | /* After POR, we can run background GC thread.*/ |
923 | err = start_gc_thread(sbi); | 976 | err = start_gc_thread(sbi); |
924 | if (err) | 977 | if (err) |
925 | goto fail; | 978 | goto free_gc; |
926 | } | 979 | } |
927 | 980 | ||
928 | err = f2fs_build_stats(sbi); | 981 | err = f2fs_build_stats(sbi); |
929 | if (err) | 982 | if (err) |
930 | goto fail; | 983 | goto free_gc; |
931 | 984 | ||
932 | if (f2fs_proc_root) | 985 | if (f2fs_proc_root) |
933 | sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); | 986 | sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); |
@@ -953,6 +1006,12 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
953 | 1006 | ||
954 | return 0; | 1007 | return 0; |
955 | fail: | 1008 | fail: |
1009 | if (sbi->s_proc) { | ||
1010 | remove_proc_entry("segment_info", sbi->s_proc); | ||
1011 | remove_proc_entry(sb->s_id, f2fs_proc_root); | ||
1012 | } | ||
1013 | f2fs_destroy_stats(sbi); | ||
1014 | free_gc: | ||
956 | stop_gc_thread(sbi); | 1015 | stop_gc_thread(sbi); |
957 | free_root_inode: | 1016 | free_root_inode: |
958 | dput(sb->s_root); | 1017 | dput(sb->s_root); |
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 1ac8a5f6e380..aa7a3f139fe5 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -154,6 +154,9 @@ static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name, | |||
154 | } | 154 | } |
155 | 155 | ||
156 | #ifdef CONFIG_F2FS_FS_SECURITY | 156 | #ifdef CONFIG_F2FS_FS_SECURITY |
157 | static int __f2fs_setxattr(struct inode *inode, int name_index, | ||
158 | const char *name, const void *value, size_t value_len, | ||
159 | struct page *ipage); | ||
157 | static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, | 160 | static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, |
158 | void *page) | 161 | void *page) |
159 | { | 162 | { |
@@ -161,7 +164,7 @@ static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, | |||
161 | int err = 0; | 164 | int err = 0; |
162 | 165 | ||
163 | for (xattr = xattr_array; xattr->name != NULL; xattr++) { | 166 | for (xattr = xattr_array; xattr->name != NULL; xattr++) { |
164 | err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY, | 167 | err = __f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY, |
165 | xattr->name, xattr->value, | 168 | xattr->name, xattr->value, |
166 | xattr->value_len, (struct page *)page); | 169 | xattr->value_len, (struct page *)page); |
167 | if (err < 0) | 170 | if (err < 0) |
@@ -369,7 +372,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, | |||
369 | alloc_nid_failed(sbi, new_nid); | 372 | alloc_nid_failed(sbi, new_nid); |
370 | return PTR_ERR(xpage); | 373 | return PTR_ERR(xpage); |
371 | } | 374 | } |
372 | BUG_ON(new_nid); | 375 | f2fs_bug_on(new_nid); |
373 | } else { | 376 | } else { |
374 | struct dnode_of_data dn; | 377 | struct dnode_of_data dn; |
375 | set_new_dnode(&dn, inode, NULL, NULL, new_nid); | 378 | set_new_dnode(&dn, inode, NULL, NULL, new_nid); |
@@ -469,16 +472,15 @@ cleanup: | |||
469 | return error; | 472 | return error; |
470 | } | 473 | } |
471 | 474 | ||
472 | int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | 475 | static int __f2fs_setxattr(struct inode *inode, int name_index, |
473 | const void *value, size_t value_len, struct page *ipage) | 476 | const char *name, const void *value, size_t value_len, |
477 | struct page *ipage) | ||
474 | { | 478 | { |
475 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
476 | struct f2fs_inode_info *fi = F2FS_I(inode); | 479 | struct f2fs_inode_info *fi = F2FS_I(inode); |
477 | struct f2fs_xattr_entry *here, *last; | 480 | struct f2fs_xattr_entry *here, *last; |
478 | void *base_addr; | 481 | void *base_addr; |
479 | int found, newsize; | 482 | int found, newsize; |
480 | size_t name_len; | 483 | size_t name_len; |
481 | int ilock; | ||
482 | __u32 new_hsize; | 484 | __u32 new_hsize; |
483 | int error = -ENOMEM; | 485 | int error = -ENOMEM; |
484 | 486 | ||
@@ -493,10 +495,6 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
493 | if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN(inode)) | 495 | if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN(inode)) |
494 | return -ERANGE; | 496 | return -ERANGE; |
495 | 497 | ||
496 | f2fs_balance_fs(sbi); | ||
497 | |||
498 | ilock = mutex_lock_op(sbi); | ||
499 | |||
500 | base_addr = read_all_xattrs(inode, ipage); | 498 | base_addr = read_all_xattrs(inode, ipage); |
501 | if (!base_addr) | 499 | if (!base_addr) |
502 | goto exit; | 500 | goto exit; |
@@ -522,7 +520,7 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
522 | */ | 520 | */ |
523 | free = MIN_OFFSET(inode) - ((char *)last - (char *)base_addr); | 521 | free = MIN_OFFSET(inode) - ((char *)last - (char *)base_addr); |
524 | if (found) | 522 | if (found) |
525 | free = free - ENTRY_SIZE(here); | 523 | free = free + ENTRY_SIZE(here); |
526 | 524 | ||
527 | if (free < newsize) { | 525 | if (free < newsize) { |
528 | error = -ENOSPC; | 526 | error = -ENOSPC; |
@@ -578,7 +576,21 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
578 | else | 576 | else |
579 | update_inode_page(inode); | 577 | update_inode_page(inode); |
580 | exit: | 578 | exit: |
581 | mutex_unlock_op(sbi, ilock); | ||
582 | kzfree(base_addr); | 579 | kzfree(base_addr); |
583 | return error; | 580 | return error; |
584 | } | 581 | } |
582 | |||
583 | int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | ||
584 | const void *value, size_t value_len, struct page *ipage) | ||
585 | { | ||
586 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
587 | int err; | ||
588 | |||
589 | f2fs_balance_fs(sbi); | ||
590 | |||
591 | f2fs_lock_op(sbi); | ||
592 | err = __f2fs_setxattr(inode, name_index, name, value, value_len, ipage); | ||
593 | f2fs_unlock_op(sbi); | ||
594 | |||
595 | return err; | ||
596 | } | ||
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 52ae54828eda..e0dc355fa317 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h | |||
@@ -36,6 +36,11 @@ | |||
36 | { CURSEG_COLD_NODE, "Cold NODE" }, \ | 36 | { CURSEG_COLD_NODE, "Cold NODE" }, \ |
37 | { NO_CHECK_TYPE, "No TYPE" }) | 37 | { NO_CHECK_TYPE, "No TYPE" }) |
38 | 38 | ||
39 | #define show_file_type(type) \ | ||
40 | __print_symbolic(type, \ | ||
41 | { 0, "FILE" }, \ | ||
42 | { 1, "DIR" }) | ||
43 | |||
39 | #define show_gc_type(type) \ | 44 | #define show_gc_type(type) \ |
40 | __print_symbolic(type, \ | 45 | __print_symbolic(type, \ |
41 | { FG_GC, "Foreground GC" }, \ | 46 | { FG_GC, "Foreground GC" }, \ |
@@ -623,6 +628,52 @@ TRACE_EVENT(f2fs_do_submit_bio, | |||
623 | __entry->size) | 628 | __entry->size) |
624 | ); | 629 | ); |
625 | 630 | ||
631 | DECLARE_EVENT_CLASS(f2fs__page, | ||
632 | |||
633 | TP_PROTO(struct page *page, int type), | ||
634 | |||
635 | TP_ARGS(page, type), | ||
636 | |||
637 | TP_STRUCT__entry( | ||
638 | __field(dev_t, dev) | ||
639 | __field(ino_t, ino) | ||
640 | __field(int, type) | ||
641 | __field(int, dir) | ||
642 | __field(pgoff_t, index) | ||
643 | __field(int, dirty) | ||
644 | ), | ||
645 | |||
646 | TP_fast_assign( | ||
647 | __entry->dev = page->mapping->host->i_sb->s_dev; | ||
648 | __entry->ino = page->mapping->host->i_ino; | ||
649 | __entry->type = type; | ||
650 | __entry->dir = S_ISDIR(page->mapping->host->i_mode); | ||
651 | __entry->index = page->index; | ||
652 | __entry->dirty = PageDirty(page); | ||
653 | ), | ||
654 | |||
655 | TP_printk("dev = (%d,%d), ino = %lu, %s, %s, index = %lu, dirty = %d", | ||
656 | show_dev_ino(__entry), | ||
657 | show_block_type(__entry->type), | ||
658 | show_file_type(__entry->dir), | ||
659 | (unsigned long)__entry->index, | ||
660 | __entry->dirty) | ||
661 | ); | ||
662 | |||
663 | DEFINE_EVENT(f2fs__page, f2fs_set_page_dirty, | ||
664 | |||
665 | TP_PROTO(struct page *page, int type), | ||
666 | |||
667 | TP_ARGS(page, type) | ||
668 | ); | ||
669 | |||
670 | DEFINE_EVENT(f2fs__page, f2fs_vm_page_mkwrite, | ||
671 | |||
672 | TP_PROTO(struct page *page, int type), | ||
673 | |||
674 | TP_ARGS(page, type) | ||
675 | ); | ||
676 | |||
626 | TRACE_EVENT(f2fs_submit_write_page, | 677 | TRACE_EVENT(f2fs_submit_write_page, |
627 | 678 | ||
628 | TP_PROTO(struct page *page, block_t blk_addr, int type), | 679 | TP_PROTO(struct page *page, block_t blk_addr, int type), |