diff options
| -rw-r--r-- | Documentation/filesystems/f2fs.txt | 18 | ||||
| -rw-r--r-- | fs/f2fs/acl.c | 13 | ||||
| -rw-r--r-- | fs/f2fs/checkpoint.c | 3 | ||||
| -rw-r--r-- | fs/f2fs/data.c | 17 | ||||
| -rw-r--r-- | fs/f2fs/debug.c | 50 | ||||
| -rw-r--r-- | fs/f2fs/dir.c | 2 | ||||
| -rw-r--r-- | fs/f2fs/f2fs.h | 18 | ||||
| -rw-r--r-- | fs/f2fs/file.c | 16 | ||||
| -rw-r--r-- | fs/f2fs/gc.c | 68 | ||||
| -rw-r--r-- | fs/f2fs/inode.c | 3 | ||||
| -rw-r--r-- | fs/f2fs/node.c | 19 | ||||
| -rw-r--r-- | fs/f2fs/recovery.c | 10 | ||||
| -rw-r--r-- | fs/f2fs/segment.c | 2 | ||||
| -rw-r--r-- | fs/f2fs/super.c | 97 | ||||
| -rw-r--r-- | fs/f2fs/xattr.c | 2 |
15 files changed, 198 insertions, 140 deletions
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 8fbd8b46ee34..dcf338e62b71 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt | |||
| @@ -175,9 +175,9 @@ consists of multiple segments as described below. | |||
| 175 | align with the zone size <-| | 175 | align with the zone size <-| |
| 176 | |-> align with the segment size | 176 | |-> align with the segment size |
| 177 | _________________________________________________________________________ | 177 | _________________________________________________________________________ |
| 178 | | | | Node | Segment | Segment | | | 178 | | | | Segment | Node | Segment | | |
| 179 | | Superblock | Checkpoint | Address | Info. | Summary | Main | | 179 | | Superblock | Checkpoint | Info. | Address | Summary | Main | |
| 180 | | (SB) | (CP) | Table (NAT) | Table (SIT) | Area (SSA) | | | 180 | | (SB) | (CP) | Table (SIT) | Table (NAT) | Area (SSA) | | |
| 181 | |____________|_____2______|______N______|______N______|______N_____|__N___| | 181 | |____________|_____2______|______N______|______N______|______N_____|__N___| |
| 182 | . . | 182 | . . |
| 183 | . . | 183 | . . |
| @@ -200,14 +200,14 @@ consists of multiple segments as described below. | |||
| 200 | : It contains file system information, bitmaps for valid NAT/SIT sets, orphan | 200 | : It contains file system information, bitmaps for valid NAT/SIT sets, orphan |
| 201 | inode lists, and summary entries of current active segments. | 201 | inode lists, and summary entries of current active segments. |
| 202 | 202 | ||
| 203 | - Node Address Table (NAT) | ||
| 204 | : It is composed of a block address table for all the node blocks stored in | ||
| 205 | Main area. | ||
| 206 | |||
| 207 | - Segment Information Table (SIT) | 203 | - Segment Information Table (SIT) |
| 208 | : It contains segment information such as valid block count and bitmap for the | 204 | : It contains segment information such as valid block count and bitmap for the |
| 209 | validity of all the blocks. | 205 | validity of all the blocks. |
| 210 | 206 | ||
| 207 | - Node Address Table (NAT) | ||
| 208 | : It is composed of a block address table for all the node blocks stored in | ||
| 209 | Main area. | ||
| 210 | |||
| 211 | - Segment Summary Area (SSA) | 211 | - Segment Summary Area (SSA) |
| 212 | : It contains summary entries which contains the owner information of all the | 212 | : It contains summary entries which contains the owner information of all the |
| 213 | data and node blocks stored in Main area. | 213 | data and node blocks stored in Main area. |
| @@ -236,13 +236,13 @@ For file system consistency, each CP points to which NAT and SIT copies are | |||
| 236 | valid, as shown as below. | 236 | valid, as shown as below. |
| 237 | 237 | ||
| 238 | +--------+----------+---------+ | 238 | +--------+----------+---------+ |
| 239 | | CP | NAT | SIT | | 239 | | CP | SIT | NAT | |
| 240 | +--------+----------+---------+ | 240 | +--------+----------+---------+ |
| 241 | . . . . | 241 | . . . . |
| 242 | . . . . | 242 | . . . . |
| 243 | . . . . | 243 | . . . . |
| 244 | +-------+-------+--------+--------+--------+--------+ | 244 | +-------+-------+--------+--------+--------+--------+ |
| 245 | | CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 | | 245 | | CP #0 | CP #1 | SIT #0 | SIT #1 | NAT #0 | NAT #1 | |
| 246 | +-------+-------+--------+--------+--------+--------+ | 246 | +-------+-------+--------+--------+--------+--------+ |
| 247 | | ^ ^ | 247 | | ^ ^ |
| 248 | | | | | 248 | | | | |
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index e95b94945d5f..137af4255da6 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c | |||
| @@ -191,15 +191,14 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type) | |||
| 191 | retval = f2fs_getxattr(inode, name_index, "", value, retval); | 191 | retval = f2fs_getxattr(inode, name_index, "", value, retval); |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | if (retval < 0) { | 194 | if (retval > 0) |
| 195 | if (retval == -ENODATA) | ||
| 196 | acl = NULL; | ||
| 197 | else | ||
| 198 | acl = ERR_PTR(retval); | ||
| 199 | } else { | ||
| 200 | acl = f2fs_acl_from_disk(value, retval); | 195 | acl = f2fs_acl_from_disk(value, retval); |
| 201 | } | 196 | else if (retval == -ENODATA) |
| 197 | acl = NULL; | ||
| 198 | else | ||
| 199 | acl = ERR_PTR(retval); | ||
| 202 | kfree(value); | 200 | kfree(value); |
| 201 | |||
| 203 | if (!IS_ERR(acl)) | 202 | if (!IS_ERR(acl)) |
| 204 | set_cached_acl(inode, type, acl); | 203 | set_cached_acl(inode, type, acl); |
| 205 | 204 | ||
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 6ef36c37e2be..ff3c8439af87 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
| @@ -214,7 +214,6 @@ retry: | |||
| 214 | goto retry; | 214 | goto retry; |
| 215 | } | 215 | } |
| 216 | new->ino = ino; | 216 | new->ino = ino; |
| 217 | INIT_LIST_HEAD(&new->list); | ||
| 218 | 217 | ||
| 219 | /* add new_oentry into list which is sorted by inode number */ | 218 | /* add new_oentry into list which is sorted by inode number */ |
| 220 | if (orphan) { | 219 | if (orphan) { |
| @@ -772,7 +771,7 @@ void init_orphan_info(struct f2fs_sb_info *sbi) | |||
| 772 | sbi->n_orphans = 0; | 771 | sbi->n_orphans = 0; |
| 773 | } | 772 | } |
| 774 | 773 | ||
| 775 | int create_checkpoint_caches(void) | 774 | int __init create_checkpoint_caches(void) |
| 776 | { | 775 | { |
| 777 | orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry", | 776 | orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry", |
| 778 | sizeof(struct orphan_inode_entry), NULL); | 777 | sizeof(struct orphan_inode_entry), NULL); |
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 3aa5ce7cab83..7bd22a201125 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
| @@ -547,6 +547,15 @@ redirty_out: | |||
| 547 | 547 | ||
| 548 | #define MAX_DESIRED_PAGES_WP 4096 | 548 | #define MAX_DESIRED_PAGES_WP 4096 |
| 549 | 549 | ||
| 550 | static int __f2fs_writepage(struct page *page, struct writeback_control *wbc, | ||
| 551 | void *data) | ||
| 552 | { | ||
| 553 | struct address_space *mapping = data; | ||
| 554 | int ret = mapping->a_ops->writepage(page, wbc); | ||
| 555 | mapping_set_error(mapping, ret); | ||
| 556 | return ret; | ||
| 557 | } | ||
| 558 | |||
| 550 | static int f2fs_write_data_pages(struct address_space *mapping, | 559 | static int f2fs_write_data_pages(struct address_space *mapping, |
| 551 | struct writeback_control *wbc) | 560 | struct writeback_control *wbc) |
| 552 | { | 561 | { |
| @@ -563,7 +572,7 @@ static int f2fs_write_data_pages(struct address_space *mapping, | |||
| 563 | 572 | ||
| 564 | if (!S_ISDIR(inode->i_mode)) | 573 | if (!S_ISDIR(inode->i_mode)) |
| 565 | mutex_lock(&sbi->writepages); | 574 | mutex_lock(&sbi->writepages); |
| 566 | ret = generic_writepages(mapping, wbc); | 575 | ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping); |
| 567 | if (!S_ISDIR(inode->i_mode)) | 576 | if (!S_ISDIR(inode->i_mode)) |
| 568 | mutex_unlock(&sbi->writepages); | 577 | mutex_unlock(&sbi->writepages); |
| 569 | f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL)); | 578 | f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL)); |
| @@ -689,6 +698,11 @@ static int f2fs_set_data_page_dirty(struct page *page) | |||
| 689 | return 0; | 698 | return 0; |
| 690 | } | 699 | } |
| 691 | 700 | ||
| 701 | static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) | ||
| 702 | { | ||
| 703 | return generic_block_bmap(mapping, block, get_data_block_ro); | ||
| 704 | } | ||
| 705 | |||
| 692 | const struct address_space_operations f2fs_dblock_aops = { | 706 | const struct address_space_operations f2fs_dblock_aops = { |
| 693 | .readpage = f2fs_read_data_page, | 707 | .readpage = f2fs_read_data_page, |
| 694 | .readpages = f2fs_read_data_pages, | 708 | .readpages = f2fs_read_data_pages, |
| @@ -700,4 +714,5 @@ const struct address_space_operations f2fs_dblock_aops = { | |||
| 700 | .invalidatepage = f2fs_invalidate_data_page, | 714 | .invalidatepage = f2fs_invalidate_data_page, |
| 701 | .releasepage = f2fs_release_data_page, | 715 | .releasepage = f2fs_release_data_page, |
| 702 | .direct_IO = f2fs_direct_IO, | 716 | .direct_IO = f2fs_direct_IO, |
| 717 | .bmap = f2fs_bmap, | ||
| 703 | }; | 718 | }; |
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 0e0380a588ad..c8c37307b326 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | static LIST_HEAD(f2fs_stat_list); | 27 | static LIST_HEAD(f2fs_stat_list); |
| 28 | static struct dentry *debugfs_root; | 28 | static struct dentry *debugfs_root; |
| 29 | static DEFINE_MUTEX(f2fs_stat_mutex); | ||
| 29 | 30 | ||
| 30 | static void update_general_status(struct f2fs_sb_info *sbi) | 31 | static void update_general_status(struct f2fs_sb_info *sbi) |
| 31 | { | 32 | { |
| @@ -180,18 +181,14 @@ static int stat_show(struct seq_file *s, void *v) | |||
| 180 | int i = 0; | 181 | int i = 0; |
| 181 | int j; | 182 | int j; |
| 182 | 183 | ||
| 184 | mutex_lock(&f2fs_stat_mutex); | ||
| 183 | list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) { | 185 | list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) { |
| 184 | 186 | ||
| 185 | mutex_lock(&si->stat_lock); | ||
| 186 | if (!si->sbi) { | ||
| 187 | mutex_unlock(&si->stat_lock); | ||
| 188 | continue; | ||
| 189 | } | ||
| 190 | update_general_status(si->sbi); | 187 | update_general_status(si->sbi); |
| 191 | 188 | ||
| 192 | seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++); | 189 | seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++); |
| 193 | seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ", | 190 | seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", |
| 194 | si->nat_area_segs, si->sit_area_segs); | 191 | si->sit_area_segs, si->nat_area_segs); |
| 195 | seq_printf(s, "[SSA: %d] [MAIN: %d", | 192 | seq_printf(s, "[SSA: %d] [MAIN: %d", |
| 196 | si->ssa_area_segs, si->main_area_segs); | 193 | si->ssa_area_segs, si->main_area_segs); |
| 197 | seq_printf(s, "(OverProv:%d Resv:%d)]\n\n", | 194 | seq_printf(s, "(OverProv:%d Resv:%d)]\n\n", |
| @@ -286,8 +283,8 @@ static int stat_show(struct seq_file *s, void *v) | |||
| 286 | seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n", | 283 | seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n", |
| 287 | (si->base_mem + si->cache_mem) >> 10, | 284 | (si->base_mem + si->cache_mem) >> 10, |
| 288 | si->base_mem >> 10, si->cache_mem >> 10); | 285 | si->base_mem >> 10, si->cache_mem >> 10); |
| 289 | mutex_unlock(&si->stat_lock); | ||
| 290 | } | 286 | } |
| 287 | mutex_unlock(&f2fs_stat_mutex); | ||
| 291 | return 0; | 288 | return 0; |
| 292 | } | 289 | } |
| 293 | 290 | ||
| @@ -303,7 +300,7 @@ static const struct file_operations stat_fops = { | |||
| 303 | .release = single_release, | 300 | .release = single_release, |
| 304 | }; | 301 | }; |
| 305 | 302 | ||
| 306 | static int init_stats(struct f2fs_sb_info *sbi) | 303 | int f2fs_build_stats(struct f2fs_sb_info *sbi) |
| 307 | { | 304 | { |
| 308 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); | 305 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); |
| 309 | struct f2fs_stat_info *si; | 306 | struct f2fs_stat_info *si; |
| @@ -313,9 +310,6 @@ static int init_stats(struct f2fs_sb_info *sbi) | |||
| 313 | return -ENOMEM; | 310 | return -ENOMEM; |
| 314 | 311 | ||
| 315 | si = sbi->stat_info; | 312 | si = sbi->stat_info; |
| 316 | mutex_init(&si->stat_lock); | ||
| 317 | list_add_tail(&si->stat_list, &f2fs_stat_list); | ||
| 318 | |||
| 319 | si->all_area_segs = le32_to_cpu(raw_super->segment_count); | 313 | si->all_area_segs = le32_to_cpu(raw_super->segment_count); |
| 320 | si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); | 314 | si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); |
| 321 | si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat); | 315 | si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat); |
| @@ -325,21 +319,11 @@ static int init_stats(struct f2fs_sb_info *sbi) | |||
| 325 | si->main_area_zones = si->main_area_sections / | 319 | si->main_area_zones = si->main_area_sections / |
| 326 | le32_to_cpu(raw_super->secs_per_zone); | 320 | le32_to_cpu(raw_super->secs_per_zone); |
| 327 | si->sbi = sbi; | 321 | si->sbi = sbi; |
| 328 | return 0; | ||
| 329 | } | ||
| 330 | 322 | ||
| 331 | int f2fs_build_stats(struct f2fs_sb_info *sbi) | 323 | mutex_lock(&f2fs_stat_mutex); |
| 332 | { | 324 | list_add_tail(&si->stat_list, &f2fs_stat_list); |
| 333 | int retval; | 325 | mutex_unlock(&f2fs_stat_mutex); |
| 334 | |||
| 335 | retval = init_stats(sbi); | ||
| 336 | if (retval) | ||
| 337 | return retval; | ||
| 338 | |||
| 339 | if (!debugfs_root) | ||
| 340 | debugfs_root = debugfs_create_dir("f2fs", NULL); | ||
| 341 | 326 | ||
| 342 | debugfs_create_file("status", S_IRUGO, debugfs_root, NULL, &stat_fops); | ||
| 343 | return 0; | 327 | return 0; |
| 344 | } | 328 | } |
| 345 | 329 | ||
| @@ -347,14 +331,22 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi) | |||
| 347 | { | 331 | { |
| 348 | struct f2fs_stat_info *si = sbi->stat_info; | 332 | struct f2fs_stat_info *si = sbi->stat_info; |
| 349 | 333 | ||
| 334 | mutex_lock(&f2fs_stat_mutex); | ||
| 350 | list_del(&si->stat_list); | 335 | list_del(&si->stat_list); |
| 351 | mutex_lock(&si->stat_lock); | 336 | mutex_unlock(&f2fs_stat_mutex); |
| 352 | si->sbi = NULL; | 337 | |
| 353 | mutex_unlock(&si->stat_lock); | ||
| 354 | kfree(sbi->stat_info); | 338 | kfree(sbi->stat_info); |
| 355 | } | 339 | } |
| 356 | 340 | ||
| 357 | void destroy_root_stats(void) | 341 | void __init f2fs_create_root_stats(void) |
| 342 | { | ||
| 343 | debugfs_root = debugfs_create_dir("f2fs", NULL); | ||
| 344 | if (debugfs_root) | ||
| 345 | debugfs_create_file("status", S_IRUGO, debugfs_root, | ||
| 346 | NULL, &stat_fops); | ||
| 347 | } | ||
| 348 | |||
| 349 | void f2fs_destroy_root_stats(void) | ||
| 358 | { | 350 | { |
| 359 | debugfs_remove_recursive(debugfs_root); | 351 | debugfs_remove_recursive(debugfs_root); |
| 360 | debugfs_root = NULL; | 352 | debugfs_root = NULL; |
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 951ed52748f6..989980e16d0b 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
| @@ -503,7 +503,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, | |||
| 503 | } | 503 | } |
| 504 | 504 | ||
| 505 | if (inode) { | 505 | if (inode) { |
| 506 | inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 506 | inode->i_ctime = CURRENT_TIME; |
| 507 | drop_nlink(inode); | 507 | drop_nlink(inode); |
| 508 | if (S_ISDIR(inode->i_mode)) { | 508 | if (S_ISDIR(inode->i_mode)) { |
| 509 | drop_nlink(inode); | 509 | drop_nlink(inode); |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 13c6dfbb7183..c8e2d751ef9c 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
| @@ -211,11 +211,11 @@ struct dnode_of_data { | |||
| 211 | static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, | 211 | static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, |
| 212 | struct page *ipage, struct page *npage, nid_t nid) | 212 | struct page *ipage, struct page *npage, nid_t nid) |
| 213 | { | 213 | { |
| 214 | memset(dn, 0, sizeof(*dn)); | ||
| 214 | dn->inode = inode; | 215 | dn->inode = inode; |
| 215 | dn->inode_page = ipage; | 216 | dn->inode_page = ipage; |
| 216 | dn->node_page = npage; | 217 | dn->node_page = npage; |
| 217 | dn->nid = nid; | 218 | dn->nid = nid; |
| 218 | dn->inode_page_locked = 0; | ||
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | /* | 221 | /* |
| @@ -877,6 +877,8 @@ bool f2fs_empty_dir(struct inode *); | |||
| 877 | * super.c | 877 | * super.c |
| 878 | */ | 878 | */ |
| 879 | int f2fs_sync_fs(struct super_block *, int); | 879 | int f2fs_sync_fs(struct super_block *, int); |
| 880 | extern __printf(3, 4) | ||
| 881 | void f2fs_msg(struct super_block *, const char *, const char *, ...); | ||
| 880 | 882 | ||
| 881 | /* | 883 | /* |
| 882 | * hash.c | 884 | * hash.c |
| @@ -912,7 +914,7 @@ int restore_node_summary(struct f2fs_sb_info *, unsigned int, | |||
| 912 | void flush_nat_entries(struct f2fs_sb_info *); | 914 | void flush_nat_entries(struct f2fs_sb_info *); |
| 913 | int build_node_manager(struct f2fs_sb_info *); | 915 | int build_node_manager(struct f2fs_sb_info *); |
| 914 | void destroy_node_manager(struct f2fs_sb_info *); | 916 | void destroy_node_manager(struct f2fs_sb_info *); |
| 915 | int create_node_manager_caches(void); | 917 | int __init create_node_manager_caches(void); |
| 916 | void destroy_node_manager_caches(void); | 918 | void destroy_node_manager_caches(void); |
| 917 | 919 | ||
| 918 | /* | 920 | /* |
| @@ -964,7 +966,7 @@ void sync_dirty_dir_inodes(struct f2fs_sb_info *); | |||
| 964 | void block_operations(struct f2fs_sb_info *); | 966 | void block_operations(struct f2fs_sb_info *); |
| 965 | void write_checkpoint(struct f2fs_sb_info *, bool, bool); | 967 | void write_checkpoint(struct f2fs_sb_info *, bool, bool); |
| 966 | void init_orphan_info(struct f2fs_sb_info *); | 968 | void init_orphan_info(struct f2fs_sb_info *); |
| 967 | int create_checkpoint_caches(void); | 969 | int __init create_checkpoint_caches(void); |
| 968 | void destroy_checkpoint_caches(void); | 970 | void destroy_checkpoint_caches(void); |
| 969 | 971 | ||
| 970 | /* | 972 | /* |
| @@ -984,9 +986,9 @@ int do_write_data_page(struct page *); | |||
| 984 | int start_gc_thread(struct f2fs_sb_info *); | 986 | int start_gc_thread(struct f2fs_sb_info *); |
| 985 | void stop_gc_thread(struct f2fs_sb_info *); | 987 | void stop_gc_thread(struct f2fs_sb_info *); |
| 986 | block_t start_bidx_of_node(unsigned int); | 988 | block_t start_bidx_of_node(unsigned int); |
| 987 | int f2fs_gc(struct f2fs_sb_info *, int); | 989 | int f2fs_gc(struct f2fs_sb_info *); |
| 988 | void build_gc_manager(struct f2fs_sb_info *); | 990 | void build_gc_manager(struct f2fs_sb_info *); |
| 989 | int create_gc_caches(void); | 991 | int __init create_gc_caches(void); |
| 990 | void destroy_gc_caches(void); | 992 | void destroy_gc_caches(void); |
| 991 | 993 | ||
| 992 | /* | 994 | /* |
| @@ -1058,7 +1060,8 @@ struct f2fs_stat_info { | |||
| 1058 | 1060 | ||
| 1059 | int f2fs_build_stats(struct f2fs_sb_info *); | 1061 | int f2fs_build_stats(struct f2fs_sb_info *); |
| 1060 | void f2fs_destroy_stats(struct f2fs_sb_info *); | 1062 | void f2fs_destroy_stats(struct f2fs_sb_info *); |
| 1061 | void destroy_root_stats(void); | 1063 | void __init f2fs_create_root_stats(void); |
| 1064 | void f2fs_destroy_root_stats(void); | ||
| 1062 | #else | 1065 | #else |
| 1063 | #define stat_inc_call_count(si) | 1066 | #define stat_inc_call_count(si) |
| 1064 | #define stat_inc_seg_count(si, type) | 1067 | #define stat_inc_seg_count(si, type) |
| @@ -1068,7 +1071,8 @@ void destroy_root_stats(void); | |||
| 1068 | 1071 | ||
| 1069 | static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; } | 1072 | static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; } |
| 1070 | static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { } | 1073 | static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { } |
| 1071 | static inline void destroy_root_stats(void) { } | 1074 | static inline void __init f2fs_create_root_stats(void) { } |
| 1075 | static inline void f2fs_destroy_root_stats(void) { } | ||
| 1072 | #endif | 1076 | #endif |
| 1073 | 1077 | ||
| 1074 | extern const struct file_operations f2fs_dir_operations; | 1078 | extern const struct file_operations f2fs_dir_operations; |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 7f9ea9271ebe..3191b52aafb0 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
| @@ -96,8 +96,9 @@ out: | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static const struct vm_operations_struct f2fs_file_vm_ops = { | 98 | static const struct vm_operations_struct f2fs_file_vm_ops = { |
| 99 | .fault = filemap_fault, | 99 | .fault = filemap_fault, |
| 100 | .page_mkwrite = f2fs_vm_page_mkwrite, | 100 | .page_mkwrite = f2fs_vm_page_mkwrite, |
| 101 | .remap_pages = generic_file_remap_pages, | ||
| 101 | }; | 102 | }; |
| 102 | 103 | ||
| 103 | static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode) | 104 | static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode) |
| @@ -137,6 +138,9 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 137 | if (ret) | 138 | if (ret) |
| 138 | return ret; | 139 | return ret; |
| 139 | 140 | ||
| 141 | /* guarantee free sections for fsync */ | ||
| 142 | f2fs_balance_fs(sbi); | ||
| 143 | |||
| 140 | mutex_lock(&inode->i_mutex); | 144 | mutex_lock(&inode->i_mutex); |
| 141 | 145 | ||
| 142 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 146 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) |
| @@ -407,6 +411,8 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end) | |||
| 407 | struct dnode_of_data dn; | 411 | struct dnode_of_data dn; |
| 408 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 412 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
| 409 | 413 | ||
| 414 | f2fs_balance_fs(sbi); | ||
| 415 | |||
| 410 | mutex_lock_op(sbi, DATA_TRUNC); | 416 | mutex_lock_op(sbi, DATA_TRUNC); |
| 411 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 417 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
| 412 | err = get_dnode_of_data(&dn, index, RDONLY_NODE); | 418 | err = get_dnode_of_data(&dn, index, RDONLY_NODE); |
| @@ -534,7 +540,6 @@ static long f2fs_fallocate(struct file *file, int mode, | |||
| 534 | loff_t offset, loff_t len) | 540 | loff_t offset, loff_t len) |
| 535 | { | 541 | { |
| 536 | struct inode *inode = file->f_path.dentry->d_inode; | 542 | struct inode *inode = file->f_path.dentry->d_inode; |
| 537 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
| 538 | long ret; | 543 | long ret; |
| 539 | 544 | ||
| 540 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) | 545 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) |
| @@ -545,7 +550,10 @@ static long f2fs_fallocate(struct file *file, int mode, | |||
| 545 | else | 550 | else |
| 546 | ret = expand_inode_data(inode, offset, len, mode); | 551 | ret = expand_inode_data(inode, offset, len, mode); |
| 547 | 552 | ||
| 548 | f2fs_balance_fs(sbi); | 553 | if (!ret) { |
| 554 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 555 | mark_inode_dirty(inode); | ||
| 556 | } | ||
| 549 | return ret; | 557 | return ret; |
| 550 | } | 558 | } |
| 551 | 559 | ||
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index b0ec721e984a..c386910dacc5 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
| @@ -78,7 +78,7 @@ static int gc_thread_func(void *data) | |||
| 78 | 78 | ||
| 79 | sbi->bg_gc++; | 79 | sbi->bg_gc++; |
| 80 | 80 | ||
| 81 | if (f2fs_gc(sbi, 1) == GC_NONE) | 81 | if (f2fs_gc(sbi) == GC_NONE) |
| 82 | wait_ms = GC_THREAD_NOGC_SLEEP_TIME; | 82 | wait_ms = GC_THREAD_NOGC_SLEEP_TIME; |
| 83 | else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME) | 83 | else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME) |
| 84 | wait_ms = GC_THREAD_MAX_SLEEP_TIME; | 84 | wait_ms = GC_THREAD_MAX_SLEEP_TIME; |
| @@ -424,7 +424,11 @@ next_step: | |||
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | /* | 426 | /* |
| 427 | * Calculate start block index that this node page contains | 427 | * Calculate start block index indicating the given node offset. |
| 428 | * Be careful, caller should give this node offset only indicating direct node | ||
| 429 | * blocks. If any node offsets, which point the other types of node blocks such | ||
| 430 | * as indirect or double indirect node blocks, are given, it must be a caller's | ||
| 431 | * bug. | ||
| 428 | */ | 432 | */ |
| 429 | block_t start_bidx_of_node(unsigned int node_ofs) | 433 | block_t start_bidx_of_node(unsigned int node_ofs) |
| 430 | { | 434 | { |
| @@ -651,62 +655,44 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno, | |||
| 651 | return ret; | 655 | return ret; |
| 652 | } | 656 | } |
| 653 | 657 | ||
| 654 | int f2fs_gc(struct f2fs_sb_info *sbi, int nGC) | 658 | int f2fs_gc(struct f2fs_sb_info *sbi) |
| 655 | { | 659 | { |
| 656 | unsigned int segno; | ||
| 657 | int old_free_secs, cur_free_secs; | ||
| 658 | int gc_status, nfree; | ||
| 659 | struct list_head ilist; | 660 | struct list_head ilist; |
| 661 | unsigned int segno, i; | ||
| 660 | int gc_type = BG_GC; | 662 | int gc_type = BG_GC; |
| 663 | int gc_status = GC_NONE; | ||
| 661 | 664 | ||
| 662 | INIT_LIST_HEAD(&ilist); | 665 | INIT_LIST_HEAD(&ilist); |
| 663 | gc_more: | 666 | gc_more: |
| 664 | nfree = 0; | 667 | if (!(sbi->sb->s_flags & MS_ACTIVE)) |
| 665 | gc_status = GC_NONE; | 668 | goto stop; |
| 666 | 669 | ||
| 667 | if (has_not_enough_free_secs(sbi)) | 670 | if (has_not_enough_free_secs(sbi)) |
| 668 | old_free_secs = reserved_sections(sbi); | 671 | gc_type = FG_GC; |
| 669 | else | ||
| 670 | old_free_secs = free_sections(sbi); | ||
| 671 | |||
| 672 | while (sbi->sb->s_flags & MS_ACTIVE) { | ||
| 673 | int i; | ||
| 674 | if (has_not_enough_free_secs(sbi)) | ||
| 675 | gc_type = FG_GC; | ||
| 676 | 672 | ||
| 677 | cur_free_secs = free_sections(sbi) + nfree; | 673 | if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) |
| 674 | goto stop; | ||
| 678 | 675 | ||
| 679 | /* We got free space successfully. */ | 676 | for (i = 0; i < sbi->segs_per_sec; i++) { |
| 680 | if (nGC < cur_free_secs - old_free_secs) | 677 | /* |
| 681 | break; | 678 | * do_garbage_collect will give us three gc_status: |
| 682 | 679 | * GC_ERROR, GC_DONE, and GC_BLOCKED. | |
| 683 | if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) | 680 | * If GC is finished uncleanly, we have to return |
| 681 | * the victim to dirty segment list. | ||
| 682 | */ | ||
| 683 | gc_status = do_garbage_collect(sbi, segno + i, &ilist, gc_type); | ||
| 684 | if (gc_status != GC_DONE) | ||
| 684 | break; | 685 | break; |
| 685 | |||
| 686 | for (i = 0; i < sbi->segs_per_sec; i++) { | ||
| 687 | /* | ||
| 688 | * do_garbage_collect will give us three gc_status: | ||
| 689 | * GC_ERROR, GC_DONE, and GC_BLOCKED. | ||
| 690 | * If GC is finished uncleanly, we have to return | ||
| 691 | * the victim to dirty segment list. | ||
| 692 | */ | ||
| 693 | gc_status = do_garbage_collect(sbi, segno + i, | ||
| 694 | &ilist, gc_type); | ||
| 695 | if (gc_status != GC_DONE) | ||
| 696 | goto stop; | ||
| 697 | nfree++; | ||
| 698 | } | ||
| 699 | } | 686 | } |
| 700 | stop: | 687 | if (has_not_enough_free_secs(sbi)) { |
| 701 | if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) { | ||
| 702 | write_checkpoint(sbi, (gc_status == GC_BLOCKED), false); | 688 | write_checkpoint(sbi, (gc_status == GC_BLOCKED), false); |
| 703 | if (nfree) | 689 | if (has_not_enough_free_secs(sbi)) |
| 704 | goto gc_more; | 690 | goto gc_more; |
| 705 | } | 691 | } |
| 692 | stop: | ||
| 706 | mutex_unlock(&sbi->gc_mutex); | 693 | mutex_unlock(&sbi->gc_mutex); |
| 707 | 694 | ||
| 708 | put_gc_inode(&ilist); | 695 | put_gc_inode(&ilist); |
| 709 | BUG_ON(!list_empty(&ilist)); | ||
| 710 | return gc_status; | 696 | return gc_status; |
| 711 | } | 697 | } |
| 712 | 698 | ||
| @@ -715,7 +701,7 @@ void build_gc_manager(struct f2fs_sb_info *sbi) | |||
| 715 | DIRTY_I(sbi)->v_ops = &default_v_ops; | 701 | DIRTY_I(sbi)->v_ops = &default_v_ops; |
| 716 | } | 702 | } |
| 717 | 703 | ||
| 718 | int create_gc_caches(void) | 704 | int __init create_gc_caches(void) |
| 719 | { | 705 | { |
| 720 | winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes", | 706 | winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes", |
| 721 | sizeof(struct inode_entry), NULL); | 707 | sizeof(struct inode_entry), NULL); |
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index bf20b4d03214..794241777322 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c | |||
| @@ -217,6 +217,9 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 217 | inode->i_ino == F2FS_META_INO(sbi)) | 217 | inode->i_ino == F2FS_META_INO(sbi)) |
| 218 | return 0; | 218 | return 0; |
| 219 | 219 | ||
| 220 | if (wbc) | ||
| 221 | f2fs_balance_fs(sbi); | ||
| 222 | |||
| 220 | node_page = get_node_page(sbi, inode->i_ino); | 223 | node_page = get_node_page(sbi, inode->i_ino); |
| 221 | if (IS_ERR(node_page)) | 224 | if (IS_ERR(node_page)) |
| 222 | return PTR_ERR(node_page); | 225 | return PTR_ERR(node_page); |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 5066bfd256c9..9bda63c9c166 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
| @@ -1124,6 +1124,12 @@ static int f2fs_write_node_page(struct page *page, | |||
| 1124 | return 0; | 1124 | return 0; |
| 1125 | } | 1125 | } |
| 1126 | 1126 | ||
| 1127 | /* | ||
| 1128 | * It is very important to gather dirty pages and write at once, so that we can | ||
| 1129 | * submit a big bio without interfering other data writes. | ||
| 1130 | * Be default, 512 pages (2MB), a segment size, is quite reasonable. | ||
| 1131 | */ | ||
| 1132 | #define COLLECT_DIRTY_NODES 512 | ||
| 1127 | static int f2fs_write_node_pages(struct address_space *mapping, | 1133 | static int f2fs_write_node_pages(struct address_space *mapping, |
| 1128 | struct writeback_control *wbc) | 1134 | struct writeback_control *wbc) |
| 1129 | { | 1135 | { |
| @@ -1131,17 +1137,16 @@ static int f2fs_write_node_pages(struct address_space *mapping, | |||
| 1131 | struct block_device *bdev = sbi->sb->s_bdev; | 1137 | struct block_device *bdev = sbi->sb->s_bdev; |
| 1132 | long nr_to_write = wbc->nr_to_write; | 1138 | long nr_to_write = wbc->nr_to_write; |
| 1133 | 1139 | ||
| 1134 | if (wbc->for_kupdate) | 1140 | /* First check balancing cached NAT entries */ |
| 1135 | return 0; | ||
| 1136 | |||
| 1137 | if (get_pages(sbi, F2FS_DIRTY_NODES) == 0) | ||
| 1138 | return 0; | ||
| 1139 | |||
| 1140 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) { | 1141 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) { |
| 1141 | write_checkpoint(sbi, false, false); | 1142 | write_checkpoint(sbi, false, false); |
| 1142 | return 0; | 1143 | return 0; |
| 1143 | } | 1144 | } |
| 1144 | 1145 | ||
| 1146 | /* collect a number of dirty node pages and write together */ | ||
| 1147 | if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES) | ||
| 1148 | return 0; | ||
| 1149 | |||
| 1145 | /* if mounting is failed, skip writing node pages */ | 1150 | /* if mounting is failed, skip writing node pages */ |
| 1146 | wbc->nr_to_write = bio_get_nr_vecs(bdev); | 1151 | wbc->nr_to_write = bio_get_nr_vecs(bdev); |
| 1147 | sync_node_pages(sbi, 0, wbc); | 1152 | sync_node_pages(sbi, 0, wbc); |
| @@ -1732,7 +1737,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi) | |||
| 1732 | kfree(nm_i); | 1737 | kfree(nm_i); |
| 1733 | } | 1738 | } |
| 1734 | 1739 | ||
| 1735 | int create_node_manager_caches(void) | 1740 | int __init create_node_manager_caches(void) |
| 1736 | { | 1741 | { |
| 1737 | nat_entry_slab = f2fs_kmem_cache_create("nat_entry", | 1742 | nat_entry_slab = f2fs_kmem_cache_create("nat_entry", |
| 1738 | sizeof(struct nat_entry), NULL); | 1743 | sizeof(struct nat_entry), NULL); |
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index b571fee677d5..f42e4060b399 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
| @@ -67,7 +67,7 @@ static int recover_dentry(struct page *ipage, struct inode *inode) | |||
| 67 | kunmap(page); | 67 | kunmap(page); |
| 68 | f2fs_put_page(page, 0); | 68 | f2fs_put_page(page, 0); |
| 69 | } else { | 69 | } else { |
| 70 | f2fs_add_link(&dent, inode); | 70 | err = f2fs_add_link(&dent, inode); |
| 71 | } | 71 | } |
| 72 | iput(dir); | 72 | iput(dir); |
| 73 | out: | 73 | out: |
| @@ -151,7 +151,6 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
| 151 | goto out; | 151 | goto out; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | INIT_LIST_HEAD(&entry->list); | ||
| 155 | list_add_tail(&entry->list, head); | 154 | list_add_tail(&entry->list, head); |
| 156 | entry->blkaddr = blkaddr; | 155 | entry->blkaddr = blkaddr; |
| 157 | } | 156 | } |
| @@ -174,10 +173,9 @@ out: | |||
| 174 | static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi, | 173 | static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi, |
| 175 | struct list_head *head) | 174 | struct list_head *head) |
| 176 | { | 175 | { |
| 177 | struct list_head *this; | 176 | struct fsync_inode_entry *entry, *tmp; |
| 178 | struct fsync_inode_entry *entry; | 177 | |
| 179 | list_for_each(this, head) { | 178 | list_for_each_entry_safe(entry, tmp, head, list) { |
| 180 | entry = list_entry(this, struct fsync_inode_entry, list); | ||
| 181 | iput(entry->inode); | 179 | iput(entry->inode); |
| 182 | list_del(&entry->list); | 180 | list_del(&entry->list); |
| 183 | kmem_cache_free(fsync_entry_slab, entry); | 181 | kmem_cache_free(fsync_entry_slab, entry); |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index de6240922b0a..4b0099066582 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
| @@ -31,7 +31,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi) | |||
| 31 | */ | 31 | */ |
| 32 | if (has_not_enough_free_secs(sbi)) { | 32 | if (has_not_enough_free_secs(sbi)) { |
| 33 | mutex_lock(&sbi->gc_mutex); | 33 | mutex_lock(&sbi->gc_mutex); |
| 34 | f2fs_gc(sbi, 1); | 34 | f2fs_gc(sbi); |
| 35 | } | 35 | } |
| 36 | } | 36 | } |
| 37 | 37 | ||
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 08a94c814bdc..37fad04c8669 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
| @@ -53,6 +53,18 @@ static match_table_t f2fs_tokens = { | |||
| 53 | {Opt_err, NULL}, | 53 | {Opt_err, NULL}, |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...) | ||
| 57 | { | ||
| 58 | struct va_format vaf; | ||
| 59 | va_list args; | ||
| 60 | |||
| 61 | va_start(args, fmt); | ||
| 62 | vaf.fmt = fmt; | ||
| 63 | vaf.va = &args; | ||
| 64 | printk("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf); | ||
| 65 | va_end(args); | ||
| 66 | } | ||
| 67 | |||
| 56 | static void init_once(void *foo) | 68 | static void init_once(void *foo) |
| 57 | { | 69 | { |
| 58 | struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; | 70 | struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; |
| @@ -125,6 +137,8 @@ int f2fs_sync_fs(struct super_block *sb, int sync) | |||
| 125 | 137 | ||
| 126 | if (sync) | 138 | if (sync) |
| 127 | write_checkpoint(sbi, false, false); | 139 | write_checkpoint(sbi, false, false); |
| 140 | else | ||
| 141 | f2fs_balance_fs(sbi); | ||
| 128 | 142 | ||
| 129 | return 0; | 143 | return 0; |
| 130 | } | 144 | } |
| @@ -247,7 +261,8 @@ static const struct export_operations f2fs_export_ops = { | |||
| 247 | .get_parent = f2fs_get_parent, | 261 | .get_parent = f2fs_get_parent, |
| 248 | }; | 262 | }; |
| 249 | 263 | ||
| 250 | static int parse_options(struct f2fs_sb_info *sbi, char *options) | 264 | static int parse_options(struct super_block *sb, struct f2fs_sb_info *sbi, |
| 265 | char *options) | ||
| 251 | { | 266 | { |
| 252 | substring_t args[MAX_OPT_ARGS]; | 267 | substring_t args[MAX_OPT_ARGS]; |
| 253 | char *p; | 268 | char *p; |
| @@ -286,7 +301,8 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) | |||
| 286 | break; | 301 | break; |
| 287 | #else | 302 | #else |
| 288 | case Opt_nouser_xattr: | 303 | case Opt_nouser_xattr: |
| 289 | pr_info("nouser_xattr options not supported\n"); | 304 | f2fs_msg(sb, KERN_INFO, |
| 305 | "nouser_xattr options not supported"); | ||
| 290 | break; | 306 | break; |
| 291 | #endif | 307 | #endif |
| 292 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | 308 | #ifdef CONFIG_F2FS_FS_POSIX_ACL |
| @@ -295,7 +311,7 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) | |||
| 295 | break; | 311 | break; |
| 296 | #else | 312 | #else |
| 297 | case Opt_noacl: | 313 | case Opt_noacl: |
| 298 | pr_info("noacl options not supported\n"); | 314 | f2fs_msg(sb, KERN_INFO, "noacl options not supported"); |
| 299 | break; | 315 | break; |
| 300 | #endif | 316 | #endif |
| 301 | case Opt_active_logs: | 317 | case Opt_active_logs: |
| @@ -309,8 +325,9 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) | |||
| 309 | set_opt(sbi, DISABLE_EXT_IDENTIFY); | 325 | set_opt(sbi, DISABLE_EXT_IDENTIFY); |
| 310 | break; | 326 | break; |
| 311 | default: | 327 | default: |
| 312 | pr_err("Unrecognized mount option \"%s\" or missing value\n", | 328 | f2fs_msg(sb, KERN_ERR, |
| 313 | p); | 329 | "Unrecognized mount option \"%s\" or missing value", |
| 330 | p); | ||
| 314 | return -EINVAL; | 331 | return -EINVAL; |
| 315 | } | 332 | } |
| 316 | } | 333 | } |
| @@ -337,23 +354,36 @@ static loff_t max_file_size(unsigned bits) | |||
| 337 | return result; | 354 | return result; |
| 338 | } | 355 | } |
| 339 | 356 | ||
| 340 | static int sanity_check_raw_super(struct f2fs_super_block *raw_super) | 357 | static int sanity_check_raw_super(struct super_block *sb, |
| 358 | struct f2fs_super_block *raw_super) | ||
| 341 | { | 359 | { |
| 342 | unsigned int blocksize; | 360 | unsigned int blocksize; |
| 343 | 361 | ||
| 344 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) | 362 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { |
| 363 | f2fs_msg(sb, KERN_INFO, | ||
| 364 | "Magic Mismatch, valid(0x%x) - read(0x%x)", | ||
| 365 | F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic)); | ||
| 345 | return 1; | 366 | return 1; |
| 367 | } | ||
| 346 | 368 | ||
| 347 | /* Currently, support only 4KB block size */ | 369 | /* Currently, support only 4KB block size */ |
| 348 | blocksize = 1 << le32_to_cpu(raw_super->log_blocksize); | 370 | blocksize = 1 << le32_to_cpu(raw_super->log_blocksize); |
| 349 | if (blocksize != PAGE_CACHE_SIZE) | 371 | if (blocksize != PAGE_CACHE_SIZE) { |
| 372 | f2fs_msg(sb, KERN_INFO, | ||
| 373 | "Invalid blocksize (%u), supports only 4KB\n", | ||
| 374 | blocksize); | ||
| 350 | return 1; | 375 | return 1; |
| 376 | } | ||
| 351 | if (le32_to_cpu(raw_super->log_sectorsize) != | 377 | if (le32_to_cpu(raw_super->log_sectorsize) != |
| 352 | F2FS_LOG_SECTOR_SIZE) | 378 | F2FS_LOG_SECTOR_SIZE) { |
| 379 | f2fs_msg(sb, KERN_INFO, "Invalid log sectorsize"); | ||
| 353 | return 1; | 380 | return 1; |
| 381 | } | ||
| 354 | if (le32_to_cpu(raw_super->log_sectors_per_block) != | 382 | if (le32_to_cpu(raw_super->log_sectors_per_block) != |
| 355 | F2FS_LOG_SECTORS_PER_BLOCK) | 383 | F2FS_LOG_SECTORS_PER_BLOCK) { |
| 384 | f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block"); | ||
| 356 | return 1; | 385 | return 1; |
| 386 | } | ||
| 357 | return 0; | 387 | return 0; |
| 358 | } | 388 | } |
| 359 | 389 | ||
| @@ -413,14 +443,17 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 413 | if (!sbi) | 443 | if (!sbi) |
| 414 | return -ENOMEM; | 444 | return -ENOMEM; |
| 415 | 445 | ||
| 416 | /* set a temporary block size */ | 446 | /* set a block size */ |
| 417 | if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) | 447 | if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) { |
| 448 | f2fs_msg(sb, KERN_ERR, "unable to set blocksize"); | ||
| 418 | goto free_sbi; | 449 | goto free_sbi; |
| 450 | } | ||
| 419 | 451 | ||
| 420 | /* read f2fs raw super block */ | 452 | /* read f2fs raw super block */ |
| 421 | raw_super_buf = sb_bread(sb, 0); | 453 | raw_super_buf = sb_bread(sb, 0); |
| 422 | if (!raw_super_buf) { | 454 | if (!raw_super_buf) { |
| 423 | err = -EIO; | 455 | err = -EIO; |
| 456 | f2fs_msg(sb, KERN_ERR, "unable to read superblock"); | ||
| 424 | goto free_sbi; | 457 | goto free_sbi; |
| 425 | } | 458 | } |
| 426 | raw_super = (struct f2fs_super_block *) | 459 | raw_super = (struct f2fs_super_block *) |
| @@ -438,12 +471,14 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 438 | set_opt(sbi, POSIX_ACL); | 471 | set_opt(sbi, POSIX_ACL); |
| 439 | #endif | 472 | #endif |
| 440 | /* parse mount options */ | 473 | /* parse mount options */ |
| 441 | if (parse_options(sbi, (char *)data)) | 474 | if (parse_options(sb, sbi, (char *)data)) |
| 442 | goto free_sb_buf; | 475 | goto free_sb_buf; |
| 443 | 476 | ||
| 444 | /* sanity checking of raw super */ | 477 | /* sanity checking of raw super */ |
| 445 | if (sanity_check_raw_super(raw_super)) | 478 | if (sanity_check_raw_super(sb, raw_super)) { |
| 479 | f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem"); | ||
| 446 | goto free_sb_buf; | 480 | goto free_sb_buf; |
| 481 | } | ||
| 447 | 482 | ||
| 448 | sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize)); | 483 | sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize)); |
| 449 | sb->s_max_links = F2FS_LINK_MAX; | 484 | sb->s_max_links = F2FS_LINK_MAX; |
| @@ -477,18 +512,23 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 477 | /* get an inode for meta space */ | 512 | /* get an inode for meta space */ |
| 478 | sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); | 513 | sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); |
| 479 | if (IS_ERR(sbi->meta_inode)) { | 514 | if (IS_ERR(sbi->meta_inode)) { |
| 515 | f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode"); | ||
| 480 | err = PTR_ERR(sbi->meta_inode); | 516 | err = PTR_ERR(sbi->meta_inode); |
| 481 | goto free_sb_buf; | 517 | goto free_sb_buf; |
| 482 | } | 518 | } |
| 483 | 519 | ||
| 484 | err = get_valid_checkpoint(sbi); | 520 | err = get_valid_checkpoint(sbi); |
| 485 | if (err) | 521 | if (err) { |
| 522 | f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint"); | ||
| 486 | goto free_meta_inode; | 523 | goto free_meta_inode; |
| 524 | } | ||
| 487 | 525 | ||
| 488 | /* sanity checking of checkpoint */ | 526 | /* sanity checking of checkpoint */ |
| 489 | err = -EINVAL; | 527 | err = -EINVAL; |
| 490 | if (sanity_check_ckpt(raw_super, sbi->ckpt)) | 528 | if (sanity_check_ckpt(raw_super, sbi->ckpt)) { |
| 529 | f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint"); | ||
| 491 | goto free_cp; | 530 | goto free_cp; |
| 531 | } | ||
| 492 | 532 | ||
| 493 | sbi->total_valid_node_count = | 533 | sbi->total_valid_node_count = |
| 494 | le32_to_cpu(sbi->ckpt->valid_node_count); | 534 | le32_to_cpu(sbi->ckpt->valid_node_count); |
| @@ -502,25 +542,28 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 502 | INIT_LIST_HEAD(&sbi->dir_inode_list); | 542 | INIT_LIST_HEAD(&sbi->dir_inode_list); |
| 503 | spin_lock_init(&sbi->dir_inode_lock); | 543 | spin_lock_init(&sbi->dir_inode_lock); |
| 504 | 544 | ||
| 505 | /* init super block */ | ||
| 506 | if (!sb_set_blocksize(sb, sbi->blocksize)) | ||
| 507 | goto free_cp; | ||
| 508 | |||
| 509 | init_orphan_info(sbi); | 545 | init_orphan_info(sbi); |
| 510 | 546 | ||
| 511 | /* setup f2fs internal modules */ | 547 | /* setup f2fs internal modules */ |
| 512 | err = build_segment_manager(sbi); | 548 | err = build_segment_manager(sbi); |
| 513 | if (err) | 549 | if (err) { |
| 550 | f2fs_msg(sb, KERN_ERR, | ||
| 551 | "Failed to initialize F2FS segment manager"); | ||
| 514 | goto free_sm; | 552 | goto free_sm; |
| 553 | } | ||
| 515 | err = build_node_manager(sbi); | 554 | err = build_node_manager(sbi); |
| 516 | if (err) | 555 | if (err) { |
| 556 | f2fs_msg(sb, KERN_ERR, | ||
| 557 | "Failed to initialize F2FS node manager"); | ||
| 517 | goto free_nm; | 558 | goto free_nm; |
| 559 | } | ||
| 518 | 560 | ||
| 519 | build_gc_manager(sbi); | 561 | build_gc_manager(sbi); |
| 520 | 562 | ||
| 521 | /* get an inode for node space */ | 563 | /* get an inode for node space */ |
| 522 | sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi)); | 564 | sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi)); |
| 523 | if (IS_ERR(sbi->node_inode)) { | 565 | if (IS_ERR(sbi->node_inode)) { |
| 566 | f2fs_msg(sb, KERN_ERR, "Failed to read node inode"); | ||
| 524 | err = PTR_ERR(sbi->node_inode); | 567 | err = PTR_ERR(sbi->node_inode); |
| 525 | goto free_nm; | 568 | goto free_nm; |
| 526 | } | 569 | } |
| @@ -533,6 +576,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 533 | /* read root inode and dentry */ | 576 | /* read root inode and dentry */ |
| 534 | root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); | 577 | root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); |
| 535 | if (IS_ERR(root)) { | 578 | if (IS_ERR(root)) { |
| 579 | f2fs_msg(sb, KERN_ERR, "Failed to read root inode"); | ||
| 536 | err = PTR_ERR(root); | 580 | err = PTR_ERR(root); |
| 537 | goto free_node_inode; | 581 | goto free_node_inode; |
| 538 | } | 582 | } |
| @@ -596,7 +640,7 @@ static struct file_system_type f2fs_fs_type = { | |||
| 596 | .fs_flags = FS_REQUIRES_DEV, | 640 | .fs_flags = FS_REQUIRES_DEV, |
| 597 | }; | 641 | }; |
| 598 | 642 | ||
| 599 | static int init_inodecache(void) | 643 | static int __init init_inodecache(void) |
| 600 | { | 644 | { |
| 601 | f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache", | 645 | f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache", |
| 602 | sizeof(struct f2fs_inode_info), NULL); | 646 | sizeof(struct f2fs_inode_info), NULL); |
| @@ -631,14 +675,17 @@ static int __init init_f2fs_fs(void) | |||
| 631 | err = create_checkpoint_caches(); | 675 | err = create_checkpoint_caches(); |
| 632 | if (err) | 676 | if (err) |
| 633 | goto fail; | 677 | goto fail; |
| 634 | return register_filesystem(&f2fs_fs_type); | 678 | err = register_filesystem(&f2fs_fs_type); |
| 679 | if (err) | ||
| 680 | goto fail; | ||
| 681 | f2fs_create_root_stats(); | ||
| 635 | fail: | 682 | fail: |
| 636 | return err; | 683 | return err; |
| 637 | } | 684 | } |
| 638 | 685 | ||
| 639 | static void __exit exit_f2fs_fs(void) | 686 | static void __exit exit_f2fs_fs(void) |
| 640 | { | 687 | { |
| 641 | destroy_root_stats(); | 688 | f2fs_destroy_root_stats(); |
| 642 | unregister_filesystem(&f2fs_fs_type); | 689 | unregister_filesystem(&f2fs_fs_type); |
| 643 | destroy_checkpoint_caches(); | 690 | destroy_checkpoint_caches(); |
| 644 | destroy_gc_caches(); | 691 | destroy_gc_caches(); |
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 940136a3d3a6..8038c0496504 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
| @@ -318,6 +318,8 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
| 318 | if (name_len > 255 || value_len > MAX_VALUE_LEN) | 318 | if (name_len > 255 || value_len > MAX_VALUE_LEN) |
| 319 | return -ERANGE; | 319 | return -ERANGE; |
| 320 | 320 | ||
| 321 | f2fs_balance_fs(sbi); | ||
| 322 | |||
| 321 | mutex_lock_op(sbi, NODE_NEW); | 323 | mutex_lock_op(sbi, NODE_NEW); |
| 322 | if (!fi->i_xattr_nid) { | 324 | if (!fi->i_xattr_nid) { |
| 323 | /* Allocate new attribute block */ | 325 | /* Allocate new attribute block */ |
