diff options
Diffstat (limited to 'fs/f2fs/checkpoint.c')
| -rw-r--r-- | fs/f2fs/checkpoint.c | 178 |
1 files changed, 117 insertions, 61 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 0b4710c1d370..6aeed5bada52 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include "segment.h" | 22 | #include "segment.h" |
| 23 | #include <trace/events/f2fs.h> | 23 | #include <trace/events/f2fs.h> |
| 24 | 24 | ||
| 25 | static struct kmem_cache *orphan_entry_slab; | 25 | static struct kmem_cache *ino_entry_slab; |
| 26 | static struct kmem_cache *inode_entry_slab; | 26 | static struct kmem_cache *inode_entry_slab; |
| 27 | 27 | ||
| 28 | /* | 28 | /* |
| @@ -282,72 +282,120 @@ const struct address_space_operations f2fs_meta_aops = { | |||
| 282 | .set_page_dirty = f2fs_set_meta_page_dirty, | 282 | .set_page_dirty = f2fs_set_meta_page_dirty, |
| 283 | }; | 283 | }; |
| 284 | 284 | ||
| 285 | static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) | ||
| 286 | { | ||
| 287 | struct ino_entry *e; | ||
| 288 | retry: | ||
| 289 | spin_lock(&sbi->ino_lock[type]); | ||
| 290 | |||
| 291 | e = radix_tree_lookup(&sbi->ino_root[type], ino); | ||
| 292 | if (!e) { | ||
| 293 | e = kmem_cache_alloc(ino_entry_slab, GFP_ATOMIC); | ||
| 294 | if (!e) { | ||
| 295 | spin_unlock(&sbi->ino_lock[type]); | ||
| 296 | goto retry; | ||
| 297 | } | ||
| 298 | if (radix_tree_insert(&sbi->ino_root[type], ino, e)) { | ||
| 299 | spin_unlock(&sbi->ino_lock[type]); | ||
| 300 | kmem_cache_free(ino_entry_slab, e); | ||
| 301 | goto retry; | ||
| 302 | } | ||
| 303 | memset(e, 0, sizeof(struct ino_entry)); | ||
| 304 | e->ino = ino; | ||
| 305 | |||
| 306 | list_add_tail(&e->list, &sbi->ino_list[type]); | ||
| 307 | } | ||
| 308 | spin_unlock(&sbi->ino_lock[type]); | ||
| 309 | } | ||
| 310 | |||
| 311 | static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) | ||
| 312 | { | ||
| 313 | struct ino_entry *e; | ||
| 314 | |||
| 315 | spin_lock(&sbi->ino_lock[type]); | ||
| 316 | e = radix_tree_lookup(&sbi->ino_root[type], ino); | ||
| 317 | if (e) { | ||
| 318 | list_del(&e->list); | ||
| 319 | radix_tree_delete(&sbi->ino_root[type], ino); | ||
| 320 | if (type == ORPHAN_INO) | ||
| 321 | sbi->n_orphans--; | ||
| 322 | spin_unlock(&sbi->ino_lock[type]); | ||
| 323 | kmem_cache_free(ino_entry_slab, e); | ||
| 324 | return; | ||
| 325 | } | ||
| 326 | spin_unlock(&sbi->ino_lock[type]); | ||
| 327 | } | ||
| 328 | |||
| 329 | void add_dirty_inode(struct f2fs_sb_info *sbi, nid_t ino, int type) | ||
| 330 | { | ||
| 331 | /* add new dirty ino entry into list */ | ||
| 332 | __add_ino_entry(sbi, ino, type); | ||
| 333 | } | ||
| 334 | |||
| 335 | void remove_dirty_inode(struct f2fs_sb_info *sbi, nid_t ino, int type) | ||
| 336 | { | ||
| 337 | /* remove dirty ino entry from list */ | ||
| 338 | __remove_ino_entry(sbi, ino, type); | ||
| 339 | } | ||
| 340 | |||
| 341 | /* mode should be APPEND_INO or UPDATE_INO */ | ||
| 342 | bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode) | ||
| 343 | { | ||
| 344 | struct ino_entry *e; | ||
| 345 | spin_lock(&sbi->ino_lock[mode]); | ||
| 346 | e = radix_tree_lookup(&sbi->ino_root[mode], ino); | ||
| 347 | spin_unlock(&sbi->ino_lock[mode]); | ||
| 348 | return e ? true : false; | ||
| 349 | } | ||
| 350 | |||
| 351 | static void release_dirty_inode(struct f2fs_sb_info *sbi) | ||
| 352 | { | ||
| 353 | struct ino_entry *e, *tmp; | ||
| 354 | int i; | ||
| 355 | |||
| 356 | for (i = APPEND_INO; i <= UPDATE_INO; i++) { | ||
| 357 | spin_lock(&sbi->ino_lock[i]); | ||
| 358 | list_for_each_entry_safe(e, tmp, &sbi->ino_list[i], list) { | ||
| 359 | list_del(&e->list); | ||
| 360 | radix_tree_delete(&sbi->ino_root[i], e->ino); | ||
| 361 | kmem_cache_free(ino_entry_slab, e); | ||
| 362 | } | ||
| 363 | spin_unlock(&sbi->ino_lock[i]); | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 285 | int acquire_orphan_inode(struct f2fs_sb_info *sbi) | 367 | int acquire_orphan_inode(struct f2fs_sb_info *sbi) |
| 286 | { | 368 | { |
| 287 | int err = 0; | 369 | int err = 0; |
| 288 | 370 | ||
| 289 | spin_lock(&sbi->orphan_inode_lock); | 371 | spin_lock(&sbi->ino_lock[ORPHAN_INO]); |
| 290 | if (unlikely(sbi->n_orphans >= sbi->max_orphans)) | 372 | if (unlikely(sbi->n_orphans >= sbi->max_orphans)) |
| 291 | err = -ENOSPC; | 373 | err = -ENOSPC; |
| 292 | else | 374 | else |
| 293 | sbi->n_orphans++; | 375 | sbi->n_orphans++; |
| 294 | spin_unlock(&sbi->orphan_inode_lock); | 376 | spin_unlock(&sbi->ino_lock[ORPHAN_INO]); |
| 295 | 377 | ||
| 296 | return err; | 378 | return err; |
| 297 | } | 379 | } |
| 298 | 380 | ||
| 299 | void release_orphan_inode(struct f2fs_sb_info *sbi) | 381 | void release_orphan_inode(struct f2fs_sb_info *sbi) |
| 300 | { | 382 | { |
| 301 | spin_lock(&sbi->orphan_inode_lock); | 383 | spin_lock(&sbi->ino_lock[ORPHAN_INO]); |
| 302 | f2fs_bug_on(sbi->n_orphans == 0); | 384 | f2fs_bug_on(sbi->n_orphans == 0); |
| 303 | sbi->n_orphans--; | 385 | sbi->n_orphans--; |
| 304 | spin_unlock(&sbi->orphan_inode_lock); | 386 | spin_unlock(&sbi->ino_lock[ORPHAN_INO]); |
| 305 | } | 387 | } |
| 306 | 388 | ||
| 307 | void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 389 | void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
| 308 | { | 390 | { |
| 309 | struct list_head *head; | 391 | /* add new orphan ino entry into list */ |
| 310 | struct orphan_inode_entry *new, *orphan; | 392 | __add_ino_entry(sbi, ino, ORPHAN_INO); |
| 311 | |||
| 312 | new = f2fs_kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC); | ||
| 313 | new->ino = ino; | ||
| 314 | |||
| 315 | spin_lock(&sbi->orphan_inode_lock); | ||
| 316 | head = &sbi->orphan_inode_list; | ||
| 317 | list_for_each_entry(orphan, head, list) { | ||
| 318 | if (orphan->ino == ino) { | ||
| 319 | spin_unlock(&sbi->orphan_inode_lock); | ||
| 320 | kmem_cache_free(orphan_entry_slab, new); | ||
| 321 | return; | ||
| 322 | } | ||
| 323 | |||
| 324 | if (orphan->ino > ino) | ||
| 325 | break; | ||
| 326 | } | ||
| 327 | |||
| 328 | /* add new orphan entry into list which is sorted by inode number */ | ||
| 329 | list_add_tail(&new->list, &orphan->list); | ||
| 330 | spin_unlock(&sbi->orphan_inode_lock); | ||
| 331 | } | 393 | } |
| 332 | 394 | ||
| 333 | void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 395 | void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
| 334 | { | 396 | { |
| 335 | struct list_head *head; | 397 | /* remove orphan entry from orphan list */ |
| 336 | struct orphan_inode_entry *orphan; | 398 | __remove_ino_entry(sbi, ino, ORPHAN_INO); |
| 337 | |||
| 338 | spin_lock(&sbi->orphan_inode_lock); | ||
| 339 | head = &sbi->orphan_inode_list; | ||
| 340 | list_for_each_entry(orphan, head, list) { | ||
| 341 | if (orphan->ino == ino) { | ||
| 342 | list_del(&orphan->list); | ||
| 343 | f2fs_bug_on(sbi->n_orphans == 0); | ||
| 344 | sbi->n_orphans--; | ||
| 345 | spin_unlock(&sbi->orphan_inode_lock); | ||
| 346 | kmem_cache_free(orphan_entry_slab, orphan); | ||
| 347 | return; | ||
| 348 | } | ||
| 349 | } | ||
| 350 | spin_unlock(&sbi->orphan_inode_lock); | ||
| 351 | } | 399 | } |
| 352 | 400 | ||
| 353 | static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | 401 | static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) |
| @@ -401,14 +449,14 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) | |||
| 401 | unsigned short orphan_blocks = (unsigned short)((sbi->n_orphans + | 449 | unsigned short orphan_blocks = (unsigned short)((sbi->n_orphans + |
| 402 | (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK); | 450 | (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK); |
| 403 | struct page *page = NULL; | 451 | struct page *page = NULL; |
| 404 | struct orphan_inode_entry *orphan = NULL; | 452 | struct ino_entry *orphan = NULL; |
| 405 | 453 | ||
| 406 | for (index = 0; index < orphan_blocks; index++) | 454 | for (index = 0; index < orphan_blocks; index++) |
| 407 | grab_meta_page(sbi, start_blk + index); | 455 | grab_meta_page(sbi, start_blk + index); |
| 408 | 456 | ||
| 409 | index = 1; | 457 | index = 1; |
| 410 | spin_lock(&sbi->orphan_inode_lock); | 458 | spin_lock(&sbi->ino_lock[ORPHAN_INO]); |
| 411 | head = &sbi->orphan_inode_list; | 459 | head = &sbi->ino_list[ORPHAN_INO]; |
| 412 | 460 | ||
| 413 | /* loop for each orphan inode entry and write them in Jornal block */ | 461 | /* loop for each orphan inode entry and write them in Jornal block */ |
| 414 | list_for_each_entry(orphan, head, list) { | 462 | list_for_each_entry(orphan, head, list) { |
| @@ -448,7 +496,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) | |||
| 448 | f2fs_put_page(page, 1); | 496 | f2fs_put_page(page, 1); |
| 449 | } | 497 | } |
| 450 | 498 | ||
| 451 | spin_unlock(&sbi->orphan_inode_lock); | 499 | spin_unlock(&sbi->ino_lock[ORPHAN_INO]); |
| 452 | } | 500 | } |
| 453 | 501 | ||
| 454 | static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | 502 | static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, |
| @@ -714,10 +762,10 @@ retry_flush_dents: | |||
| 714 | * until finishing nat/sit flush. | 762 | * until finishing nat/sit flush. |
| 715 | */ | 763 | */ |
| 716 | retry_flush_nodes: | 764 | retry_flush_nodes: |
| 717 | mutex_lock(&sbi->node_write); | 765 | down_write(&sbi->node_write); |
| 718 | 766 | ||
| 719 | if (get_pages(sbi, F2FS_DIRTY_NODES)) { | 767 | if (get_pages(sbi, F2FS_DIRTY_NODES)) { |
| 720 | mutex_unlock(&sbi->node_write); | 768 | up_write(&sbi->node_write); |
| 721 | sync_node_pages(sbi, 0, &wbc); | 769 | sync_node_pages(sbi, 0, &wbc); |
| 722 | goto retry_flush_nodes; | 770 | goto retry_flush_nodes; |
| 723 | } | 771 | } |
| @@ -726,7 +774,7 @@ retry_flush_nodes: | |||
| 726 | 774 | ||
| 727 | static void unblock_operations(struct f2fs_sb_info *sbi) | 775 | static void unblock_operations(struct f2fs_sb_info *sbi) |
| 728 | { | 776 | { |
| 729 | mutex_unlock(&sbi->node_write); | 777 | up_write(&sbi->node_write); |
| 730 | f2fs_unlock_all(sbi); | 778 | f2fs_unlock_all(sbi); |
| 731 | } | 779 | } |
| 732 | 780 | ||
| @@ -748,6 +796,7 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi) | |||
| 748 | static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | 796 | static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) |
| 749 | { | 797 | { |
| 750 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | 798 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); |
| 799 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); | ||
| 751 | nid_t last_nid = 0; | 800 | nid_t last_nid = 0; |
| 752 | block_t start_blk; | 801 | block_t start_blk; |
| 753 | struct page *cp_page; | 802 | struct page *cp_page; |
| @@ -761,7 +810,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
| 761 | * This avoids to conduct wrong roll-forward operations and uses | 810 | * This avoids to conduct wrong roll-forward operations and uses |
| 762 | * metapages, so should be called prior to sync_meta_pages below. | 811 | * metapages, so should be called prior to sync_meta_pages below. |
| 763 | */ | 812 | */ |
| 764 | discard_next_dnode(sbi); | 813 | discard_next_dnode(sbi, NEXT_FREE_BLKADDR(sbi, curseg)); |
| 765 | 814 | ||
| 766 | /* Flush all the NAT/SIT pages */ | 815 | /* Flush all the NAT/SIT pages */ |
| 767 | while (get_pages(sbi, F2FS_DIRTY_META)) | 816 | while (get_pages(sbi, F2FS_DIRTY_META)) |
| @@ -885,8 +934,9 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
| 885 | /* Here, we only have one bio having CP pack */ | 934 | /* Here, we only have one bio having CP pack */ |
| 886 | sync_meta_pages(sbi, META_FLUSH, LONG_MAX); | 935 | sync_meta_pages(sbi, META_FLUSH, LONG_MAX); |
| 887 | 936 | ||
| 888 | if (unlikely(!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))) { | 937 | if (!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) { |
| 889 | clear_prefree_segments(sbi); | 938 | clear_prefree_segments(sbi); |
| 939 | release_dirty_inode(sbi); | ||
| 890 | F2FS_RESET_SB_DIRT(sbi); | 940 | F2FS_RESET_SB_DIRT(sbi); |
| 891 | } | 941 | } |
| 892 | } | 942 | } |
| @@ -932,31 +982,37 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
| 932 | trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish checkpoint"); | 982 | trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish checkpoint"); |
| 933 | } | 983 | } |
| 934 | 984 | ||
| 935 | void init_orphan_info(struct f2fs_sb_info *sbi) | 985 | void init_ino_entry_info(struct f2fs_sb_info *sbi) |
| 936 | { | 986 | { |
| 937 | spin_lock_init(&sbi->orphan_inode_lock); | 987 | int i; |
| 938 | INIT_LIST_HEAD(&sbi->orphan_inode_list); | 988 | |
| 939 | sbi->n_orphans = 0; | 989 | for (i = 0; i < MAX_INO_ENTRY; i++) { |
| 990 | INIT_RADIX_TREE(&sbi->ino_root[i], GFP_ATOMIC); | ||
| 991 | spin_lock_init(&sbi->ino_lock[i]); | ||
| 992 | INIT_LIST_HEAD(&sbi->ino_list[i]); | ||
| 993 | } | ||
| 994 | |||
| 940 | /* | 995 | /* |
| 941 | * considering 512 blocks in a segment 8 blocks are needed for cp | 996 | * considering 512 blocks in a segment 8 blocks are needed for cp |
| 942 | * and log segment summaries. Remaining blocks are used to keep | 997 | * and log segment summaries. Remaining blocks are used to keep |
| 943 | * orphan entries with the limitation one reserved segment | 998 | * orphan entries with the limitation one reserved segment |
| 944 | * for cp pack we can have max 1020*504 orphan entries | 999 | * for cp pack we can have max 1020*504 orphan entries |
| 945 | */ | 1000 | */ |
| 1001 | sbi->n_orphans = 0; | ||
| 946 | sbi->max_orphans = (sbi->blocks_per_seg - 2 - NR_CURSEG_TYPE) | 1002 | sbi->max_orphans = (sbi->blocks_per_seg - 2 - NR_CURSEG_TYPE) |
| 947 | * F2FS_ORPHANS_PER_BLOCK; | 1003 | * F2FS_ORPHANS_PER_BLOCK; |
| 948 | } | 1004 | } |
| 949 | 1005 | ||
| 950 | int __init create_checkpoint_caches(void) | 1006 | int __init create_checkpoint_caches(void) |
| 951 | { | 1007 | { |
| 952 | orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry", | 1008 | ino_entry_slab = f2fs_kmem_cache_create("f2fs_ino_entry", |
| 953 | sizeof(struct orphan_inode_entry)); | 1009 | sizeof(struct ino_entry)); |
| 954 | if (!orphan_entry_slab) | 1010 | if (!ino_entry_slab) |
| 955 | return -ENOMEM; | 1011 | return -ENOMEM; |
| 956 | inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry", | 1012 | inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry", |
| 957 | sizeof(struct dir_inode_entry)); | 1013 | sizeof(struct dir_inode_entry)); |
| 958 | if (!inode_entry_slab) { | 1014 | if (!inode_entry_slab) { |
| 959 | kmem_cache_destroy(orphan_entry_slab); | 1015 | kmem_cache_destroy(ino_entry_slab); |
| 960 | return -ENOMEM; | 1016 | return -ENOMEM; |
| 961 | } | 1017 | } |
| 962 | return 0; | 1018 | return 0; |
| @@ -964,6 +1020,6 @@ int __init create_checkpoint_caches(void) | |||
| 964 | 1020 | ||
| 965 | void destroy_checkpoint_caches(void) | 1021 | void destroy_checkpoint_caches(void) |
| 966 | { | 1022 | { |
| 967 | kmem_cache_destroy(orphan_entry_slab); | 1023 | kmem_cache_destroy(ino_entry_slab); |
| 968 | kmem_cache_destroy(inode_entry_slab); | 1024 | kmem_cache_destroy(inode_entry_slab); |
| 969 | } | 1025 | } |
