diff options
| -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), |
