diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 12:42:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 12:42:38 -0400 |
commit | 3f490f7f99053288bd85563f8d9b5032b810e177 (patch) | |
tree | a921f0fba44c8aac602608ff7349c25e4129b132 /fs/f2fs | |
parent | c4eb1b07303ad9e00aba842aa90d5521293ac857 (diff) | |
parent | a1dd3c13ce65b726fddfe72b9d2f1009db983ce6 (diff) |
Merge tag 'for-f2fs-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim:
"This patch-set includes the following major enhancement patches:
- remount_fs callback function
- restore parent inode number to enhance the fsync performance
- xattr security labels
- reduce the number of redundant lock/unlock data pages
- avoid frequent write_inode calls
The other minor bug fixes are as follows.
- endian conversion bugs
- various bugs in the roll-forward recovery routine"
* tag 'for-f2fs-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (56 commits)
f2fs: fix to recover i_size from roll-forward
f2fs: remove the unused argument "sbi" of func destroy_fsync_dnodes()
f2fs: remove reusing any prefree segments
f2fs: code cleanup and simplify in func {find/add}_gc_inode
f2fs: optimize the init_dirty_segmap function
f2fs: fix an endian conversion bug detected by sparse
f2fs: fix crc endian conversion
f2fs: add remount_fs callback support
f2fs: recover wrong pino after checkpoint during fsync
f2fs: optimize do_write_data_page()
f2fs: make locate_dirty_segment() as static
f2fs: remove unnecessary parameter "offset" from __add_sum_entry()
f2fs: avoid freqeunt write_inode calls
f2fs: optimise the truncate_data_blocks_range() range
f2fs: use the F2FS specific flags in f2fs_ioctl()
f2fs: sync dir->i_size with its block allocation
f2fs: fix i_blocks translation on various types of files
f2fs: set sb->s_fs_info before calling parse_options()
f2fs: support xattr security labels
f2fs: fix iget/iput of dir during recovery
...
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/Kconfig | 12 | ||||
-rw-r--r-- | fs/f2fs/acl.c | 2 | ||||
-rw-r--r-- | fs/f2fs/checkpoint.c | 99 | ||||
-rw-r--r-- | fs/f2fs/data.c | 68 | ||||
-rw-r--r-- | fs/f2fs/debug.c | 4 | ||||
-rw-r--r-- | fs/f2fs/dir.c | 109 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 66 | ||||
-rw-r--r-- | fs/f2fs/file.c | 58 | ||||
-rw-r--r-- | fs/f2fs/gc.c | 42 | ||||
-rw-r--r-- | fs/f2fs/inode.c | 13 | ||||
-rw-r--r-- | fs/f2fs/namei.c | 17 | ||||
-rw-r--r-- | fs/f2fs/node.c | 34 | ||||
-rw-r--r-- | fs/f2fs/node.h | 68 | ||||
-rw-r--r-- | fs/f2fs/recovery.c | 150 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 101 | ||||
-rw-r--r-- | fs/f2fs/super.c | 253 | ||||
-rw-r--r-- | fs/f2fs/xattr.c | 68 | ||||
-rw-r--r-- | fs/f2fs/xattr.h | 24 |
18 files changed, 741 insertions, 447 deletions
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig index fd27e7e6326e..e06e0995e00f 100644 --- a/fs/f2fs/Kconfig +++ b/fs/f2fs/Kconfig | |||
@@ -51,3 +51,15 @@ config F2FS_FS_POSIX_ACL | |||
51 | Linux website <http://acl.bestbits.at/>. | 51 | Linux website <http://acl.bestbits.at/>. |
52 | 52 | ||
53 | If you don't know what Access Control Lists are, say N | 53 | If you don't know what Access Control Lists are, say N |
54 | |||
55 | config F2FS_FS_SECURITY | ||
56 | bool "F2FS Security Labels" | ||
57 | depends on F2FS_FS_XATTR | ||
58 | help | ||
59 | Security labels provide an access control facility to support Linux | ||
60 | Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO | ||
61 | Linux. This option enables an extended attribute handler for file | ||
62 | security labels in the f2fs filesystem, so that it requires enabling | ||
63 | the extended attribute support in advance. | ||
64 | |||
65 | If you are not using a security module, say N. | ||
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index 44abc2f286e0..b7826ec1b470 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c | |||
@@ -250,7 +250,7 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
250 | } | 250 | } |
251 | } | 251 | } |
252 | 252 | ||
253 | error = f2fs_setxattr(inode, name_index, "", value, size); | 253 | error = f2fs_setxattr(inode, name_index, "", value, size, NULL); |
254 | 254 | ||
255 | kfree(value); | 255 | kfree(value); |
256 | if (!error) | 256 | if (!error) |
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index b1de01da1a40..66a6b85a51d8 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -357,8 +357,8 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | |||
357 | unsigned long blk_size = sbi->blocksize; | 357 | unsigned long blk_size = sbi->blocksize; |
358 | struct f2fs_checkpoint *cp_block; | 358 | struct f2fs_checkpoint *cp_block; |
359 | unsigned long long cur_version = 0, pre_version = 0; | 359 | unsigned long long cur_version = 0, pre_version = 0; |
360 | unsigned int crc = 0; | ||
361 | size_t crc_offset; | 360 | size_t crc_offset; |
361 | __u32 crc = 0; | ||
362 | 362 | ||
363 | /* Read the 1st cp block in this CP pack */ | 363 | /* Read the 1st cp block in this CP pack */ |
364 | cp_page_1 = get_meta_page(sbi, cp_addr); | 364 | cp_page_1 = get_meta_page(sbi, cp_addr); |
@@ -369,7 +369,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | |||
369 | if (crc_offset >= blk_size) | 369 | if (crc_offset >= blk_size) |
370 | goto invalid_cp1; | 370 | goto invalid_cp1; |
371 | 371 | ||
372 | crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset); | 372 | crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); |
373 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) | 373 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) |
374 | goto invalid_cp1; | 374 | goto invalid_cp1; |
375 | 375 | ||
@@ -384,7 +384,7 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, | |||
384 | if (crc_offset >= blk_size) | 384 | if (crc_offset >= blk_size) |
385 | goto invalid_cp2; | 385 | goto invalid_cp2; |
386 | 386 | ||
387 | crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset); | 387 | crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); |
388 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) | 388 | if (!f2fs_crc_valid(crc, cp_block, crc_offset)) |
389 | goto invalid_cp2; | 389 | goto invalid_cp2; |
390 | 390 | ||
@@ -450,13 +450,30 @@ fail_no_cp: | |||
450 | return -EINVAL; | 450 | return -EINVAL; |
451 | } | 451 | } |
452 | 452 | ||
453 | void set_dirty_dir_page(struct inode *inode, struct page *page) | 453 | static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new) |
454 | { | 454 | { |
455 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 455 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
456 | struct list_head *head = &sbi->dir_inode_list; | 456 | struct list_head *head = &sbi->dir_inode_list; |
457 | struct dir_inode_entry *new; | ||
458 | struct list_head *this; | 457 | struct list_head *this; |
459 | 458 | ||
459 | list_for_each(this, head) { | ||
460 | struct dir_inode_entry *entry; | ||
461 | entry = list_entry(this, struct dir_inode_entry, list); | ||
462 | if (entry->inode == inode) | ||
463 | return -EEXIST; | ||
464 | } | ||
465 | list_add_tail(&new->list, head); | ||
466 | #ifdef CONFIG_F2FS_STAT_FS | ||
467 | sbi->n_dirty_dirs++; | ||
468 | #endif | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | void set_dirty_dir_page(struct inode *inode, struct page *page) | ||
473 | { | ||
474 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
475 | struct dir_inode_entry *new; | ||
476 | |||
460 | if (!S_ISDIR(inode->i_mode)) | 477 | if (!S_ISDIR(inode->i_mode)) |
461 | return; | 478 | return; |
462 | retry: | 479 | retry: |
@@ -469,23 +486,31 @@ retry: | |||
469 | INIT_LIST_HEAD(&new->list); | 486 | INIT_LIST_HEAD(&new->list); |
470 | 487 | ||
471 | spin_lock(&sbi->dir_inode_lock); | 488 | spin_lock(&sbi->dir_inode_lock); |
472 | list_for_each(this, head) { | 489 | if (__add_dirty_inode(inode, new)) |
473 | struct dir_inode_entry *entry; | 490 | kmem_cache_free(inode_entry_slab, new); |
474 | entry = list_entry(this, struct dir_inode_entry, list); | ||
475 | if (entry->inode == inode) { | ||
476 | kmem_cache_free(inode_entry_slab, new); | ||
477 | goto out; | ||
478 | } | ||
479 | } | ||
480 | list_add_tail(&new->list, head); | ||
481 | sbi->n_dirty_dirs++; | ||
482 | 491 | ||
483 | BUG_ON(!S_ISDIR(inode->i_mode)); | ||
484 | out: | ||
485 | inc_page_count(sbi, F2FS_DIRTY_DENTS); | 492 | inc_page_count(sbi, F2FS_DIRTY_DENTS); |
486 | inode_inc_dirty_dents(inode); | 493 | inode_inc_dirty_dents(inode); |
487 | SetPagePrivate(page); | 494 | SetPagePrivate(page); |
495 | spin_unlock(&sbi->dir_inode_lock); | ||
496 | } | ||
488 | 497 | ||
498 | void add_dirty_dir_inode(struct inode *inode) | ||
499 | { | ||
500 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
501 | struct dir_inode_entry *new; | ||
502 | retry: | ||
503 | new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS); | ||
504 | if (!new) { | ||
505 | cond_resched(); | ||
506 | goto retry; | ||
507 | } | ||
508 | new->inode = inode; | ||
509 | INIT_LIST_HEAD(&new->list); | ||
510 | |||
511 | spin_lock(&sbi->dir_inode_lock); | ||
512 | if (__add_dirty_inode(inode, new)) | ||
513 | kmem_cache_free(inode_entry_slab, new); | ||
489 | spin_unlock(&sbi->dir_inode_lock); | 514 | spin_unlock(&sbi->dir_inode_lock); |
490 | } | 515 | } |
491 | 516 | ||
@@ -499,8 +524,10 @@ void remove_dirty_dir_inode(struct inode *inode) | |||
499 | return; | 524 | return; |
500 | 525 | ||
501 | spin_lock(&sbi->dir_inode_lock); | 526 | spin_lock(&sbi->dir_inode_lock); |
502 | if (atomic_read(&F2FS_I(inode)->dirty_dents)) | 527 | if (atomic_read(&F2FS_I(inode)->dirty_dents)) { |
503 | goto out; | 528 | spin_unlock(&sbi->dir_inode_lock); |
529 | return; | ||
530 | } | ||
504 | 531 | ||
505 | list_for_each(this, head) { | 532 | list_for_each(this, head) { |
506 | struct dir_inode_entry *entry; | 533 | struct dir_inode_entry *entry; |
@@ -508,12 +535,38 @@ void remove_dirty_dir_inode(struct inode *inode) | |||
508 | if (entry->inode == inode) { | 535 | if (entry->inode == inode) { |
509 | list_del(&entry->list); | 536 | list_del(&entry->list); |
510 | kmem_cache_free(inode_entry_slab, entry); | 537 | kmem_cache_free(inode_entry_slab, entry); |
538 | #ifdef CONFIG_F2FS_STAT_FS | ||
511 | sbi->n_dirty_dirs--; | 539 | sbi->n_dirty_dirs--; |
540 | #endif | ||
541 | break; | ||
542 | } | ||
543 | } | ||
544 | spin_unlock(&sbi->dir_inode_lock); | ||
545 | |||
546 | /* Only from the recovery routine */ | ||
547 | if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT)) { | ||
548 | clear_inode_flag(F2FS_I(inode), FI_DELAY_IPUT); | ||
549 | iput(inode); | ||
550 | } | ||
551 | } | ||
552 | |||
553 | struct inode *check_dirty_dir_inode(struct f2fs_sb_info *sbi, nid_t ino) | ||
554 | { | ||
555 | struct list_head *head = &sbi->dir_inode_list; | ||
556 | struct list_head *this; | ||
557 | struct inode *inode = NULL; | ||
558 | |||
559 | spin_lock(&sbi->dir_inode_lock); | ||
560 | list_for_each(this, head) { | ||
561 | struct dir_inode_entry *entry; | ||
562 | entry = list_entry(this, struct dir_inode_entry, list); | ||
563 | if (entry->inode->i_ino == ino) { | ||
564 | inode = entry->inode; | ||
512 | break; | 565 | break; |
513 | } | 566 | } |
514 | } | 567 | } |
515 | out: | ||
516 | spin_unlock(&sbi->dir_inode_lock); | 568 | spin_unlock(&sbi->dir_inode_lock); |
569 | return inode; | ||
517 | } | 570 | } |
518 | 571 | ||
519 | void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi) | 572 | void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi) |
@@ -595,7 +648,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
595 | block_t start_blk; | 648 | block_t start_blk; |
596 | struct page *cp_page; | 649 | struct page *cp_page; |
597 | unsigned int data_sum_blocks, orphan_blocks; | 650 | unsigned int data_sum_blocks, orphan_blocks; |
598 | unsigned int crc32 = 0; | 651 | __u32 crc32 = 0; |
599 | void *kaddr; | 652 | void *kaddr; |
600 | int i; | 653 | int i; |
601 | 654 | ||
@@ -664,8 +717,8 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) | |||
664 | get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); | 717 | get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); |
665 | 718 | ||
666 | crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset)); | 719 | crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset)); |
667 | *(__le32 *)((unsigned char *)ckpt + | 720 | *((__le32 *)((unsigned char *)ckpt + |
668 | le32_to_cpu(ckpt->checksum_offset)) | 721 | le32_to_cpu(ckpt->checksum_offset))) |
669 | = cpu_to_le32(crc32); | 722 | = cpu_to_le32(crc32); |
670 | 723 | ||
671 | start_blk = __start_cp_addr(sbi); | 724 | start_blk = __start_cp_addr(sbi); |
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index ce11d9a92aed..035f9a345cdf 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -68,7 +68,9 @@ 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 | ||
71 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 72 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
73 | #endif | ||
72 | pgoff_t start_fofs, end_fofs; | 74 | pgoff_t start_fofs, end_fofs; |
73 | block_t start_blkaddr; | 75 | block_t start_blkaddr; |
74 | 76 | ||
@@ -78,7 +80,9 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, | |||
78 | return 0; | 80 | return 0; |
79 | } | 81 | } |
80 | 82 | ||
83 | #ifdef CONFIG_F2FS_STAT_FS | ||
81 | sbi->total_hit_ext++; | 84 | sbi->total_hit_ext++; |
85 | #endif | ||
82 | start_fofs = fi->ext.fofs; | 86 | start_fofs = fi->ext.fofs; |
83 | end_fofs = fi->ext.fofs + fi->ext.len - 1; | 87 | end_fofs = fi->ext.fofs + fi->ext.len - 1; |
84 | start_blkaddr = fi->ext.blk_addr; | 88 | start_blkaddr = fi->ext.blk_addr; |
@@ -96,7 +100,9 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs, | |||
96 | else | 100 | else |
97 | bh_result->b_size = UINT_MAX; | 101 | bh_result->b_size = UINT_MAX; |
98 | 102 | ||
103 | #ifdef CONFIG_F2FS_STAT_FS | ||
99 | sbi->read_hit_ext++; | 104 | sbi->read_hit_ext++; |
105 | #endif | ||
100 | read_unlock(&fi->ext.ext_lock); | 106 | read_unlock(&fi->ext.ext_lock); |
101 | return 1; | 107 | return 1; |
102 | } | 108 | } |
@@ -199,7 +205,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync) | |||
199 | if (dn.data_blkaddr == NEW_ADDR) | 205 | if (dn.data_blkaddr == NEW_ADDR) |
200 | return ERR_PTR(-EINVAL); | 206 | return ERR_PTR(-EINVAL); |
201 | 207 | ||
202 | page = grab_cache_page(mapping, index); | 208 | page = grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS); |
203 | if (!page) | 209 | if (!page) |
204 | return ERR_PTR(-ENOMEM); | 210 | return ERR_PTR(-ENOMEM); |
205 | 211 | ||
@@ -233,18 +239,23 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index) | |||
233 | struct page *page; | 239 | struct page *page; |
234 | int err; | 240 | int err; |
235 | 241 | ||
242 | repeat: | ||
243 | page = grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS); | ||
244 | if (!page) | ||
245 | return ERR_PTR(-ENOMEM); | ||
246 | |||
236 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 247 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
237 | err = get_dnode_of_data(&dn, index, LOOKUP_NODE); | 248 | err = get_dnode_of_data(&dn, index, LOOKUP_NODE); |
238 | if (err) | 249 | if (err) { |
250 | f2fs_put_page(page, 1); | ||
239 | return ERR_PTR(err); | 251 | return ERR_PTR(err); |
252 | } | ||
240 | f2fs_put_dnode(&dn); | 253 | f2fs_put_dnode(&dn); |
241 | 254 | ||
242 | if (dn.data_blkaddr == NULL_ADDR) | 255 | if (dn.data_blkaddr == NULL_ADDR) { |
256 | f2fs_put_page(page, 1); | ||
243 | return ERR_PTR(-ENOENT); | 257 | return ERR_PTR(-ENOENT); |
244 | repeat: | 258 | } |
245 | page = grab_cache_page(mapping, index); | ||
246 | if (!page) | ||
247 | return ERR_PTR(-ENOMEM); | ||
248 | 259 | ||
249 | if (PageUptodate(page)) | 260 | if (PageUptodate(page)) |
250 | return page; | 261 | return page; |
@@ -274,9 +285,10 @@ repeat: | |||
274 | * | 285 | * |
275 | * Also, caller should grab and release a mutex by calling mutex_lock_op() and | 286 | * Also, caller should grab and release a mutex by calling mutex_lock_op() and |
276 | * mutex_unlock_op(). | 287 | * mutex_unlock_op(). |
288 | * Note that, npage is set only by make_empty_dir. | ||
277 | */ | 289 | */ |
278 | struct page *get_new_data_page(struct inode *inode, pgoff_t index, | 290 | struct page *get_new_data_page(struct inode *inode, |
279 | bool new_i_size) | 291 | struct page *npage, pgoff_t index, bool new_i_size) |
280 | { | 292 | { |
281 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 293 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
282 | struct address_space *mapping = inode->i_mapping; | 294 | struct address_space *mapping = inode->i_mapping; |
@@ -284,18 +296,20 @@ struct page *get_new_data_page(struct inode *inode, pgoff_t index, | |||
284 | struct dnode_of_data dn; | 296 | struct dnode_of_data dn; |
285 | int err; | 297 | int err; |
286 | 298 | ||
287 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 299 | set_new_dnode(&dn, inode, npage, npage, 0); |
288 | err = get_dnode_of_data(&dn, index, ALLOC_NODE); | 300 | err = get_dnode_of_data(&dn, index, ALLOC_NODE); |
289 | if (err) | 301 | if (err) |
290 | return ERR_PTR(err); | 302 | return ERR_PTR(err); |
291 | 303 | ||
292 | if (dn.data_blkaddr == NULL_ADDR) { | 304 | if (dn.data_blkaddr == NULL_ADDR) { |
293 | if (reserve_new_block(&dn)) { | 305 | if (reserve_new_block(&dn)) { |
294 | f2fs_put_dnode(&dn); | 306 | if (!npage) |
307 | f2fs_put_dnode(&dn); | ||
295 | return ERR_PTR(-ENOSPC); | 308 | return ERR_PTR(-ENOSPC); |
296 | } | 309 | } |
297 | } | 310 | } |
298 | f2fs_put_dnode(&dn); | 311 | if (!npage) |
312 | f2fs_put_dnode(&dn); | ||
299 | repeat: | 313 | repeat: |
300 | page = grab_cache_page(mapping, index); | 314 | page = grab_cache_page(mapping, index); |
301 | if (!page) | 315 | if (!page) |
@@ -325,6 +339,8 @@ repeat: | |||
325 | if (new_i_size && | 339 | if (new_i_size && |
326 | i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) { | 340 | i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) { |
327 | i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT)); | 341 | i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT)); |
342 | /* Only the directory inode sets new_i_size */ | ||
343 | set_inode_flag(F2FS_I(inode), FI_UPDATE_DIR); | ||
328 | mark_inode_dirty_sync(inode); | 344 | mark_inode_dirty_sync(inode); |
329 | } | 345 | } |
330 | return page; | 346 | return page; |
@@ -481,8 +497,9 @@ int do_write_data_page(struct page *page) | |||
481 | * If current allocation needs SSR, | 497 | * If current allocation needs SSR, |
482 | * it had better in-place writes for updated data. | 498 | * it had better in-place writes for updated data. |
483 | */ | 499 | */ |
484 | if (old_blk_addr != NEW_ADDR && !is_cold_data(page) && | 500 | if (unlikely(old_blk_addr != NEW_ADDR && |
485 | need_inplace_update(inode)) { | 501 | !is_cold_data(page) && |
502 | need_inplace_update(inode))) { | ||
486 | rewrite_data_page(F2FS_SB(inode->i_sb), page, | 503 | rewrite_data_page(F2FS_SB(inode->i_sb), page, |
487 | old_blk_addr); | 504 | old_blk_addr); |
488 | } else { | 505 | } else { |
@@ -684,6 +701,27 @@ err: | |||
684 | return err; | 701 | return err; |
685 | } | 702 | } |
686 | 703 | ||
704 | static int f2fs_write_end(struct file *file, | ||
705 | struct address_space *mapping, | ||
706 | loff_t pos, unsigned len, unsigned copied, | ||
707 | struct page *page, void *fsdata) | ||
708 | { | ||
709 | struct inode *inode = page->mapping->host; | ||
710 | |||
711 | SetPageUptodate(page); | ||
712 | set_page_dirty(page); | ||
713 | |||
714 | if (pos + copied > i_size_read(inode)) { | ||
715 | i_size_write(inode, pos + copied); | ||
716 | mark_inode_dirty(inode); | ||
717 | update_inode_page(inode); | ||
718 | } | ||
719 | |||
720 | unlock_page(page); | ||
721 | page_cache_release(page); | ||
722 | return copied; | ||
723 | } | ||
724 | |||
687 | static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, | 725 | static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, |
688 | const struct iovec *iov, loff_t offset, unsigned long nr_segs) | 726 | const struct iovec *iov, loff_t offset, unsigned long nr_segs) |
689 | { | 727 | { |
@@ -741,7 +779,7 @@ const struct address_space_operations f2fs_dblock_aops = { | |||
741 | .writepage = f2fs_write_data_page, | 779 | .writepage = f2fs_write_data_page, |
742 | .writepages = f2fs_write_data_pages, | 780 | .writepages = f2fs_write_data_pages, |
743 | .write_begin = f2fs_write_begin, | 781 | .write_begin = f2fs_write_begin, |
744 | .write_end = nobh_write_end, | 782 | .write_end = f2fs_write_end, |
745 | .set_page_dirty = f2fs_set_data_page_dirty, | 783 | .set_page_dirty = f2fs_set_data_page_dirty, |
746 | .invalidatepage = f2fs_invalidate_data_page, | 784 | .invalidatepage = f2fs_invalidate_data_page, |
747 | .releasepage = f2fs_release_data_page, | 785 | .releasepage = f2fs_release_data_page, |
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 8d9943786c31..0d6c6aafb235 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c | |||
@@ -175,12 +175,12 @@ get_cache: | |||
175 | 175 | ||
176 | static int stat_show(struct seq_file *s, void *v) | 176 | static int stat_show(struct seq_file *s, void *v) |
177 | { | 177 | { |
178 | struct f2fs_stat_info *si, *next; | 178 | struct f2fs_stat_info *si; |
179 | int i = 0; | 179 | int i = 0; |
180 | int j; | 180 | int j; |
181 | 181 | ||
182 | mutex_lock(&f2fs_stat_mutex); | 182 | mutex_lock(&f2fs_stat_mutex); |
183 | list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) { | 183 | list_for_each_entry(si, &f2fs_stat_list, stat_list) { |
184 | char devname[BDEVNAME_SIZE]; | 184 | char devname[BDEVNAME_SIZE]; |
185 | 185 | ||
186 | update_general_status(si->sbi); | 186 | update_general_status(si->sbi); |
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 600bb5efe603..9d1cd423450d 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "f2fs.h" | 13 | #include "f2fs.h" |
14 | #include "node.h" | 14 | #include "node.h" |
15 | #include "acl.h" | 15 | #include "acl.h" |
16 | #include "xattr.h" | ||
16 | 17 | ||
17 | static unsigned long dir_blocks(struct inode *inode) | 18 | static unsigned long dir_blocks(struct inode *inode) |
18 | { | 19 | { |
@@ -215,9 +216,9 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir, | |||
215 | 216 | ||
216 | struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p) | 217 | struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p) |
217 | { | 218 | { |
218 | struct page *page = NULL; | 219 | struct page *page; |
219 | struct f2fs_dir_entry *de = NULL; | 220 | struct f2fs_dir_entry *de; |
220 | struct f2fs_dentry_block *dentry_blk = NULL; | 221 | struct f2fs_dentry_block *dentry_blk; |
221 | 222 | ||
222 | page = get_lock_data_page(dir, 0); | 223 | page = get_lock_data_page(dir, 0); |
223 | if (IS_ERR(page)) | 224 | if (IS_ERR(page)) |
@@ -264,15 +265,10 @@ void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de, | |||
264 | f2fs_put_page(page, 1); | 265 | f2fs_put_page(page, 1); |
265 | } | 266 | } |
266 | 267 | ||
267 | void init_dent_inode(const struct qstr *name, struct page *ipage) | 268 | static void init_dent_inode(const struct qstr *name, struct page *ipage) |
268 | { | 269 | { |
269 | struct f2fs_node *rn; | 270 | struct f2fs_node *rn; |
270 | 271 | ||
271 | if (IS_ERR(ipage)) | ||
272 | return; | ||
273 | |||
274 | wait_on_page_writeback(ipage); | ||
275 | |||
276 | /* copy name info. to this inode page */ | 272 | /* copy name info. to this inode page */ |
277 | rn = (struct f2fs_node *)page_address(ipage); | 273 | rn = (struct f2fs_node *)page_address(ipage); |
278 | rn->i.i_namelen = cpu_to_le32(name->len); | 274 | rn->i.i_namelen = cpu_to_le32(name->len); |
@@ -280,14 +276,15 @@ void init_dent_inode(const struct qstr *name, struct page *ipage) | |||
280 | set_page_dirty(ipage); | 276 | set_page_dirty(ipage); |
281 | } | 277 | } |
282 | 278 | ||
283 | static int make_empty_dir(struct inode *inode, struct inode *parent) | 279 | static int make_empty_dir(struct inode *inode, |
280 | struct inode *parent, struct page *page) | ||
284 | { | 281 | { |
285 | struct page *dentry_page; | 282 | struct page *dentry_page; |
286 | struct f2fs_dentry_block *dentry_blk; | 283 | struct f2fs_dentry_block *dentry_blk; |
287 | struct f2fs_dir_entry *de; | 284 | struct f2fs_dir_entry *de; |
288 | void *kaddr; | 285 | void *kaddr; |
289 | 286 | ||
290 | dentry_page = get_new_data_page(inode, 0, true); | 287 | dentry_page = get_new_data_page(inode, page, 0, true); |
291 | if (IS_ERR(dentry_page)) | 288 | if (IS_ERR(dentry_page)) |
292 | return PTR_ERR(dentry_page); | 289 | return PTR_ERR(dentry_page); |
293 | 290 | ||
@@ -317,63 +314,76 @@ static int make_empty_dir(struct inode *inode, struct inode *parent) | |||
317 | return 0; | 314 | return 0; |
318 | } | 315 | } |
319 | 316 | ||
320 | static int init_inode_metadata(struct inode *inode, | 317 | static struct page *init_inode_metadata(struct inode *inode, |
321 | struct inode *dir, const struct qstr *name) | 318 | struct inode *dir, const struct qstr *name) |
322 | { | 319 | { |
320 | struct page *page; | ||
321 | int err; | ||
322 | |||
323 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { | 323 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { |
324 | int err; | 324 | page = new_inode_page(inode, name); |
325 | err = new_inode_page(inode, name); | 325 | if (IS_ERR(page)) |
326 | if (err) | 326 | return page; |
327 | return err; | ||
328 | 327 | ||
329 | if (S_ISDIR(inode->i_mode)) { | 328 | if (S_ISDIR(inode->i_mode)) { |
330 | err = make_empty_dir(inode, dir); | 329 | err = make_empty_dir(inode, dir, page); |
331 | if (err) { | 330 | if (err) |
332 | remove_inode_page(inode); | 331 | goto error; |
333 | return err; | ||
334 | } | ||
335 | } | 332 | } |
336 | 333 | ||
337 | err = f2fs_init_acl(inode, dir); | 334 | err = f2fs_init_acl(inode, dir); |
338 | if (err) { | 335 | if (err) |
339 | remove_inode_page(inode); | 336 | goto error; |
340 | return err; | 337 | |
341 | } | 338 | err = f2fs_init_security(inode, dir, name, page); |
339 | if (err) | ||
340 | goto error; | ||
341 | |||
342 | wait_on_page_writeback(page); | ||
342 | } else { | 343 | } else { |
343 | struct page *ipage; | 344 | page = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino); |
344 | ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino); | 345 | if (IS_ERR(page)) |
345 | if (IS_ERR(ipage)) | 346 | return page; |
346 | return PTR_ERR(ipage); | 347 | |
347 | set_cold_node(inode, ipage); | 348 | wait_on_page_writeback(page); |
348 | init_dent_inode(name, ipage); | 349 | set_cold_node(inode, page); |
349 | f2fs_put_page(ipage, 1); | ||
350 | } | 350 | } |
351 | |||
352 | init_dent_inode(name, page); | ||
353 | |||
354 | /* | ||
355 | * This file should be checkpointed during fsync. | ||
356 | * We lost i_pino from now on. | ||
357 | */ | ||
351 | if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { | 358 | if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { |
359 | file_lost_pino(inode); | ||
352 | inc_nlink(inode); | 360 | inc_nlink(inode); |
353 | update_inode_page(inode); | ||
354 | } | 361 | } |
355 | return 0; | 362 | return page; |
363 | |||
364 | error: | ||
365 | f2fs_put_page(page, 1); | ||
366 | remove_inode_page(inode); | ||
367 | return ERR_PTR(err); | ||
356 | } | 368 | } |
357 | 369 | ||
358 | static void update_parent_metadata(struct inode *dir, struct inode *inode, | 370 | static void update_parent_metadata(struct inode *dir, struct inode *inode, |
359 | unsigned int current_depth) | 371 | unsigned int current_depth) |
360 | { | 372 | { |
361 | bool need_dir_update = false; | ||
362 | |||
363 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { | 373 | if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { |
364 | if (S_ISDIR(inode->i_mode)) { | 374 | if (S_ISDIR(inode->i_mode)) { |
365 | inc_nlink(dir); | 375 | inc_nlink(dir); |
366 | need_dir_update = true; | 376 | set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); |
367 | } | 377 | } |
368 | clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); | 378 | clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); |
369 | } | 379 | } |
370 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | 380 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; |
371 | if (F2FS_I(dir)->i_current_depth != current_depth) { | 381 | if (F2FS_I(dir)->i_current_depth != current_depth) { |
372 | F2FS_I(dir)->i_current_depth = current_depth; | 382 | F2FS_I(dir)->i_current_depth = current_depth; |
373 | need_dir_update = true; | 383 | set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); |
374 | } | 384 | } |
375 | 385 | ||
376 | if (need_dir_update) | 386 | if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) |
377 | update_inode_page(dir); | 387 | update_inode_page(dir); |
378 | else | 388 | else |
379 | mark_inode_dirty(dir); | 389 | mark_inode_dirty(dir); |
@@ -423,6 +433,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, struct inode *in | |||
423 | struct page *dentry_page = NULL; | 433 | struct page *dentry_page = NULL; |
424 | struct f2fs_dentry_block *dentry_blk = NULL; | 434 | struct f2fs_dentry_block *dentry_blk = NULL; |
425 | int slots = GET_DENTRY_SLOTS(namelen); | 435 | int slots = GET_DENTRY_SLOTS(namelen); |
436 | struct page *page; | ||
426 | int err = 0; | 437 | int err = 0; |
427 | int i; | 438 | int i; |
428 | 439 | ||
@@ -448,7 +459,7 @@ start: | |||
448 | bidx = dir_block_index(level, (le32_to_cpu(dentry_hash) % nbucket)); | 459 | bidx = dir_block_index(level, (le32_to_cpu(dentry_hash) % nbucket)); |
449 | 460 | ||
450 | for (block = bidx; block <= (bidx + nblock - 1); block++) { | 461 | for (block = bidx; block <= (bidx + nblock - 1); block++) { |
451 | dentry_page = get_new_data_page(dir, block, true); | 462 | dentry_page = get_new_data_page(dir, NULL, block, true); |
452 | if (IS_ERR(dentry_page)) | 463 | if (IS_ERR(dentry_page)) |
453 | return PTR_ERR(dentry_page); | 464 | return PTR_ERR(dentry_page); |
454 | 465 | ||
@@ -465,12 +476,13 @@ start: | |||
465 | ++level; | 476 | ++level; |
466 | goto start; | 477 | goto start; |
467 | add_dentry: | 478 | add_dentry: |
468 | err = init_inode_metadata(inode, dir, name); | ||
469 | if (err) | ||
470 | goto fail; | ||
471 | |||
472 | wait_on_page_writeback(dentry_page); | 479 | wait_on_page_writeback(dentry_page); |
473 | 480 | ||
481 | page = init_inode_metadata(inode, dir, name); | ||
482 | if (IS_ERR(page)) { | ||
483 | err = PTR_ERR(page); | ||
484 | goto fail; | ||
485 | } | ||
474 | de = &dentry_blk->dentry[bit_pos]; | 486 | de = &dentry_blk->dentry[bit_pos]; |
475 | de->hash_code = dentry_hash; | 487 | de->hash_code = dentry_hash; |
476 | de->name_len = cpu_to_le16(namelen); | 488 | de->name_len = cpu_to_le16(namelen); |
@@ -481,11 +493,14 @@ add_dentry: | |||
481 | test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); | 493 | test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); |
482 | set_page_dirty(dentry_page); | 494 | set_page_dirty(dentry_page); |
483 | 495 | ||
484 | update_parent_metadata(dir, inode, current_depth); | 496 | /* we don't need to mark_inode_dirty now */ |
485 | |||
486 | /* update parent inode number before releasing dentry page */ | ||
487 | F2FS_I(inode)->i_pino = dir->i_ino; | 497 | F2FS_I(inode)->i_pino = dir->i_ino; |
498 | update_inode(inode, page); | ||
499 | f2fs_put_page(page, 1); | ||
500 | |||
501 | update_parent_metadata(dir, inode, current_depth); | ||
488 | fail: | 502 | fail: |
503 | clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); | ||
489 | kunmap(dentry_page); | 504 | kunmap(dentry_page); |
490 | f2fs_put_page(dentry_page, 1); | 505 | f2fs_put_page(dentry_page, 1); |
491 | return err; | 506 | return err; |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 20aab02f2a42..467d42d65c48 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -37,21 +37,35 @@ | |||
37 | typecheck(unsigned long long, b) && \ | 37 | typecheck(unsigned long long, b) && \ |
38 | ((long long)((a) - (b)) > 0)) | 38 | ((long long)((a) - (b)) > 0)) |
39 | 39 | ||
40 | typedef u64 block_t; | 40 | typedef u32 block_t; /* |
41 | * should not change u32, since it is the on-disk block | ||
42 | * address format, __le32. | ||
43 | */ | ||
41 | typedef u32 nid_t; | 44 | typedef u32 nid_t; |
42 | 45 | ||
43 | struct f2fs_mount_info { | 46 | struct f2fs_mount_info { |
44 | unsigned int opt; | 47 | unsigned int opt; |
45 | }; | 48 | }; |
46 | 49 | ||
47 | static inline __u32 f2fs_crc32(void *buff, size_t len) | 50 | #define CRCPOLY_LE 0xedb88320 |
51 | |||
52 | static inline __u32 f2fs_crc32(void *buf, size_t len) | ||
48 | { | 53 | { |
49 | return crc32_le(F2FS_SUPER_MAGIC, buff, len); | 54 | unsigned char *p = (unsigned char *)buf; |
55 | __u32 crc = F2FS_SUPER_MAGIC; | ||
56 | int i; | ||
57 | |||
58 | while (len--) { | ||
59 | crc ^= *p++; | ||
60 | for (i = 0; i < 8; i++) | ||
61 | crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); | ||
62 | } | ||
63 | return crc; | ||
50 | } | 64 | } |
51 | 65 | ||
52 | static inline bool f2fs_crc_valid(__u32 blk_crc, void *buff, size_t buff_size) | 66 | static inline bool f2fs_crc_valid(__u32 blk_crc, void *buf, size_t buf_size) |
53 | { | 67 | { |
54 | return f2fs_crc32(buff, buff_size) == blk_crc; | 68 | return f2fs_crc32(buf, buf_size) == blk_crc; |
55 | } | 69 | } |
56 | 70 | ||
57 | /* | 71 | /* |
@@ -148,7 +162,7 @@ struct extent_info { | |||
148 | * i_advise uses FADVISE_XXX_BIT. We can add additional hints later. | 162 | * i_advise uses FADVISE_XXX_BIT. We can add additional hints later. |
149 | */ | 163 | */ |
150 | #define FADVISE_COLD_BIT 0x01 | 164 | #define FADVISE_COLD_BIT 0x01 |
151 | #define FADVISE_CP_BIT 0x02 | 165 | #define FADVISE_LOST_PINO_BIT 0x02 |
152 | 166 | ||
153 | struct f2fs_inode_info { | 167 | struct f2fs_inode_info { |
154 | struct inode vfs_inode; /* serve a vfs inode */ | 168 | struct inode vfs_inode; /* serve a vfs inode */ |
@@ -369,7 +383,6 @@ struct f2fs_sb_info { | |||
369 | /* for directory inode management */ | 383 | /* for directory inode management */ |
370 | struct list_head dir_inode_list; /* dir inode list */ | 384 | struct list_head dir_inode_list; /* dir inode list */ |
371 | spinlock_t dir_inode_lock; /* for dir inode list lock */ | 385 | spinlock_t dir_inode_lock; /* for dir inode list lock */ |
372 | unsigned int n_dirty_dirs; /* # of dir inodes */ | ||
373 | 386 | ||
374 | /* basic file system units */ | 387 | /* basic file system units */ |
375 | unsigned int log_sectors_per_block; /* log2 sectors per block */ | 388 | unsigned int log_sectors_per_block; /* log2 sectors per block */ |
@@ -406,12 +419,15 @@ struct f2fs_sb_info { | |||
406 | * for stat information. | 419 | * for stat information. |
407 | * one is for the LFS mode, and the other is for the SSR mode. | 420 | * one is for the LFS mode, and the other is for the SSR mode. |
408 | */ | 421 | */ |
422 | #ifdef CONFIG_F2FS_STAT_FS | ||
409 | struct f2fs_stat_info *stat_info; /* FS status information */ | 423 | struct f2fs_stat_info *stat_info; /* FS status information */ |
410 | unsigned int segment_count[2]; /* # of allocated segments */ | 424 | unsigned int segment_count[2]; /* # of allocated segments */ |
411 | unsigned int block_count[2]; /* # of allocated blocks */ | 425 | unsigned int block_count[2]; /* # of allocated blocks */ |
412 | unsigned int last_victim[2]; /* last victim segment # */ | ||
413 | int total_hit_ext, read_hit_ext; /* extent cache hit ratio */ | 426 | int total_hit_ext, read_hit_ext; /* extent cache hit ratio */ |
414 | int bg_gc; /* background gc calls */ | 427 | int bg_gc; /* background gc calls */ |
428 | unsigned int n_dirty_dirs; /* # of dir inodes */ | ||
429 | #endif | ||
430 | unsigned int last_victim[2]; /* last victim segment # */ | ||
415 | spinlock_t stat_lock; /* lock for stat operations */ | 431 | spinlock_t stat_lock; /* lock for stat operations */ |
416 | }; | 432 | }; |
417 | 433 | ||
@@ -495,9 +511,17 @@ static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f) | |||
495 | 511 | ||
496 | static inline void mutex_lock_all(struct f2fs_sb_info *sbi) | 512 | static inline void mutex_lock_all(struct f2fs_sb_info *sbi) |
497 | { | 513 | { |
498 | int i = 0; | 514 | int i; |
499 | for (; i < NR_GLOBAL_LOCKS; i++) | 515 | |
500 | mutex_lock(&sbi->fs_lock[i]); | 516 | for (i = 0; i < NR_GLOBAL_LOCKS; i++) { |
517 | /* | ||
518 | * This is the only time we take multiple fs_lock[] | ||
519 | * instances; the order is immaterial since we | ||
520 | * always hold cp_mutex, which serializes multiple | ||
521 | * such operations. | ||
522 | */ | ||
523 | mutex_lock_nest_lock(&sbi->fs_lock[i], &sbi->cp_mutex); | ||
524 | } | ||
501 | } | 525 | } |
502 | 526 | ||
503 | static inline void mutex_unlock_all(struct f2fs_sb_info *sbi) | 527 | static inline void mutex_unlock_all(struct f2fs_sb_info *sbi) |
@@ -843,9 +867,12 @@ static inline int f2fs_clear_bit(unsigned int nr, char *addr) | |||
843 | /* used for f2fs_inode_info->flags */ | 867 | /* used for f2fs_inode_info->flags */ |
844 | enum { | 868 | enum { |
845 | FI_NEW_INODE, /* indicate newly allocated inode */ | 869 | FI_NEW_INODE, /* indicate newly allocated inode */ |
870 | FI_DIRTY_INODE, /* indicate inode is dirty or not */ | ||
846 | FI_INC_LINK, /* need to increment i_nlink */ | 871 | FI_INC_LINK, /* need to increment i_nlink */ |
847 | FI_ACL_MODE, /* indicate acl mode */ | 872 | FI_ACL_MODE, /* indicate acl mode */ |
848 | FI_NO_ALLOC, /* should not allocate any blocks */ | 873 | FI_NO_ALLOC, /* should not allocate any blocks */ |
874 | FI_UPDATE_DIR, /* should update inode block for consistency */ | ||
875 | FI_DELAY_IPUT, /* used for the recovery */ | ||
849 | }; | 876 | }; |
850 | 877 | ||
851 | static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag) | 878 | static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag) |
@@ -878,14 +905,21 @@ static inline int cond_clear_inode_flag(struct f2fs_inode_info *fi, int flag) | |||
878 | return 0; | 905 | return 0; |
879 | } | 906 | } |
880 | 907 | ||
908 | static inline int f2fs_readonly(struct super_block *sb) | ||
909 | { | ||
910 | return sb->s_flags & MS_RDONLY; | ||
911 | } | ||
912 | |||
881 | /* | 913 | /* |
882 | * file.c | 914 | * file.c |
883 | */ | 915 | */ |
884 | int f2fs_sync_file(struct file *, loff_t, loff_t, int); | 916 | int f2fs_sync_file(struct file *, loff_t, loff_t, int); |
885 | void truncate_data_blocks(struct dnode_of_data *); | 917 | void truncate_data_blocks(struct dnode_of_data *); |
886 | void f2fs_truncate(struct inode *); | 918 | void f2fs_truncate(struct inode *); |
919 | int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | ||
887 | int f2fs_setattr(struct dentry *, struct iattr *); | 920 | int f2fs_setattr(struct dentry *, struct iattr *); |
888 | int truncate_hole(struct inode *, pgoff_t, pgoff_t); | 921 | int truncate_hole(struct inode *, pgoff_t, pgoff_t); |
922 | int truncate_data_blocks_range(struct dnode_of_data *, int); | ||
889 | long f2fs_ioctl(struct file *, unsigned int, unsigned long); | 923 | long f2fs_ioctl(struct file *, unsigned int, unsigned long); |
890 | long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long); | 924 | long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long); |
891 | 925 | ||
@@ -913,7 +947,6 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **); | |||
913 | ino_t f2fs_inode_by_name(struct inode *, struct qstr *); | 947 | ino_t f2fs_inode_by_name(struct inode *, struct qstr *); |
914 | void f2fs_set_link(struct inode *, struct f2fs_dir_entry *, | 948 | void f2fs_set_link(struct inode *, struct f2fs_dir_entry *, |
915 | struct page *, struct inode *); | 949 | struct page *, struct inode *); |
916 | void init_dent_inode(const struct qstr *, struct page *); | ||
917 | int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *); | 950 | int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *); |
918 | void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *); | 951 | void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *); |
919 | int f2fs_make_empty(struct inode *, struct inode *); | 952 | int f2fs_make_empty(struct inode *, struct inode *); |
@@ -948,8 +981,8 @@ void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); | |||
948 | int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); | 981 | int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); |
949 | int truncate_inode_blocks(struct inode *, pgoff_t); | 982 | int truncate_inode_blocks(struct inode *, pgoff_t); |
950 | int remove_inode_page(struct inode *); | 983 | int remove_inode_page(struct inode *); |
951 | int new_inode_page(struct inode *, const struct qstr *); | 984 | struct page *new_inode_page(struct inode *, const struct qstr *); |
952 | struct page *new_node_page(struct dnode_of_data *, unsigned int); | 985 | struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *); |
953 | void ra_node_page(struct f2fs_sb_info *, nid_t); | 986 | void ra_node_page(struct f2fs_sb_info *, nid_t); |
954 | struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); | 987 | struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); |
955 | struct page *get_node_page_ra(struct page *, int); | 988 | struct page *get_node_page_ra(struct page *, int); |
@@ -974,7 +1007,6 @@ void destroy_node_manager_caches(void); | |||
974 | */ | 1007 | */ |
975 | void f2fs_balance_fs(struct f2fs_sb_info *); | 1008 | void f2fs_balance_fs(struct f2fs_sb_info *); |
976 | void invalidate_blocks(struct f2fs_sb_info *, block_t); | 1009 | void invalidate_blocks(struct f2fs_sb_info *, block_t); |
977 | void locate_dirty_segment(struct f2fs_sb_info *, unsigned int); | ||
978 | void clear_prefree_segments(struct f2fs_sb_info *); | 1010 | void clear_prefree_segments(struct f2fs_sb_info *); |
979 | int npages_for_summary_flush(struct f2fs_sb_info *); | 1011 | int npages_for_summary_flush(struct f2fs_sb_info *); |
980 | void allocate_new_segments(struct f2fs_sb_info *); | 1012 | void allocate_new_segments(struct f2fs_sb_info *); |
@@ -1011,7 +1043,9 @@ void remove_orphan_inode(struct f2fs_sb_info *, nid_t); | |||
1011 | int recover_orphan_inodes(struct f2fs_sb_info *); | 1043 | int recover_orphan_inodes(struct f2fs_sb_info *); |
1012 | int get_valid_checkpoint(struct f2fs_sb_info *); | 1044 | int get_valid_checkpoint(struct f2fs_sb_info *); |
1013 | void set_dirty_dir_page(struct inode *, struct page *); | 1045 | void set_dirty_dir_page(struct inode *, struct page *); |
1046 | void add_dirty_dir_inode(struct inode *); | ||
1014 | void remove_dirty_dir_inode(struct inode *); | 1047 | void remove_dirty_dir_inode(struct inode *); |
1048 | struct inode *check_dirty_dir_inode(struct f2fs_sb_info *, nid_t); | ||
1015 | void sync_dirty_dir_inodes(struct f2fs_sb_info *); | 1049 | void sync_dirty_dir_inodes(struct f2fs_sb_info *); |
1016 | void write_checkpoint(struct f2fs_sb_info *, bool); | 1050 | void write_checkpoint(struct f2fs_sb_info *, bool); |
1017 | void init_orphan_info(struct f2fs_sb_info *); | 1051 | void init_orphan_info(struct f2fs_sb_info *); |
@@ -1025,7 +1059,7 @@ int reserve_new_block(struct dnode_of_data *); | |||
1025 | void update_extent_cache(block_t, struct dnode_of_data *); | 1059 | void update_extent_cache(block_t, struct dnode_of_data *); |
1026 | struct page *find_data_page(struct inode *, pgoff_t, bool); | 1060 | struct page *find_data_page(struct inode *, pgoff_t, bool); |
1027 | struct page *get_lock_data_page(struct inode *, pgoff_t); | 1061 | struct page *get_lock_data_page(struct inode *, pgoff_t); |
1028 | struct page *get_new_data_page(struct inode *, pgoff_t, bool); | 1062 | struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool); |
1029 | int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int); | 1063 | int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int); |
1030 | int do_write_data_page(struct page *); | 1064 | int do_write_data_page(struct page *); |
1031 | 1065 | ||
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 1cae864f8dfc..d2d2b7dbdcc1 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -63,9 +63,10 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
63 | f2fs_put_dnode(&dn); | 63 | f2fs_put_dnode(&dn); |
64 | mutex_unlock_op(sbi, ilock); | 64 | mutex_unlock_op(sbi, ilock); |
65 | 65 | ||
66 | file_update_time(vma->vm_file); | ||
66 | lock_page(page); | 67 | lock_page(page); |
67 | if (page->mapping != inode->i_mapping || | 68 | if (page->mapping != inode->i_mapping || |
68 | page_offset(page) >= i_size_read(inode) || | 69 | page_offset(page) > i_size_read(inode) || |
69 | !PageUptodate(page)) { | 70 | !PageUptodate(page)) { |
70 | unlock_page(page); | 71 | unlock_page(page); |
71 | err = -EFAULT; | 72 | err = -EFAULT; |
@@ -76,10 +77,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
76 | * check to see if the page is mapped already (no holes) | 77 | * check to see if the page is mapped already (no holes) |
77 | */ | 78 | */ |
78 | if (PageMappedToDisk(page)) | 79 | if (PageMappedToDisk(page)) |
79 | goto out; | 80 | goto mapped; |
80 | |||
81 | /* fill the page */ | ||
82 | wait_on_page_writeback(page); | ||
83 | 81 | ||
84 | /* page is wholly or partially inside EOF */ | 82 | /* page is wholly or partially inside EOF */ |
85 | if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) { | 83 | if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) { |
@@ -90,7 +88,9 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
90 | set_page_dirty(page); | 88 | set_page_dirty(page); |
91 | SetPageUptodate(page); | 89 | SetPageUptodate(page); |
92 | 90 | ||
93 | file_update_time(vma->vm_file); | 91 | mapped: |
92 | /* fill the page */ | ||
93 | wait_on_page_writeback(page); | ||
94 | out: | 94 | out: |
95 | sb_end_pagefault(inode->i_sb); | 95 | sb_end_pagefault(inode->i_sb); |
96 | return block_page_mkwrite_return(err); | 96 | return block_page_mkwrite_return(err); |
@@ -102,6 +102,24 @@ static const struct vm_operations_struct f2fs_file_vm_ops = { | |||
102 | .remap_pages = generic_file_remap_pages, | 102 | .remap_pages = generic_file_remap_pages, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static int get_parent_ino(struct inode *inode, nid_t *pino) | ||
106 | { | ||
107 | struct dentry *dentry; | ||
108 | |||
109 | inode = igrab(inode); | ||
110 | dentry = d_find_any_alias(inode); | ||
111 | iput(inode); | ||
112 | if (!dentry) | ||
113 | return 0; | ||
114 | |||
115 | inode = igrab(dentry->d_parent->d_inode); | ||
116 | dput(dentry); | ||
117 | |||
118 | *pino = inode->i_ino; | ||
119 | iput(inode); | ||
120 | return 1; | ||
121 | } | ||
122 | |||
105 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | 123 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) |
106 | { | 124 | { |
107 | struct inode *inode = file->f_mapping->host; | 125 | struct inode *inode = file->f_mapping->host; |
@@ -114,7 +132,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
114 | .for_reclaim = 0, | 132 | .for_reclaim = 0, |
115 | }; | 133 | }; |
116 | 134 | ||
117 | if (inode->i_sb->s_flags & MS_RDONLY) | 135 | if (f2fs_readonly(inode->i_sb)) |
118 | return 0; | 136 | return 0; |
119 | 137 | ||
120 | trace_f2fs_sync_file_enter(inode); | 138 | trace_f2fs_sync_file_enter(inode); |
@@ -134,7 +152,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
134 | 152 | ||
135 | if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) | 153 | if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) |
136 | need_cp = true; | 154 | need_cp = true; |
137 | else if (is_cp_file(inode)) | 155 | else if (file_wrong_pino(inode)) |
138 | need_cp = true; | 156 | need_cp = true; |
139 | else if (!space_for_roll_forward(sbi)) | 157 | else if (!space_for_roll_forward(sbi)) |
140 | need_cp = true; | 158 | need_cp = true; |
@@ -142,11 +160,23 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
142 | need_cp = true; | 160 | need_cp = true; |
143 | 161 | ||
144 | if (need_cp) { | 162 | if (need_cp) { |
163 | nid_t pino; | ||
164 | |||
145 | /* all the dirty node pages should be flushed for POR */ | 165 | /* all the dirty node pages should be flushed for POR */ |
146 | ret = f2fs_sync_fs(inode->i_sb, 1); | 166 | ret = f2fs_sync_fs(inode->i_sb, 1); |
167 | if (file_wrong_pino(inode) && inode->i_nlink == 1 && | ||
168 | get_parent_ino(inode, &pino)) { | ||
169 | F2FS_I(inode)->i_pino = pino; | ||
170 | file_got_pino(inode); | ||
171 | mark_inode_dirty_sync(inode); | ||
172 | ret = f2fs_write_inode(inode, NULL); | ||
173 | if (ret) | ||
174 | goto out; | ||
175 | } | ||
147 | } else { | 176 | } else { |
148 | /* if there is no written node page, write its inode page */ | 177 | /* if there is no written node page, write its inode page */ |
149 | while (!sync_node_pages(sbi, inode->i_ino, &wbc)) { | 178 | while (!sync_node_pages(sbi, inode->i_ino, &wbc)) { |
179 | mark_inode_dirty_sync(inode); | ||
150 | ret = f2fs_write_inode(inode, NULL); | 180 | ret = f2fs_write_inode(inode, NULL); |
151 | if (ret) | 181 | if (ret) |
152 | goto out; | 182 | goto out; |
@@ -168,7 +198,7 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
168 | return 0; | 198 | return 0; |
169 | } | 199 | } |
170 | 200 | ||
171 | static int truncate_data_blocks_range(struct dnode_of_data *dn, int count) | 201 | int truncate_data_blocks_range(struct dnode_of_data *dn, int count) |
172 | { | 202 | { |
173 | int nr_free = 0, ofs = dn->ofs_in_node; | 203 | int nr_free = 0, ofs = dn->ofs_in_node; |
174 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 204 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
@@ -185,10 +215,10 @@ static int truncate_data_blocks_range(struct dnode_of_data *dn, int count) | |||
185 | 215 | ||
186 | update_extent_cache(NULL_ADDR, dn); | 216 | update_extent_cache(NULL_ADDR, dn); |
187 | invalidate_blocks(sbi, blkaddr); | 217 | invalidate_blocks(sbi, blkaddr); |
188 | dec_valid_block_count(sbi, dn->inode, 1); | ||
189 | nr_free++; | 218 | nr_free++; |
190 | } | 219 | } |
191 | if (nr_free) { | 220 | if (nr_free) { |
221 | dec_valid_block_count(sbi, dn->inode, nr_free); | ||
192 | set_page_dirty(dn->node_page); | 222 | set_page_dirty(dn->node_page); |
193 | sync_inode_page(dn); | 223 | sync_inode_page(dn); |
194 | } | 224 | } |
@@ -291,7 +321,7 @@ void f2fs_truncate(struct inode *inode) | |||
291 | } | 321 | } |
292 | } | 322 | } |
293 | 323 | ||
294 | static int f2fs_getattr(struct vfsmount *mnt, | 324 | int f2fs_getattr(struct vfsmount *mnt, |
295 | struct dentry *dentry, struct kstat *stat) | 325 | struct dentry *dentry, struct kstat *stat) |
296 | { | 326 | { |
297 | struct inode *inode = dentry->d_inode; | 327 | struct inode *inode = dentry->d_inode; |
@@ -387,7 +417,7 @@ static void fill_zero(struct inode *inode, pgoff_t index, | |||
387 | f2fs_balance_fs(sbi); | 417 | f2fs_balance_fs(sbi); |
388 | 418 | ||
389 | ilock = mutex_lock_op(sbi); | 419 | ilock = mutex_lock_op(sbi); |
390 | page = get_new_data_page(inode, index, false); | 420 | page = get_new_data_page(inode, NULL, index, false); |
391 | mutex_unlock_op(sbi, ilock); | 421 | mutex_unlock_op(sbi, ilock); |
392 | 422 | ||
393 | if (!IS_ERR(page)) { | 423 | if (!IS_ERR(page)) { |
@@ -575,10 +605,10 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
575 | int ret; | 605 | int ret; |
576 | 606 | ||
577 | switch (cmd) { | 607 | switch (cmd) { |
578 | case FS_IOC_GETFLAGS: | 608 | case F2FS_IOC_GETFLAGS: |
579 | flags = fi->i_flags & FS_FL_USER_VISIBLE; | 609 | flags = fi->i_flags & FS_FL_USER_VISIBLE; |
580 | return put_user(flags, (int __user *) arg); | 610 | return put_user(flags, (int __user *) arg); |
581 | case FS_IOC_SETFLAGS: | 611 | case F2FS_IOC_SETFLAGS: |
582 | { | 612 | { |
583 | unsigned int oldflags; | 613 | unsigned int oldflags; |
584 | 614 | ||
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 14961593e93c..35f9b1a196aa 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -76,7 +76,9 @@ static int gc_thread_func(void *data) | |||
76 | else | 76 | else |
77 | wait_ms = increase_sleep_time(wait_ms); | 77 | wait_ms = increase_sleep_time(wait_ms); |
78 | 78 | ||
79 | #ifdef CONFIG_F2FS_STAT_FS | ||
79 | sbi->bg_gc++; | 80 | sbi->bg_gc++; |
81 | #endif | ||
80 | 82 | ||
81 | /* if return value is not zero, no victim was selected */ | 83 | /* if return value is not zero, no victim was selected */ |
82 | if (f2fs_gc(sbi)) | 84 | if (f2fs_gc(sbi)) |
@@ -89,23 +91,28 @@ int start_gc_thread(struct f2fs_sb_info *sbi) | |||
89 | { | 91 | { |
90 | struct f2fs_gc_kthread *gc_th; | 92 | struct f2fs_gc_kthread *gc_th; |
91 | dev_t dev = sbi->sb->s_bdev->bd_dev; | 93 | dev_t dev = sbi->sb->s_bdev->bd_dev; |
94 | int err = 0; | ||
92 | 95 | ||
93 | if (!test_opt(sbi, BG_GC)) | 96 | if (!test_opt(sbi, BG_GC)) |
94 | return 0; | 97 | goto out; |
95 | gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL); | 98 | gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL); |
96 | if (!gc_th) | 99 | if (!gc_th) { |
97 | return -ENOMEM; | 100 | err = -ENOMEM; |
101 | goto out; | ||
102 | } | ||
98 | 103 | ||
99 | sbi->gc_thread = gc_th; | 104 | sbi->gc_thread = gc_th; |
100 | init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head); | 105 | init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head); |
101 | sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi, | 106 | sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi, |
102 | "f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev)); | 107 | "f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev)); |
103 | if (IS_ERR(gc_th->f2fs_gc_task)) { | 108 | if (IS_ERR(gc_th->f2fs_gc_task)) { |
109 | err = PTR_ERR(gc_th->f2fs_gc_task); | ||
104 | kfree(gc_th); | 110 | kfree(gc_th); |
105 | sbi->gc_thread = NULL; | 111 | sbi->gc_thread = NULL; |
106 | return -ENOMEM; | ||
107 | } | 112 | } |
108 | return 0; | 113 | |
114 | out: | ||
115 | return err; | ||
109 | } | 116 | } |
110 | 117 | ||
111 | void stop_gc_thread(struct f2fs_sb_info *sbi) | 118 | void stop_gc_thread(struct f2fs_sb_info *sbi) |
@@ -234,14 +241,14 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
234 | { | 241 | { |
235 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 242 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
236 | struct victim_sel_policy p; | 243 | struct victim_sel_policy p; |
237 | unsigned int secno; | 244 | unsigned int secno, max_cost; |
238 | int nsearched = 0; | 245 | int nsearched = 0; |
239 | 246 | ||
240 | p.alloc_mode = alloc_mode; | 247 | p.alloc_mode = alloc_mode; |
241 | select_policy(sbi, gc_type, type, &p); | 248 | select_policy(sbi, gc_type, type, &p); |
242 | 249 | ||
243 | p.min_segno = NULL_SEGNO; | 250 | p.min_segno = NULL_SEGNO; |
244 | p.min_cost = get_max_cost(sbi, &p); | 251 | p.min_cost = max_cost = get_max_cost(sbi, &p); |
245 | 252 | ||
246 | mutex_lock(&dirty_i->seglist_lock); | 253 | mutex_lock(&dirty_i->seglist_lock); |
247 | 254 | ||
@@ -280,7 +287,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
280 | p.min_cost = cost; | 287 | p.min_cost = cost; |
281 | } | 288 | } |
282 | 289 | ||
283 | if (cost == get_max_cost(sbi, &p)) | 290 | if (cost == max_cost) |
284 | continue; | 291 | continue; |
285 | 292 | ||
286 | if (nsearched++ >= MAX_VICTIM_SEARCH) { | 293 | if (nsearched++ >= MAX_VICTIM_SEARCH) { |
@@ -288,8 +295,8 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
288 | break; | 295 | break; |
289 | } | 296 | } |
290 | } | 297 | } |
291 | got_it: | ||
292 | if (p.min_segno != NULL_SEGNO) { | 298 | if (p.min_segno != NULL_SEGNO) { |
299 | got_it: | ||
293 | if (p.alloc_mode == LFS) { | 300 | if (p.alloc_mode == LFS) { |
294 | secno = GET_SECNO(sbi, p.min_segno); | 301 | secno = GET_SECNO(sbi, p.min_segno); |
295 | if (gc_type == FG_GC) | 302 | if (gc_type == FG_GC) |
@@ -314,28 +321,21 @@ static const struct victim_selection default_v_ops = { | |||
314 | 321 | ||
315 | static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist) | 322 | static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist) |
316 | { | 323 | { |
317 | struct list_head *this; | ||
318 | struct inode_entry *ie; | 324 | struct inode_entry *ie; |
319 | 325 | ||
320 | list_for_each(this, ilist) { | 326 | list_for_each_entry(ie, ilist, list) |
321 | ie = list_entry(this, struct inode_entry, list); | ||
322 | if (ie->inode->i_ino == ino) | 327 | if (ie->inode->i_ino == ino) |
323 | return ie->inode; | 328 | return ie->inode; |
324 | } | ||
325 | return NULL; | 329 | return NULL; |
326 | } | 330 | } |
327 | 331 | ||
328 | static void add_gc_inode(struct inode *inode, struct list_head *ilist) | 332 | static void add_gc_inode(struct inode *inode, struct list_head *ilist) |
329 | { | 333 | { |
330 | struct list_head *this; | 334 | struct inode_entry *new_ie; |
331 | struct inode_entry *new_ie, *ie; | ||
332 | 335 | ||
333 | list_for_each(this, ilist) { | 336 | if (inode == find_gc_inode(inode->i_ino, ilist)) { |
334 | ie = list_entry(this, struct inode_entry, list); | 337 | iput(inode); |
335 | if (ie->inode == inode) { | 338 | return; |
336 | iput(inode); | ||
337 | return; | ||
338 | } | ||
339 | } | 339 | } |
340 | repeat: | 340 | repeat: |
341 | new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS); | 341 | new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS); |
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 91ac7f9d88ee..2b2d45d19e3e 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c | |||
@@ -109,12 +109,6 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino) | |||
109 | ret = do_read_inode(inode); | 109 | ret = do_read_inode(inode); |
110 | if (ret) | 110 | if (ret) |
111 | goto bad_inode; | 111 | goto bad_inode; |
112 | |||
113 | if (!sbi->por_doing && inode->i_nlink == 0) { | ||
114 | ret = -ENOENT; | ||
115 | goto bad_inode; | ||
116 | } | ||
117 | |||
118 | make_now: | 112 | make_now: |
119 | if (ino == F2FS_NODE_INO(sbi)) { | 113 | if (ino == F2FS_NODE_INO(sbi)) { |
120 | inode->i_mapping->a_ops = &f2fs_node_aops; | 114 | inode->i_mapping->a_ops = &f2fs_node_aops; |
@@ -130,8 +124,7 @@ make_now: | |||
130 | inode->i_op = &f2fs_dir_inode_operations; | 124 | inode->i_op = &f2fs_dir_inode_operations; |
131 | inode->i_fop = &f2fs_dir_operations; | 125 | inode->i_fop = &f2fs_dir_operations; |
132 | inode->i_mapping->a_ops = &f2fs_dblock_aops; | 126 | inode->i_mapping->a_ops = &f2fs_dblock_aops; |
133 | mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER_MOVABLE | | 127 | mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); |
134 | __GFP_ZERO); | ||
135 | } else if (S_ISLNK(inode->i_mode)) { | 128 | } else if (S_ISLNK(inode->i_mode)) { |
136 | inode->i_op = &f2fs_symlink_inode_operations; | 129 | inode->i_op = &f2fs_symlink_inode_operations; |
137 | inode->i_mapping->a_ops = &f2fs_dblock_aops; | 130 | inode->i_mapping->a_ops = &f2fs_dblock_aops; |
@@ -199,6 +192,7 @@ void update_inode(struct inode *inode, struct page *node_page) | |||
199 | 192 | ||
200 | set_cold_node(inode, node_page); | 193 | set_cold_node(inode, node_page); |
201 | set_page_dirty(node_page); | 194 | set_page_dirty(node_page); |
195 | clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); | ||
202 | } | 196 | } |
203 | 197 | ||
204 | int update_inode_page(struct inode *inode) | 198 | int update_inode_page(struct inode *inode) |
@@ -224,6 +218,9 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
224 | inode->i_ino == F2FS_META_INO(sbi)) | 218 | inode->i_ino == F2FS_META_INO(sbi)) |
225 | return 0; | 219 | return 0; |
226 | 220 | ||
221 | if (!is_inode_flag_set(F2FS_I(inode), FI_DIRTY_INODE)) | ||
222 | return 0; | ||
223 | |||
227 | if (wbc) | 224 | if (wbc) |
228 | f2fs_balance_fs(sbi); | 225 | f2fs_balance_fs(sbi); |
229 | 226 | ||
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 47abc9722b17..64c07169df05 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c | |||
@@ -112,7 +112,7 @@ static inline void set_cold_files(struct f2fs_sb_info *sbi, struct inode *inode, | |||
112 | int count = le32_to_cpu(sbi->raw_super->extension_count); | 112 | int count = le32_to_cpu(sbi->raw_super->extension_count); |
113 | for (i = 0; i < count; i++) { | 113 | for (i = 0; i < count; i++) { |
114 | if (is_multimedia_file(name, extlist[i])) { | 114 | if (is_multimedia_file(name, extlist[i])) { |
115 | set_cold_file(inode); | 115 | file_set_cold(inode); |
116 | break; | 116 | break; |
117 | } | 117 | } |
118 | } | 118 | } |
@@ -149,8 +149,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
149 | 149 | ||
150 | alloc_nid_done(sbi, ino); | 150 | alloc_nid_done(sbi, ino); |
151 | 151 | ||
152 | if (!sbi->por_doing) | 152 | d_instantiate(dentry, inode); |
153 | d_instantiate(dentry, inode); | ||
154 | unlock_new_inode(inode); | 153 | unlock_new_inode(inode); |
155 | return 0; | 154 | return 0; |
156 | out: | 155 | out: |
@@ -173,7 +172,7 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, | |||
173 | f2fs_balance_fs(sbi); | 172 | f2fs_balance_fs(sbi); |
174 | 173 | ||
175 | inode->i_ctime = CURRENT_TIME; | 174 | inode->i_ctime = CURRENT_TIME; |
176 | atomic_inc(&inode->i_count); | 175 | ihold(inode); |
177 | 176 | ||
178 | set_inode_flag(F2FS_I(inode), FI_INC_LINK); | 177 | set_inode_flag(F2FS_I(inode), FI_INC_LINK); |
179 | ilock = mutex_lock_op(sbi); | 178 | ilock = mutex_lock_op(sbi); |
@@ -182,17 +181,10 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, | |||
182 | if (err) | 181 | if (err) |
183 | goto out; | 182 | goto out; |
184 | 183 | ||
185 | /* | ||
186 | * This file should be checkpointed during fsync. | ||
187 | * We lost i_pino from now on. | ||
188 | */ | ||
189 | set_cp_file(inode); | ||
190 | |||
191 | d_instantiate(dentry, inode); | 184 | d_instantiate(dentry, inode); |
192 | return 0; | 185 | return 0; |
193 | out: | 186 | out: |
194 | clear_inode_flag(F2FS_I(inode), FI_INC_LINK); | 187 | clear_inode_flag(F2FS_I(inode), FI_INC_LINK); |
195 | make_bad_inode(inode); | ||
196 | iput(inode); | 188 | iput(inode); |
197 | return err; | 189 | return err; |
198 | } | 190 | } |
@@ -498,6 +490,7 @@ const struct inode_operations f2fs_dir_inode_operations = { | |||
498 | .rmdir = f2fs_rmdir, | 490 | .rmdir = f2fs_rmdir, |
499 | .mknod = f2fs_mknod, | 491 | .mknod = f2fs_mknod, |
500 | .rename = f2fs_rename, | 492 | .rename = f2fs_rename, |
493 | .getattr = f2fs_getattr, | ||
501 | .setattr = f2fs_setattr, | 494 | .setattr = f2fs_setattr, |
502 | .get_acl = f2fs_get_acl, | 495 | .get_acl = f2fs_get_acl, |
503 | #ifdef CONFIG_F2FS_FS_XATTR | 496 | #ifdef CONFIG_F2FS_FS_XATTR |
@@ -512,6 +505,7 @@ const struct inode_operations f2fs_symlink_inode_operations = { | |||
512 | .readlink = generic_readlink, | 505 | .readlink = generic_readlink, |
513 | .follow_link = page_follow_link_light, | 506 | .follow_link = page_follow_link_light, |
514 | .put_link = page_put_link, | 507 | .put_link = page_put_link, |
508 | .getattr = f2fs_getattr, | ||
515 | .setattr = f2fs_setattr, | 509 | .setattr = f2fs_setattr, |
516 | #ifdef CONFIG_F2FS_FS_XATTR | 510 | #ifdef CONFIG_F2FS_FS_XATTR |
517 | .setxattr = generic_setxattr, | 511 | .setxattr = generic_setxattr, |
@@ -522,6 +516,7 @@ const struct inode_operations f2fs_symlink_inode_operations = { | |||
522 | }; | 516 | }; |
523 | 517 | ||
524 | const struct inode_operations f2fs_special_inode_operations = { | 518 | const struct inode_operations f2fs_special_inode_operations = { |
519 | .getattr = f2fs_getattr, | ||
525 | .setattr = f2fs_setattr, | 520 | .setattr = f2fs_setattr, |
526 | .get_acl = f2fs_get_acl, | 521 | .get_acl = f2fs_get_acl, |
527 | #ifdef CONFIG_F2FS_FS_XATTR | 522 | #ifdef CONFIG_F2FS_FS_XATTR |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 74f3c7b03eb2..b418aee09573 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -408,10 +408,13 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) | |||
408 | level = get_node_path(index, offset, noffset); | 408 | level = get_node_path(index, offset, noffset); |
409 | 409 | ||
410 | nids[0] = dn->inode->i_ino; | 410 | nids[0] = dn->inode->i_ino; |
411 | npage[0] = get_node_page(sbi, nids[0]); | 411 | npage[0] = dn->inode_page; |
412 | if (IS_ERR(npage[0])) | ||
413 | return PTR_ERR(npage[0]); | ||
414 | 412 | ||
413 | if (!npage[0]) { | ||
414 | npage[0] = get_node_page(sbi, nids[0]); | ||
415 | if (IS_ERR(npage[0])) | ||
416 | return PTR_ERR(npage[0]); | ||
417 | } | ||
415 | parent = npage[0]; | 418 | parent = npage[0]; |
416 | if (level != 0) | 419 | if (level != 0) |
417 | nids[1] = get_nid(parent, offset[0], true); | 420 | nids[1] = get_nid(parent, offset[0], true); |
@@ -430,7 +433,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) | |||
430 | } | 433 | } |
431 | 434 | ||
432 | dn->nid = nids[i]; | 435 | dn->nid = nids[i]; |
433 | npage[i] = new_node_page(dn, noffset[i]); | 436 | npage[i] = new_node_page(dn, noffset[i], NULL); |
434 | if (IS_ERR(npage[i])) { | 437 | if (IS_ERR(npage[i])) { |
435 | alloc_nid_failed(sbi, nids[i]); | 438 | alloc_nid_failed(sbi, nids[i]); |
436 | err = PTR_ERR(npage[i]); | 439 | err = PTR_ERR(npage[i]); |
@@ -803,22 +806,19 @@ int remove_inode_page(struct inode *inode) | |||
803 | return 0; | 806 | return 0; |
804 | } | 807 | } |
805 | 808 | ||
806 | int new_inode_page(struct inode *inode, const struct qstr *name) | 809 | struct page *new_inode_page(struct inode *inode, const struct qstr *name) |
807 | { | 810 | { |
808 | struct page *page; | ||
809 | struct dnode_of_data dn; | 811 | struct dnode_of_data dn; |
810 | 812 | ||
811 | /* allocate inode page for new inode */ | 813 | /* allocate inode page for new inode */ |
812 | set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); | 814 | set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); |
813 | page = new_node_page(&dn, 0); | 815 | |
814 | init_dent_inode(name, page); | 816 | /* caller should f2fs_put_page(page, 1); */ |
815 | if (IS_ERR(page)) | 817 | return new_node_page(&dn, 0, NULL); |
816 | return PTR_ERR(page); | ||
817 | f2fs_put_page(page, 1); | ||
818 | return 0; | ||
819 | } | 818 | } |
820 | 819 | ||
821 | struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs) | 820 | struct page *new_node_page(struct dnode_of_data *dn, |
821 | unsigned int ofs, struct page *ipage) | ||
822 | { | 822 | { |
823 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 823 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
824 | struct address_space *mapping = sbi->node_inode->i_mapping; | 824 | struct address_space *mapping = sbi->node_inode->i_mapping; |
@@ -851,7 +851,10 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs) | |||
851 | set_cold_node(dn->inode, page); | 851 | set_cold_node(dn->inode, page); |
852 | 852 | ||
853 | dn->node_page = page; | 853 | dn->node_page = page; |
854 | sync_inode_page(dn); | 854 | if (ipage) |
855 | update_inode(dn->inode, ipage); | ||
856 | else | ||
857 | sync_inode_page(dn); | ||
855 | set_page_dirty(page); | 858 | set_page_dirty(page); |
856 | if (ofs == 0) | 859 | if (ofs == 0) |
857 | inc_valid_inode_count(sbi); | 860 | inc_valid_inode_count(sbi); |
@@ -1493,9 +1496,10 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) | |||
1493 | new_ni = old_ni; | 1496 | new_ni = old_ni; |
1494 | new_ni.ino = ino; | 1497 | new_ni.ino = ino; |
1495 | 1498 | ||
1499 | if (!inc_valid_node_count(sbi, NULL, 1)) | ||
1500 | WARN_ON(1); | ||
1496 | set_node_addr(sbi, &new_ni, NEW_ADDR); | 1501 | set_node_addr(sbi, &new_ni, NEW_ADDR); |
1497 | inc_valid_inode_count(sbi); | 1502 | inc_valid_inode_count(sbi); |
1498 | |||
1499 | f2fs_put_page(ipage, 1); | 1503 | f2fs_put_page(ipage, 1); |
1500 | return 0; | 1504 | return 0; |
1501 | } | 1505 | } |
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 0a2d72f0024d..c65fb4f4230f 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h | |||
@@ -275,25 +275,27 @@ static inline nid_t get_nid(struct page *p, int off, bool i) | |||
275 | * - Mark cold node blocks in their node footer | 275 | * - Mark cold node blocks in their node footer |
276 | * - Mark cold data pages in page cache | 276 | * - Mark cold data pages in page cache |
277 | */ | 277 | */ |
278 | static inline int is_cold_file(struct inode *inode) | 278 | static inline int is_file(struct inode *inode, int type) |
279 | { | 279 | { |
280 | return F2FS_I(inode)->i_advise & FADVISE_COLD_BIT; | 280 | return F2FS_I(inode)->i_advise & type; |
281 | } | 281 | } |
282 | 282 | ||
283 | static inline void set_cold_file(struct inode *inode) | 283 | static inline void set_file(struct inode *inode, int type) |
284 | { | 284 | { |
285 | F2FS_I(inode)->i_advise |= FADVISE_COLD_BIT; | 285 | F2FS_I(inode)->i_advise |= type; |
286 | } | 286 | } |
287 | 287 | ||
288 | static inline int is_cp_file(struct inode *inode) | 288 | static inline void clear_file(struct inode *inode, int type) |
289 | { | 289 | { |
290 | return F2FS_I(inode)->i_advise & FADVISE_CP_BIT; | 290 | F2FS_I(inode)->i_advise &= ~type; |
291 | } | 291 | } |
292 | 292 | ||
293 | static inline void set_cp_file(struct inode *inode) | 293 | #define file_is_cold(inode) is_file(inode, FADVISE_COLD_BIT) |
294 | { | 294 | #define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT) |
295 | F2FS_I(inode)->i_advise |= FADVISE_CP_BIT; | 295 | #define file_set_cold(inode) set_file(inode, FADVISE_COLD_BIT) |
296 | } | 296 | #define file_lost_pino(inode) set_file(inode, FADVISE_LOST_PINO_BIT) |
297 | #define file_clear_cold(inode) clear_file(inode, FADVISE_COLD_BIT) | ||
298 | #define file_got_pino(inode) clear_file(inode, FADVISE_LOST_PINO_BIT) | ||
297 | 299 | ||
298 | static inline int is_cold_data(struct page *page) | 300 | static inline int is_cold_data(struct page *page) |
299 | { | 301 | { |
@@ -310,29 +312,16 @@ static inline void clear_cold_data(struct page *page) | |||
310 | ClearPageChecked(page); | 312 | ClearPageChecked(page); |
311 | } | 313 | } |
312 | 314 | ||
313 | static inline int is_cold_node(struct page *page) | 315 | static inline int is_node(struct page *page, int type) |
314 | { | 316 | { |
315 | void *kaddr = page_address(page); | 317 | void *kaddr = page_address(page); |
316 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | 318 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; |
317 | unsigned int flag = le32_to_cpu(rn->footer.flag); | 319 | return le32_to_cpu(rn->footer.flag) & (1 << type); |
318 | return flag & (0x1 << COLD_BIT_SHIFT); | ||
319 | } | 320 | } |
320 | 321 | ||
321 | static inline unsigned char is_fsync_dnode(struct page *page) | 322 | #define is_cold_node(page) is_node(page, COLD_BIT_SHIFT) |
322 | { | 323 | #define is_fsync_dnode(page) is_node(page, FSYNC_BIT_SHIFT) |
323 | void *kaddr = page_address(page); | 324 | #define is_dent_dnode(page) is_node(page, DENT_BIT_SHIFT) |
324 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
325 | unsigned int flag = le32_to_cpu(rn->footer.flag); | ||
326 | return flag & (0x1 << FSYNC_BIT_SHIFT); | ||
327 | } | ||
328 | |||
329 | static inline unsigned char is_dent_dnode(struct page *page) | ||
330 | { | ||
331 | void *kaddr = page_address(page); | ||
332 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
333 | unsigned int flag = le32_to_cpu(rn->footer.flag); | ||
334 | return flag & (0x1 << DENT_BIT_SHIFT); | ||
335 | } | ||
336 | 325 | ||
337 | static inline void set_cold_node(struct inode *inode, struct page *page) | 326 | static inline void set_cold_node(struct inode *inode, struct page *page) |
338 | { | 327 | { |
@@ -346,26 +335,15 @@ static inline void set_cold_node(struct inode *inode, struct page *page) | |||
346 | rn->footer.flag = cpu_to_le32(flag); | 335 | rn->footer.flag = cpu_to_le32(flag); |
347 | } | 336 | } |
348 | 337 | ||
349 | static inline void set_fsync_mark(struct page *page, int mark) | 338 | static inline void set_mark(struct page *page, int mark, int type) |
350 | { | 339 | { |
351 | void *kaddr = page_address(page); | 340 | struct f2fs_node *rn = (struct f2fs_node *)page_address(page); |
352 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
353 | unsigned int flag = le32_to_cpu(rn->footer.flag); | ||
354 | if (mark) | ||
355 | flag |= (0x1 << FSYNC_BIT_SHIFT); | ||
356 | else | ||
357 | flag &= ~(0x1 << FSYNC_BIT_SHIFT); | ||
358 | rn->footer.flag = cpu_to_le32(flag); | ||
359 | } | ||
360 | |||
361 | static inline void set_dentry_mark(struct page *page, int mark) | ||
362 | { | ||
363 | void *kaddr = page_address(page); | ||
364 | struct f2fs_node *rn = (struct f2fs_node *)kaddr; | ||
365 | unsigned int flag = le32_to_cpu(rn->footer.flag); | 341 | unsigned int flag = le32_to_cpu(rn->footer.flag); |
366 | if (mark) | 342 | if (mark) |
367 | flag |= (0x1 << DENT_BIT_SHIFT); | 343 | flag |= (0x1 << type); |
368 | else | 344 | else |
369 | flag &= ~(0x1 << DENT_BIT_SHIFT); | 345 | flag &= ~(0x1 << type); |
370 | rn->footer.flag = cpu_to_le32(flag); | 346 | rn->footer.flag = cpu_to_le32(flag); |
371 | } | 347 | } |
348 | #define set_dentry_mark(page, mark) set_mark(page, mark, DENT_BIT_SHIFT) | ||
349 | #define set_fsync_mark(page, mark) set_mark(page, mark, FSYNC_BIT_SHIFT) | ||
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 60c8a5097058..d56d951c2253 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -40,36 +40,54 @@ static struct fsync_inode_entry *get_fsync_inode(struct list_head *head, | |||
40 | 40 | ||
41 | static int recover_dentry(struct page *ipage, struct inode *inode) | 41 | static int recover_dentry(struct page *ipage, struct inode *inode) |
42 | { | 42 | { |
43 | struct f2fs_node *raw_node = (struct f2fs_node *)kmap(ipage); | 43 | void *kaddr = page_address(ipage); |
44 | struct f2fs_node *raw_node = (struct f2fs_node *)kaddr; | ||
44 | struct f2fs_inode *raw_inode = &(raw_node->i); | 45 | struct f2fs_inode *raw_inode = &(raw_node->i); |
45 | struct qstr name; | 46 | nid_t pino = le32_to_cpu(raw_inode->i_pino); |
46 | struct f2fs_dir_entry *de; | 47 | struct f2fs_dir_entry *de; |
48 | struct qstr name; | ||
47 | struct page *page; | 49 | struct page *page; |
48 | struct inode *dir; | 50 | struct inode *dir, *einode; |
49 | int err = 0; | 51 | int err = 0; |
50 | 52 | ||
51 | if (!is_dent_dnode(ipage)) | 53 | dir = check_dirty_dir_inode(F2FS_SB(inode->i_sb), pino); |
52 | goto out; | 54 | if (!dir) { |
53 | 55 | dir = f2fs_iget(inode->i_sb, pino); | |
54 | dir = f2fs_iget(inode->i_sb, le32_to_cpu(raw_inode->i_pino)); | 56 | if (IS_ERR(dir)) { |
55 | if (IS_ERR(dir)) { | 57 | err = PTR_ERR(dir); |
56 | err = PTR_ERR(dir); | 58 | goto out; |
57 | goto out; | 59 | } |
60 | set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT); | ||
61 | add_dirty_dir_inode(dir); | ||
58 | } | 62 | } |
59 | 63 | ||
60 | name.len = le32_to_cpu(raw_inode->i_namelen); | 64 | name.len = le32_to_cpu(raw_inode->i_namelen); |
61 | name.name = raw_inode->i_name; | 65 | name.name = raw_inode->i_name; |
62 | 66 | retry: | |
63 | de = f2fs_find_entry(dir, &name, &page); | 67 | de = f2fs_find_entry(dir, &name, &page); |
64 | if (de) { | 68 | if (de && inode->i_ino == le32_to_cpu(de->ino)) { |
65 | kunmap(page); | 69 | kunmap(page); |
66 | f2fs_put_page(page, 0); | 70 | f2fs_put_page(page, 0); |
67 | } else { | 71 | goto out; |
68 | err = __f2fs_add_link(dir, &name, inode); | 72 | } |
73 | if (de) { | ||
74 | einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); | ||
75 | if (IS_ERR(einode)) { | ||
76 | WARN_ON(1); | ||
77 | if (PTR_ERR(einode) == -ENOENT) | ||
78 | err = -EEXIST; | ||
79 | goto out; | ||
80 | } | ||
81 | f2fs_delete_entry(de, page, einode); | ||
82 | iput(einode); | ||
83 | goto retry; | ||
69 | } | 84 | } |
70 | iput(dir); | 85 | err = __f2fs_add_link(dir, &name, inode); |
71 | out: | 86 | out: |
72 | kunmap(ipage); | 87 | f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode and its dentry: " |
88 | "ino = %x, name = %s, dir = %lx, err = %d", | ||
89 | ino_of_node(ipage), raw_inode->i_name, | ||
90 | IS_ERR(dir) ? 0 : dir->i_ino, err); | ||
73 | return err; | 91 | return err; |
74 | } | 92 | } |
75 | 93 | ||
@@ -79,6 +97,9 @@ static int recover_inode(struct inode *inode, struct page *node_page) | |||
79 | struct f2fs_node *raw_node = (struct f2fs_node *)kaddr; | 97 | struct f2fs_node *raw_node = (struct f2fs_node *)kaddr; |
80 | struct f2fs_inode *raw_inode = &(raw_node->i); | 98 | struct f2fs_inode *raw_inode = &(raw_node->i); |
81 | 99 | ||
100 | if (!IS_INODE(node_page)) | ||
101 | return 0; | ||
102 | |||
82 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); | 103 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); |
83 | i_size_write(inode, le64_to_cpu(raw_inode->i_size)); | 104 | i_size_write(inode, le64_to_cpu(raw_inode->i_size)); |
84 | inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime); | 105 | inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime); |
@@ -88,7 +109,12 @@ static int recover_inode(struct inode *inode, struct page *node_page) | |||
88 | inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec); | 109 | inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec); |
89 | inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); | 110 | inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); |
90 | 111 | ||
91 | return recover_dentry(node_page, inode); | 112 | if (is_dent_dnode(node_page)) |
113 | return recover_dentry(node_page, inode); | ||
114 | |||
115 | f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode: ino = %x, name = %s", | ||
116 | ino_of_node(node_page), raw_inode->i_name); | ||
117 | return 0; | ||
92 | } | 118 | } |
93 | 119 | ||
94 | static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | 120 | static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) |
@@ -119,14 +145,13 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
119 | lock_page(page); | 145 | lock_page(page); |
120 | 146 | ||
121 | if (cp_ver != cpver_of_node(page)) | 147 | if (cp_ver != cpver_of_node(page)) |
122 | goto unlock_out; | 148 | break; |
123 | 149 | ||
124 | if (!is_fsync_dnode(page)) | 150 | if (!is_fsync_dnode(page)) |
125 | goto next; | 151 | goto next; |
126 | 152 | ||
127 | entry = get_fsync_inode(head, ino_of_node(page)); | 153 | entry = get_fsync_inode(head, ino_of_node(page)); |
128 | if (entry) { | 154 | if (entry) { |
129 | entry->blkaddr = blkaddr; | ||
130 | if (IS_INODE(page) && is_dent_dnode(page)) | 155 | if (IS_INODE(page) && is_dent_dnode(page)) |
131 | set_inode_flag(F2FS_I(entry->inode), | 156 | set_inode_flag(F2FS_I(entry->inode), |
132 | FI_INC_LINK); | 157 | FI_INC_LINK); |
@@ -134,48 +159,40 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
134 | if (IS_INODE(page) && is_dent_dnode(page)) { | 159 | if (IS_INODE(page) && is_dent_dnode(page)) { |
135 | err = recover_inode_page(sbi, page); | 160 | err = recover_inode_page(sbi, page); |
136 | if (err) | 161 | if (err) |
137 | goto unlock_out; | 162 | break; |
138 | } | 163 | } |
139 | 164 | ||
140 | /* add this fsync inode to the list */ | 165 | /* add this fsync inode to the list */ |
141 | entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS); | 166 | entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS); |
142 | if (!entry) { | 167 | if (!entry) { |
143 | err = -ENOMEM; | 168 | err = -ENOMEM; |
144 | goto unlock_out; | 169 | break; |
145 | } | 170 | } |
146 | 171 | ||
147 | entry->inode = f2fs_iget(sbi->sb, ino_of_node(page)); | 172 | entry->inode = f2fs_iget(sbi->sb, ino_of_node(page)); |
148 | if (IS_ERR(entry->inode)) { | 173 | if (IS_ERR(entry->inode)) { |
149 | err = PTR_ERR(entry->inode); | 174 | err = PTR_ERR(entry->inode); |
150 | kmem_cache_free(fsync_entry_slab, entry); | 175 | kmem_cache_free(fsync_entry_slab, entry); |
151 | goto unlock_out; | 176 | break; |
152 | } | 177 | } |
153 | |||
154 | list_add_tail(&entry->list, head); | 178 | list_add_tail(&entry->list, head); |
155 | entry->blkaddr = blkaddr; | ||
156 | } | ||
157 | if (IS_INODE(page)) { | ||
158 | err = recover_inode(entry->inode, page); | ||
159 | if (err == -ENOENT) { | ||
160 | goto next; | ||
161 | } else if (err) { | ||
162 | err = -EINVAL; | ||
163 | goto unlock_out; | ||
164 | } | ||
165 | } | 179 | } |
180 | entry->blkaddr = blkaddr; | ||
181 | |||
182 | err = recover_inode(entry->inode, page); | ||
183 | if (err && err != -ENOENT) | ||
184 | break; | ||
166 | next: | 185 | next: |
167 | /* check next segment */ | 186 | /* check next segment */ |
168 | blkaddr = next_blkaddr_of_node(page); | 187 | blkaddr = next_blkaddr_of_node(page); |
169 | } | 188 | } |
170 | unlock_out: | ||
171 | unlock_page(page); | 189 | unlock_page(page); |
172 | out: | 190 | out: |
173 | __free_pages(page, 0); | 191 | __free_pages(page, 0); |
174 | return err; | 192 | return err; |
175 | } | 193 | } |
176 | 194 | ||
177 | static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi, | 195 | static void destroy_fsync_dnodes(struct list_head *head) |
178 | struct list_head *head) | ||
179 | { | 196 | { |
180 | struct fsync_inode_entry *entry, *tmp; | 197 | struct fsync_inode_entry *entry, *tmp; |
181 | 198 | ||
@@ -186,15 +203,15 @@ static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi, | |||
186 | } | 203 | } |
187 | } | 204 | } |
188 | 205 | ||
189 | static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | 206 | static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, |
190 | block_t blkaddr) | 207 | block_t blkaddr, struct dnode_of_data *dn) |
191 | { | 208 | { |
192 | struct seg_entry *sentry; | 209 | struct seg_entry *sentry; |
193 | unsigned int segno = GET_SEGNO(sbi, blkaddr); | 210 | unsigned int segno = GET_SEGNO(sbi, blkaddr); |
194 | unsigned short blkoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & | 211 | unsigned short blkoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & |
195 | (sbi->blocks_per_seg - 1); | 212 | (sbi->blocks_per_seg - 1); |
196 | struct f2fs_summary sum; | 213 | struct f2fs_summary sum; |
197 | nid_t ino; | 214 | nid_t ino, nid; |
198 | void *kaddr; | 215 | void *kaddr; |
199 | struct inode *inode; | 216 | struct inode *inode; |
200 | struct page *node_page; | 217 | struct page *node_page; |
@@ -203,7 +220,7 @@ static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
203 | 220 | ||
204 | sentry = get_seg_entry(sbi, segno); | 221 | sentry = get_seg_entry(sbi, segno); |
205 | if (!f2fs_test_bit(blkoff, sentry->cur_valid_map)) | 222 | if (!f2fs_test_bit(blkoff, sentry->cur_valid_map)) |
206 | return; | 223 | return 0; |
207 | 224 | ||
208 | /* Get the previous summary */ | 225 | /* Get the previous summary */ |
209 | for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) { | 226 | for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) { |
@@ -222,20 +239,39 @@ static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi, | |||
222 | f2fs_put_page(sum_page, 1); | 239 | f2fs_put_page(sum_page, 1); |
223 | } | 240 | } |
224 | 241 | ||
242 | /* Use the locked dnode page and inode */ | ||
243 | nid = le32_to_cpu(sum.nid); | ||
244 | if (dn->inode->i_ino == nid) { | ||
245 | struct dnode_of_data tdn = *dn; | ||
246 | tdn.nid = nid; | ||
247 | tdn.node_page = dn->inode_page; | ||
248 | tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); | ||
249 | truncate_data_blocks_range(&tdn, 1); | ||
250 | return 0; | ||
251 | } else if (dn->nid == nid) { | ||
252 | struct dnode_of_data tdn = *dn; | ||
253 | tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); | ||
254 | truncate_data_blocks_range(&tdn, 1); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
225 | /* Get the node page */ | 258 | /* Get the node page */ |
226 | node_page = get_node_page(sbi, le32_to_cpu(sum.nid)); | 259 | node_page = get_node_page(sbi, nid); |
260 | if (IS_ERR(node_page)) | ||
261 | return PTR_ERR(node_page); | ||
227 | bidx = start_bidx_of_node(ofs_of_node(node_page)) + | 262 | bidx = start_bidx_of_node(ofs_of_node(node_page)) + |
228 | le16_to_cpu(sum.ofs_in_node); | 263 | le16_to_cpu(sum.ofs_in_node); |
229 | ino = ino_of_node(node_page); | 264 | ino = ino_of_node(node_page); |
230 | f2fs_put_page(node_page, 1); | 265 | f2fs_put_page(node_page, 1); |
231 | 266 | ||
232 | /* Deallocate previous index in the node page */ | 267 | /* Deallocate previous index in the node page */ |
233 | inode = f2fs_iget(sbi->sb, ino); | 268 | inode = f2fs_iget(sbi->sb, ino); |
234 | if (IS_ERR(inode)) | 269 | if (IS_ERR(inode)) |
235 | return; | 270 | return PTR_ERR(inode); |
236 | 271 | ||
237 | truncate_hole(inode, bidx, bidx + 1); | 272 | truncate_hole(inode, bidx, bidx + 1); |
238 | iput(inode); | 273 | iput(inode); |
274 | return 0; | ||
239 | } | 275 | } |
240 | 276 | ||
241 | static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | 277 | static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, |
@@ -245,7 +281,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
245 | struct dnode_of_data dn; | 281 | struct dnode_of_data dn; |
246 | struct f2fs_summary sum; | 282 | struct f2fs_summary sum; |
247 | struct node_info ni; | 283 | struct node_info ni; |
248 | int err = 0; | 284 | int err = 0, recovered = 0; |
249 | int ilock; | 285 | int ilock; |
250 | 286 | ||
251 | start = start_bidx_of_node(ofs_of_node(page)); | 287 | start = start_bidx_of_node(ofs_of_node(page)); |
@@ -283,13 +319,16 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
283 | } | 319 | } |
284 | 320 | ||
285 | /* Check the previous node page having this index */ | 321 | /* Check the previous node page having this index */ |
286 | check_index_in_prev_nodes(sbi, dest); | 322 | err = check_index_in_prev_nodes(sbi, dest, &dn); |
323 | if (err) | ||
324 | goto err; | ||
287 | 325 | ||
288 | set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version); | 326 | set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version); |
289 | 327 | ||
290 | /* write dummy data page */ | 328 | /* write dummy data page */ |
291 | recover_data_page(sbi, NULL, &sum, src, dest); | 329 | recover_data_page(sbi, NULL, &sum, src, dest); |
292 | update_extent_cache(dest, &dn); | 330 | update_extent_cache(dest, &dn); |
331 | recovered++; | ||
293 | } | 332 | } |
294 | dn.ofs_in_node++; | 333 | dn.ofs_in_node++; |
295 | } | 334 | } |
@@ -305,9 +344,14 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, | |||
305 | set_page_dirty(dn.node_page); | 344 | set_page_dirty(dn.node_page); |
306 | 345 | ||
307 | recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr); | 346 | recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr); |
347 | err: | ||
308 | f2fs_put_dnode(&dn); | 348 | f2fs_put_dnode(&dn); |
309 | mutex_unlock_op(sbi, ilock); | 349 | mutex_unlock_op(sbi, ilock); |
310 | return 0; | 350 | |
351 | f2fs_msg(sbi->sb, KERN_NOTICE, "recover_data: ino = %lx, " | ||
352 | "recovered_data = %d blocks, err = %d", | ||
353 | inode->i_ino, recovered, err); | ||
354 | return err; | ||
311 | } | 355 | } |
312 | 356 | ||
313 | static int recover_data(struct f2fs_sb_info *sbi, | 357 | static int recover_data(struct f2fs_sb_info *sbi, |
@@ -340,7 +384,7 @@ static int recover_data(struct f2fs_sb_info *sbi, | |||
340 | lock_page(page); | 384 | lock_page(page); |
341 | 385 | ||
342 | if (cp_ver != cpver_of_node(page)) | 386 | if (cp_ver != cpver_of_node(page)) |
343 | goto unlock_out; | 387 | break; |
344 | 388 | ||
345 | entry = get_fsync_inode(head, ino_of_node(page)); | 389 | entry = get_fsync_inode(head, ino_of_node(page)); |
346 | if (!entry) | 390 | if (!entry) |
@@ -348,7 +392,7 @@ static int recover_data(struct f2fs_sb_info *sbi, | |||
348 | 392 | ||
349 | err = do_recover_data(sbi, entry->inode, page, blkaddr); | 393 | err = do_recover_data(sbi, entry->inode, page, blkaddr); |
350 | if (err) | 394 | if (err) |
351 | goto out; | 395 | break; |
352 | 396 | ||
353 | if (entry->blkaddr == blkaddr) { | 397 | if (entry->blkaddr == blkaddr) { |
354 | iput(entry->inode); | 398 | iput(entry->inode); |
@@ -359,7 +403,6 @@ next: | |||
359 | /* check next segment */ | 403 | /* check next segment */ |
360 | blkaddr = next_blkaddr_of_node(page); | 404 | blkaddr = next_blkaddr_of_node(page); |
361 | } | 405 | } |
362 | unlock_out: | ||
363 | unlock_page(page); | 406 | unlock_page(page); |
364 | out: | 407 | out: |
365 | __free_pages(page, 0); | 408 | __free_pages(page, 0); |
@@ -382,6 +425,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) | |||
382 | INIT_LIST_HEAD(&inode_list); | 425 | INIT_LIST_HEAD(&inode_list); |
383 | 426 | ||
384 | /* step #1: find fsynced inode numbers */ | 427 | /* step #1: find fsynced inode numbers */ |
428 | sbi->por_doing = 1; | ||
385 | err = find_fsync_dnodes(sbi, &inode_list); | 429 | err = find_fsync_dnodes(sbi, &inode_list); |
386 | if (err) | 430 | if (err) |
387 | goto out; | 431 | goto out; |
@@ -390,13 +434,13 @@ int recover_fsync_data(struct f2fs_sb_info *sbi) | |||
390 | goto out; | 434 | goto out; |
391 | 435 | ||
392 | /* step #2: recover data */ | 436 | /* step #2: recover data */ |
393 | sbi->por_doing = 1; | ||
394 | err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE); | 437 | err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE); |
395 | sbi->por_doing = 0; | ||
396 | BUG_ON(!list_empty(&inode_list)); | 438 | BUG_ON(!list_empty(&inode_list)); |
397 | out: | 439 | out: |
398 | destroy_fsync_dnodes(sbi, &inode_list); | 440 | destroy_fsync_dnodes(&inode_list); |
399 | kmem_cache_destroy(fsync_entry_slab); | 441 | kmem_cache_destroy(fsync_entry_slab); |
400 | write_checkpoint(sbi, false); | 442 | sbi->por_doing = 0; |
443 | if (!err) | ||
444 | write_checkpoint(sbi, false); | ||
401 | return err; | 445 | return err; |
402 | } | 446 | } |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index d8e84e49a5c3..a86d125a9885 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -94,7 +94,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, | |||
94 | * Adding dirty entry into seglist is not critical operation. | 94 | * Adding dirty entry into seglist is not critical operation. |
95 | * If a given segment is one of current working segments, it won't be added. | 95 | * If a given segment is one of current working segments, it won't be added. |
96 | */ | 96 | */ |
97 | void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | 97 | static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) |
98 | { | 98 | { |
99 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 99 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
100 | unsigned short valid_blocks; | 100 | unsigned short valid_blocks; |
@@ -126,17 +126,16 @@ void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | |||
126 | static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) | 126 | static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) |
127 | { | 127 | { |
128 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 128 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
129 | unsigned int segno, offset = 0; | 129 | unsigned int segno = -1; |
130 | unsigned int total_segs = TOTAL_SEGS(sbi); | 130 | unsigned int total_segs = TOTAL_SEGS(sbi); |
131 | 131 | ||
132 | mutex_lock(&dirty_i->seglist_lock); | 132 | mutex_lock(&dirty_i->seglist_lock); |
133 | while (1) { | 133 | while (1) { |
134 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, | 134 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, |
135 | offset); | 135 | segno + 1); |
136 | if (segno >= total_segs) | 136 | if (segno >= total_segs) |
137 | break; | 137 | break; |
138 | __set_test_and_free(sbi, segno); | 138 | __set_test_and_free(sbi, segno); |
139 | offset = segno + 1; | ||
140 | } | 139 | } |
141 | mutex_unlock(&dirty_i->seglist_lock); | 140 | mutex_unlock(&dirty_i->seglist_lock); |
142 | } | 141 | } |
@@ -144,17 +143,16 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) | |||
144 | void clear_prefree_segments(struct f2fs_sb_info *sbi) | 143 | void clear_prefree_segments(struct f2fs_sb_info *sbi) |
145 | { | 144 | { |
146 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 145 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
147 | unsigned int segno, offset = 0; | 146 | unsigned int segno = -1; |
148 | unsigned int total_segs = TOTAL_SEGS(sbi); | 147 | unsigned int total_segs = TOTAL_SEGS(sbi); |
149 | 148 | ||
150 | mutex_lock(&dirty_i->seglist_lock); | 149 | mutex_lock(&dirty_i->seglist_lock); |
151 | while (1) { | 150 | while (1) { |
152 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, | 151 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, |
153 | offset); | 152 | segno + 1); |
154 | if (segno >= total_segs) | 153 | if (segno >= total_segs) |
155 | break; | 154 | break; |
156 | 155 | ||
157 | offset = segno + 1; | ||
158 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE])) | 156 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE])) |
159 | dirty_i->nr_dirty[PRE]--; | 157 | dirty_i->nr_dirty[PRE]--; |
160 | 158 | ||
@@ -257,11 +255,11 @@ void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr) | |||
257 | * This function should be resided under the curseg_mutex lock | 255 | * This function should be resided under the curseg_mutex lock |
258 | */ | 256 | */ |
259 | static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, | 257 | static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, |
260 | struct f2fs_summary *sum, unsigned short offset) | 258 | struct f2fs_summary *sum) |
261 | { | 259 | { |
262 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 260 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
263 | void *addr = curseg->sum_blk; | 261 | void *addr = curseg->sum_blk; |
264 | addr += offset * sizeof(struct f2fs_summary); | 262 | addr += curseg->next_blkoff * sizeof(struct f2fs_summary); |
265 | memcpy(addr, sum, sizeof(struct f2fs_summary)); | 263 | memcpy(addr, sum, sizeof(struct f2fs_summary)); |
266 | return; | 264 | return; |
267 | } | 265 | } |
@@ -311,64 +309,14 @@ static void write_sum_page(struct f2fs_sb_info *sbi, | |||
311 | f2fs_put_page(page, 1); | 309 | f2fs_put_page(page, 1); |
312 | } | 310 | } |
313 | 311 | ||
314 | static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi, int type) | ||
315 | { | ||
316 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | ||
317 | unsigned long *prefree_segmap = dirty_i->dirty_segmap[PRE]; | ||
318 | unsigned int segno; | ||
319 | unsigned int ofs = 0; | ||
320 | |||
321 | /* | ||
322 | * If there is not enough reserved sections, | ||
323 | * we should not reuse prefree segments. | ||
324 | */ | ||
325 | if (has_not_enough_free_secs(sbi, 0)) | ||
326 | return NULL_SEGNO; | ||
327 | |||
328 | /* | ||
329 | * NODE page should not reuse prefree segment, | ||
330 | * since those information is used for SPOR. | ||
331 | */ | ||
332 | if (IS_NODESEG(type)) | ||
333 | return NULL_SEGNO; | ||
334 | next: | ||
335 | segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs); | ||
336 | ofs += sbi->segs_per_sec; | ||
337 | |||
338 | if (segno < TOTAL_SEGS(sbi)) { | ||
339 | int i; | ||
340 | |||
341 | /* skip intermediate segments in a section */ | ||
342 | if (segno % sbi->segs_per_sec) | ||
343 | goto next; | ||
344 | |||
345 | /* skip if the section is currently used */ | ||
346 | if (sec_usage_check(sbi, GET_SECNO(sbi, segno))) | ||
347 | goto next; | ||
348 | |||
349 | /* skip if whole section is not prefree */ | ||
350 | for (i = 1; i < sbi->segs_per_sec; i++) | ||
351 | if (!test_bit(segno + i, prefree_segmap)) | ||
352 | goto next; | ||
353 | |||
354 | /* skip if whole section was not free at the last checkpoint */ | ||
355 | for (i = 0; i < sbi->segs_per_sec; i++) | ||
356 | if (get_seg_entry(sbi, segno + i)->ckpt_valid_blocks) | ||
357 | goto next; | ||
358 | |||
359 | return segno; | ||
360 | } | ||
361 | return NULL_SEGNO; | ||
362 | } | ||
363 | |||
364 | static int is_next_segment_free(struct f2fs_sb_info *sbi, int type) | 312 | static int is_next_segment_free(struct f2fs_sb_info *sbi, int type) |
365 | { | 313 | { |
366 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 314 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
367 | unsigned int segno = curseg->segno; | 315 | unsigned int segno = curseg->segno + 1; |
368 | struct free_segmap_info *free_i = FREE_I(sbi); | 316 | struct free_segmap_info *free_i = FREE_I(sbi); |
369 | 317 | ||
370 | if (segno + 1 < TOTAL_SEGS(sbi) && (segno + 1) % sbi->segs_per_sec) | 318 | if (segno < TOTAL_SEGS(sbi) && segno % sbi->segs_per_sec) |
371 | return !test_bit(segno + 1, free_i->free_segmap); | 319 | return !test_bit(segno, free_i->free_segmap); |
372 | return 0; | 320 | return 0; |
373 | } | 321 | } |
374 | 322 | ||
@@ -495,7 +443,7 @@ static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec) | |||
495 | int dir = ALLOC_LEFT; | 443 | int dir = ALLOC_LEFT; |
496 | 444 | ||
497 | write_sum_page(sbi, curseg->sum_blk, | 445 | write_sum_page(sbi, curseg->sum_blk, |
498 | GET_SUM_BLOCK(sbi, curseg->segno)); | 446 | GET_SUM_BLOCK(sbi, segno)); |
499 | if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA) | 447 | if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA) |
500 | dir = ALLOC_RIGHT; | 448 | dir = ALLOC_RIGHT; |
501 | 449 | ||
@@ -599,11 +547,7 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi, | |||
599 | goto out; | 547 | goto out; |
600 | } | 548 | } |
601 | 549 | ||
602 | curseg->next_segno = check_prefree_segments(sbi, type); | 550 | if (type == CURSEG_WARM_NODE) |
603 | |||
604 | if (curseg->next_segno != NULL_SEGNO) | ||
605 | change_curseg(sbi, type, false); | ||
606 | else if (type == CURSEG_WARM_NODE) | ||
607 | new_curseg(sbi, type, false); | 551 | new_curseg(sbi, type, false); |
608 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) | 552 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) |
609 | new_curseg(sbi, type, false); | 553 | new_curseg(sbi, type, false); |
@@ -612,7 +556,10 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi, | |||
612 | else | 556 | else |
613 | new_curseg(sbi, type, false); | 557 | new_curseg(sbi, type, false); |
614 | out: | 558 | out: |
559 | #ifdef CONFIG_F2FS_STAT_FS | ||
615 | sbi->segment_count[curseg->alloc_type]++; | 560 | sbi->segment_count[curseg->alloc_type]++; |
561 | #endif | ||
562 | return; | ||
616 | } | 563 | } |
617 | 564 | ||
618 | void allocate_new_segments(struct f2fs_sb_info *sbi) | 565 | void allocate_new_segments(struct f2fs_sb_info *sbi) |
@@ -795,7 +742,7 @@ static int __get_segment_type_6(struct page *page, enum page_type p_type) | |||
795 | 742 | ||
796 | if (S_ISDIR(inode->i_mode)) | 743 | if (S_ISDIR(inode->i_mode)) |
797 | return CURSEG_HOT_DATA; | 744 | return CURSEG_HOT_DATA; |
798 | else if (is_cold_data(page) || is_cold_file(inode)) | 745 | else if (is_cold_data(page) || file_is_cold(inode)) |
799 | return CURSEG_COLD_DATA; | 746 | return CURSEG_COLD_DATA; |
800 | else | 747 | else |
801 | return CURSEG_WARM_DATA; | 748 | return CURSEG_WARM_DATA; |
@@ -844,11 +791,13 @@ static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, | |||
844 | * because, this function updates a summary entry in the | 791 | * because, this function updates a summary entry in the |
845 | * current summary block. | 792 | * current summary block. |
846 | */ | 793 | */ |
847 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); | 794 | __add_sum_entry(sbi, type, sum); |
848 | 795 | ||
849 | mutex_lock(&sit_i->sentry_lock); | 796 | mutex_lock(&sit_i->sentry_lock); |
850 | __refresh_next_blkoff(sbi, curseg); | 797 | __refresh_next_blkoff(sbi, curseg); |
798 | #ifdef CONFIG_F2FS_STAT_FS | ||
851 | sbi->block_count[curseg->alloc_type]++; | 799 | sbi->block_count[curseg->alloc_type]++; |
800 | #endif | ||
852 | 801 | ||
853 | /* | 802 | /* |
854 | * SIT information should be updated before segment allocation, | 803 | * SIT information should be updated before segment allocation, |
@@ -943,7 +892,7 @@ void recover_data_page(struct f2fs_sb_info *sbi, | |||
943 | 892 | ||
944 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) & | 893 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) & |
945 | (sbi->blocks_per_seg - 1); | 894 | (sbi->blocks_per_seg - 1); |
946 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); | 895 | __add_sum_entry(sbi, type, sum); |
947 | 896 | ||
948 | refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); | 897 | refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); |
949 | 898 | ||
@@ -980,7 +929,7 @@ void rewrite_node_page(struct f2fs_sb_info *sbi, | |||
980 | } | 929 | } |
981 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) & | 930 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) & |
982 | (sbi->blocks_per_seg - 1); | 931 | (sbi->blocks_per_seg - 1); |
983 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); | 932 | __add_sum_entry(sbi, type, sum); |
984 | 933 | ||
985 | /* change the current log to the next block addr in advance */ | 934 | /* change the current log to the next block addr in advance */ |
986 | if (next_segno != segno) { | 935 | if (next_segno != segno) { |
@@ -1579,13 +1528,13 @@ static void init_dirty_segmap(struct f2fs_sb_info *sbi) | |||
1579 | { | 1528 | { |
1580 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 1529 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
1581 | struct free_segmap_info *free_i = FREE_I(sbi); | 1530 | struct free_segmap_info *free_i = FREE_I(sbi); |
1582 | unsigned int segno = 0, offset = 0; | 1531 | unsigned int segno = 0, offset = 0, total_segs = TOTAL_SEGS(sbi); |
1583 | unsigned short valid_blocks; | 1532 | unsigned short valid_blocks; |
1584 | 1533 | ||
1585 | while (segno < TOTAL_SEGS(sbi)) { | 1534 | while (1) { |
1586 | /* find dirty segment based on free segmap */ | 1535 | /* find dirty segment based on free segmap */ |
1587 | segno = find_next_inuse(free_i, TOTAL_SEGS(sbi), offset); | 1536 | segno = find_next_inuse(free_i, total_segs, offset); |
1588 | if (segno >= TOTAL_SEGS(sbi)) | 1537 | if (segno >= total_segs) |
1589 | break; | 1538 | break; |
1590 | offset = segno + 1; | 1539 | offset = segno + 1; |
1591 | valid_blocks = get_valid_blocks(sbi, segno, 0); | 1540 | valid_blocks = get_valid_blocks(sbi, segno, 0); |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 8555f7df82c7..75c7dc363e92 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -34,7 +34,7 @@ | |||
34 | static struct kmem_cache *f2fs_inode_cachep; | 34 | static struct kmem_cache *f2fs_inode_cachep; |
35 | 35 | ||
36 | enum { | 36 | enum { |
37 | Opt_gc_background_off, | 37 | Opt_gc_background, |
38 | Opt_disable_roll_forward, | 38 | Opt_disable_roll_forward, |
39 | Opt_discard, | 39 | Opt_discard, |
40 | Opt_noheap, | 40 | Opt_noheap, |
@@ -46,7 +46,7 @@ enum { | |||
46 | }; | 46 | }; |
47 | 47 | ||
48 | static match_table_t f2fs_tokens = { | 48 | static match_table_t f2fs_tokens = { |
49 | {Opt_gc_background_off, "background_gc_off"}, | 49 | {Opt_gc_background, "background_gc=%s"}, |
50 | {Opt_disable_roll_forward, "disable_roll_forward"}, | 50 | {Opt_disable_roll_forward, "disable_roll_forward"}, |
51 | {Opt_discard, "discard"}, | 51 | {Opt_discard, "discard"}, |
52 | {Opt_noheap, "no_heap"}, | 52 | {Opt_noheap, "no_heap"}, |
@@ -76,6 +76,91 @@ static void init_once(void *foo) | |||
76 | inode_init_once(&fi->vfs_inode); | 76 | inode_init_once(&fi->vfs_inode); |
77 | } | 77 | } |
78 | 78 | ||
79 | static int parse_options(struct super_block *sb, char *options) | ||
80 | { | ||
81 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
82 | substring_t args[MAX_OPT_ARGS]; | ||
83 | char *p, *name; | ||
84 | int arg = 0; | ||
85 | |||
86 | if (!options) | ||
87 | return 0; | ||
88 | |||
89 | while ((p = strsep(&options, ",")) != NULL) { | ||
90 | int token; | ||
91 | if (!*p) | ||
92 | continue; | ||
93 | /* | ||
94 | * Initialize args struct so we know whether arg was | ||
95 | * found; some options take optional arguments. | ||
96 | */ | ||
97 | args[0].to = args[0].from = NULL; | ||
98 | token = match_token(p, f2fs_tokens, args); | ||
99 | |||
100 | switch (token) { | ||
101 | case Opt_gc_background: | ||
102 | name = match_strdup(&args[0]); | ||
103 | |||
104 | if (!name) | ||
105 | return -ENOMEM; | ||
106 | if (!strncmp(name, "on", 2)) | ||
107 | set_opt(sbi, BG_GC); | ||
108 | else if (!strncmp(name, "off", 3)) | ||
109 | clear_opt(sbi, BG_GC); | ||
110 | else { | ||
111 | kfree(name); | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | kfree(name); | ||
115 | break; | ||
116 | case Opt_disable_roll_forward: | ||
117 | set_opt(sbi, DISABLE_ROLL_FORWARD); | ||
118 | break; | ||
119 | case Opt_discard: | ||
120 | set_opt(sbi, DISCARD); | ||
121 | break; | ||
122 | case Opt_noheap: | ||
123 | set_opt(sbi, NOHEAP); | ||
124 | break; | ||
125 | #ifdef CONFIG_F2FS_FS_XATTR | ||
126 | case Opt_nouser_xattr: | ||
127 | clear_opt(sbi, XATTR_USER); | ||
128 | break; | ||
129 | #else | ||
130 | case Opt_nouser_xattr: | ||
131 | f2fs_msg(sb, KERN_INFO, | ||
132 | "nouser_xattr options not supported"); | ||
133 | break; | ||
134 | #endif | ||
135 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | ||
136 | case Opt_noacl: | ||
137 | clear_opt(sbi, POSIX_ACL); | ||
138 | break; | ||
139 | #else | ||
140 | case Opt_noacl: | ||
141 | f2fs_msg(sb, KERN_INFO, "noacl options not supported"); | ||
142 | break; | ||
143 | #endif | ||
144 | case Opt_active_logs: | ||
145 | if (args->from && match_int(args, &arg)) | ||
146 | return -EINVAL; | ||
147 | if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE) | ||
148 | return -EINVAL; | ||
149 | sbi->active_logs = arg; | ||
150 | break; | ||
151 | case Opt_disable_ext_identify: | ||
152 | set_opt(sbi, DISABLE_EXT_IDENTIFY); | ||
153 | break; | ||
154 | default: | ||
155 | f2fs_msg(sb, KERN_ERR, | ||
156 | "Unrecognized mount option \"%s\" or missing value", | ||
157 | p); | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | } | ||
161 | return 0; | ||
162 | } | ||
163 | |||
79 | static struct inode *f2fs_alloc_inode(struct super_block *sb) | 164 | static struct inode *f2fs_alloc_inode(struct super_block *sb) |
80 | { | 165 | { |
81 | struct f2fs_inode_info *fi; | 166 | struct f2fs_inode_info *fi; |
@@ -112,6 +197,17 @@ static int f2fs_drop_inode(struct inode *inode) | |||
112 | return generic_drop_inode(inode); | 197 | return generic_drop_inode(inode); |
113 | } | 198 | } |
114 | 199 | ||
200 | /* | ||
201 | * f2fs_dirty_inode() is called from __mark_inode_dirty() | ||
202 | * | ||
203 | * We should call set_dirty_inode to write the dirty inode through write_inode. | ||
204 | */ | ||
205 | static void f2fs_dirty_inode(struct inode *inode, int flags) | ||
206 | { | ||
207 | set_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); | ||
208 | return; | ||
209 | } | ||
210 | |||
115 | static void f2fs_i_callback(struct rcu_head *head) | 211 | static void f2fs_i_callback(struct rcu_head *head) |
116 | { | 212 | { |
117 | struct inode *inode = container_of(head, struct inode, i_rcu); | 213 | struct inode *inode = container_of(head, struct inode, i_rcu); |
@@ -170,7 +266,7 @@ static int f2fs_freeze(struct super_block *sb) | |||
170 | { | 266 | { |
171 | int err; | 267 | int err; |
172 | 268 | ||
173 | if (sb->s_flags & MS_RDONLY) | 269 | if (f2fs_readonly(sb)) |
174 | return 0; | 270 | return 0; |
175 | 271 | ||
176 | err = f2fs_sync_fs(sb, 1); | 272 | err = f2fs_sync_fs(sb, 1); |
@@ -214,10 +310,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) | |||
214 | { | 310 | { |
215 | struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb); | 311 | struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb); |
216 | 312 | ||
217 | if (test_opt(sbi, BG_GC)) | 313 | if (!(root->d_sb->s_flags & MS_RDONLY) && test_opt(sbi, BG_GC)) |
218 | seq_puts(seq, ",background_gc_on"); | 314 | seq_printf(seq, ",background_gc=%s", "on"); |
219 | else | 315 | else |
220 | seq_puts(seq, ",background_gc_off"); | 316 | seq_printf(seq, ",background_gc=%s", "off"); |
221 | if (test_opt(sbi, DISABLE_ROLL_FORWARD)) | 317 | if (test_opt(sbi, DISABLE_ROLL_FORWARD)) |
222 | seq_puts(seq, ",disable_roll_forward"); | 318 | seq_puts(seq, ",disable_roll_forward"); |
223 | if (test_opt(sbi, DISCARD)) | 319 | if (test_opt(sbi, DISCARD)) |
@@ -244,11 +340,64 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) | |||
244 | return 0; | 340 | return 0; |
245 | } | 341 | } |
246 | 342 | ||
343 | static int f2fs_remount(struct super_block *sb, int *flags, char *data) | ||
344 | { | ||
345 | struct f2fs_sb_info *sbi = F2FS_SB(sb); | ||
346 | struct f2fs_mount_info org_mount_opt; | ||
347 | int err, active_logs; | ||
348 | |||
349 | /* | ||
350 | * Save the old mount options in case we | ||
351 | * need to restore them. | ||
352 | */ | ||
353 | org_mount_opt = sbi->mount_opt; | ||
354 | active_logs = sbi->active_logs; | ||
355 | |||
356 | /* parse mount options */ | ||
357 | err = parse_options(sb, data); | ||
358 | if (err) | ||
359 | goto restore_opts; | ||
360 | |||
361 | /* | ||
362 | * Previous and new state of filesystem is RO, | ||
363 | * so no point in checking GC conditions. | ||
364 | */ | ||
365 | if ((sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) | ||
366 | goto skip; | ||
367 | |||
368 | /* | ||
369 | * We stop the GC thread if FS is mounted as RO | ||
370 | * or if background_gc = off is passed in mount | ||
371 | * option. Also sync the filesystem. | ||
372 | */ | ||
373 | if ((*flags & MS_RDONLY) || !test_opt(sbi, BG_GC)) { | ||
374 | if (sbi->gc_thread) { | ||
375 | stop_gc_thread(sbi); | ||
376 | f2fs_sync_fs(sb, 1); | ||
377 | } | ||
378 | } else if (test_opt(sbi, BG_GC) && !sbi->gc_thread) { | ||
379 | err = start_gc_thread(sbi); | ||
380 | if (err) | ||
381 | goto restore_opts; | ||
382 | } | ||
383 | skip: | ||
384 | /* Update the POSIXACL Flag */ | ||
385 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | | ||
386 | (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); | ||
387 | return 0; | ||
388 | |||
389 | restore_opts: | ||
390 | sbi->mount_opt = org_mount_opt; | ||
391 | sbi->active_logs = active_logs; | ||
392 | return err; | ||
393 | } | ||
394 | |||
247 | static struct super_operations f2fs_sops = { | 395 | static struct super_operations f2fs_sops = { |
248 | .alloc_inode = f2fs_alloc_inode, | 396 | .alloc_inode = f2fs_alloc_inode, |
249 | .drop_inode = f2fs_drop_inode, | 397 | .drop_inode = f2fs_drop_inode, |
250 | .destroy_inode = f2fs_destroy_inode, | 398 | .destroy_inode = f2fs_destroy_inode, |
251 | .write_inode = f2fs_write_inode, | 399 | .write_inode = f2fs_write_inode, |
400 | .dirty_inode = f2fs_dirty_inode, | ||
252 | .show_options = f2fs_show_options, | 401 | .show_options = f2fs_show_options, |
253 | .evict_inode = f2fs_evict_inode, | 402 | .evict_inode = f2fs_evict_inode, |
254 | .put_super = f2fs_put_super, | 403 | .put_super = f2fs_put_super, |
@@ -256,6 +405,7 @@ static struct super_operations f2fs_sops = { | |||
256 | .freeze_fs = f2fs_freeze, | 405 | .freeze_fs = f2fs_freeze, |
257 | .unfreeze_fs = f2fs_unfreeze, | 406 | .unfreeze_fs = f2fs_unfreeze, |
258 | .statfs = f2fs_statfs, | 407 | .statfs = f2fs_statfs, |
408 | .remount_fs = f2fs_remount, | ||
259 | }; | 409 | }; |
260 | 410 | ||
261 | static struct inode *f2fs_nfs_get_inode(struct super_block *sb, | 411 | static struct inode *f2fs_nfs_get_inode(struct super_block *sb, |
@@ -303,79 +453,6 @@ static const struct export_operations f2fs_export_ops = { | |||
303 | .get_parent = f2fs_get_parent, | 453 | .get_parent = f2fs_get_parent, |
304 | }; | 454 | }; |
305 | 455 | ||
306 | static int parse_options(struct super_block *sb, struct f2fs_sb_info *sbi, | ||
307 | char *options) | ||
308 | { | ||
309 | substring_t args[MAX_OPT_ARGS]; | ||
310 | char *p; | ||
311 | int arg = 0; | ||
312 | |||
313 | if (!options) | ||
314 | return 0; | ||
315 | |||
316 | while ((p = strsep(&options, ",")) != NULL) { | ||
317 | int token; | ||
318 | if (!*p) | ||
319 | continue; | ||
320 | /* | ||
321 | * Initialize args struct so we know whether arg was | ||
322 | * found; some options take optional arguments. | ||
323 | */ | ||
324 | args[0].to = args[0].from = NULL; | ||
325 | token = match_token(p, f2fs_tokens, args); | ||
326 | |||
327 | switch (token) { | ||
328 | case Opt_gc_background_off: | ||
329 | clear_opt(sbi, BG_GC); | ||
330 | break; | ||
331 | case Opt_disable_roll_forward: | ||
332 | set_opt(sbi, DISABLE_ROLL_FORWARD); | ||
333 | break; | ||
334 | case Opt_discard: | ||
335 | set_opt(sbi, DISCARD); | ||
336 | break; | ||
337 | case Opt_noheap: | ||
338 | set_opt(sbi, NOHEAP); | ||
339 | break; | ||
340 | #ifdef CONFIG_F2FS_FS_XATTR | ||
341 | case Opt_nouser_xattr: | ||
342 | clear_opt(sbi, XATTR_USER); | ||
343 | break; | ||
344 | #else | ||
345 | case Opt_nouser_xattr: | ||
346 | f2fs_msg(sb, KERN_INFO, | ||
347 | "nouser_xattr options not supported"); | ||
348 | break; | ||
349 | #endif | ||
350 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | ||
351 | case Opt_noacl: | ||
352 | clear_opt(sbi, POSIX_ACL); | ||
353 | break; | ||
354 | #else | ||
355 | case Opt_noacl: | ||
356 | f2fs_msg(sb, KERN_INFO, "noacl options not supported"); | ||
357 | break; | ||
358 | #endif | ||
359 | case Opt_active_logs: | ||
360 | if (args->from && match_int(args, &arg)) | ||
361 | return -EINVAL; | ||
362 | if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE) | ||
363 | return -EINVAL; | ||
364 | sbi->active_logs = arg; | ||
365 | break; | ||
366 | case Opt_disable_ext_identify: | ||
367 | set_opt(sbi, DISABLE_EXT_IDENTIFY); | ||
368 | break; | ||
369 | default: | ||
370 | f2fs_msg(sb, KERN_ERR, | ||
371 | "Unrecognized mount option \"%s\" or missing value", | ||
372 | p); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | } | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static loff_t max_file_size(unsigned bits) | 456 | static loff_t max_file_size(unsigned bits) |
380 | { | 457 | { |
381 | loff_t result = ADDRS_PER_INODE; | 458 | loff_t result = ADDRS_PER_INODE; |
@@ -541,6 +618,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
541 | if (err) | 618 | if (err) |
542 | goto free_sb_buf; | 619 | goto free_sb_buf; |
543 | } | 620 | } |
621 | sb->s_fs_info = sbi; | ||
544 | /* init some FS parameters */ | 622 | /* init some FS parameters */ |
545 | sbi->active_logs = NR_CURSEG_TYPE; | 623 | sbi->active_logs = NR_CURSEG_TYPE; |
546 | 624 | ||
@@ -553,7 +631,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
553 | set_opt(sbi, POSIX_ACL); | 631 | set_opt(sbi, POSIX_ACL); |
554 | #endif | 632 | #endif |
555 | /* parse mount options */ | 633 | /* parse mount options */ |
556 | err = parse_options(sb, sbi, (char *)data); | 634 | err = parse_options(sb, (char *)data); |
557 | if (err) | 635 | if (err) |
558 | goto free_sb_buf; | 636 | goto free_sb_buf; |
559 | 637 | ||
@@ -565,7 +643,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
565 | sb->s_xattr = f2fs_xattr_handlers; | 643 | sb->s_xattr = f2fs_xattr_handlers; |
566 | sb->s_export_op = &f2fs_export_ops; | 644 | sb->s_export_op = &f2fs_export_ops; |
567 | sb->s_magic = F2FS_SUPER_MAGIC; | 645 | sb->s_magic = F2FS_SUPER_MAGIC; |
568 | sb->s_fs_info = sbi; | ||
569 | sb->s_time_gran = 1; | 646 | sb->s_time_gran = 1; |
570 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | | 647 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | |
571 | (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); | 648 | (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); |
@@ -674,10 +751,16 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
674 | "Cannot recover all fsync data errno=%ld", err); | 751 | "Cannot recover all fsync data errno=%ld", err); |
675 | } | 752 | } |
676 | 753 | ||
677 | /* After POR, we can run background GC thread */ | 754 | /* |
678 | err = start_gc_thread(sbi); | 755 | * If filesystem is not mounted as read-only then |
679 | if (err) | 756 | * do start the gc_thread. |
680 | goto fail; | 757 | */ |
758 | if (!(sb->s_flags & MS_RDONLY)) { | ||
759 | /* After POR, we can run background GC thread.*/ | ||
760 | err = start_gc_thread(sbi); | ||
761 | if (err) | ||
762 | goto fail; | ||
763 | } | ||
681 | 764 | ||
682 | err = f2fs_build_stats(sbi); | 765 | err = f2fs_build_stats(sbi); |
683 | if (err) | 766 | if (err) |
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 0b02dce31356..3ab07ecd86ca 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/rwsem.h> | 21 | #include <linux/rwsem.h> |
22 | #include <linux/f2fs_fs.h> | 22 | #include <linux/f2fs_fs.h> |
23 | #include <linux/security.h> | ||
23 | #include "f2fs.h" | 24 | #include "f2fs.h" |
24 | #include "xattr.h" | 25 | #include "xattr.h" |
25 | 26 | ||
@@ -43,6 +44,10 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list, | |||
43 | prefix = XATTR_TRUSTED_PREFIX; | 44 | prefix = XATTR_TRUSTED_PREFIX; |
44 | prefix_len = XATTR_TRUSTED_PREFIX_LEN; | 45 | prefix_len = XATTR_TRUSTED_PREFIX_LEN; |
45 | break; | 46 | break; |
47 | case F2FS_XATTR_INDEX_SECURITY: | ||
48 | prefix = XATTR_SECURITY_PREFIX; | ||
49 | prefix_len = XATTR_SECURITY_PREFIX_LEN; | ||
50 | break; | ||
46 | default: | 51 | default: |
47 | return -EINVAL; | 52 | return -EINVAL; |
48 | } | 53 | } |
@@ -50,7 +55,7 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list, | |||
50 | total_len = prefix_len + name_len + 1; | 55 | total_len = prefix_len + name_len + 1; |
51 | if (list && total_len <= list_size) { | 56 | if (list && total_len <= list_size) { |
52 | memcpy(list, prefix, prefix_len); | 57 | memcpy(list, prefix, prefix_len); |
53 | memcpy(list+prefix_len, name, name_len); | 58 | memcpy(list + prefix_len, name, name_len); |
54 | list[prefix_len + name_len] = '\0'; | 59 | list[prefix_len + name_len] = '\0'; |
55 | } | 60 | } |
56 | return total_len; | 61 | return total_len; |
@@ -70,13 +75,14 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name, | |||
70 | if (!capable(CAP_SYS_ADMIN)) | 75 | if (!capable(CAP_SYS_ADMIN)) |
71 | return -EPERM; | 76 | return -EPERM; |
72 | break; | 77 | break; |
78 | case F2FS_XATTR_INDEX_SECURITY: | ||
79 | break; | ||
73 | default: | 80 | default: |
74 | return -EINVAL; | 81 | return -EINVAL; |
75 | } | 82 | } |
76 | if (strcmp(name, "") == 0) | 83 | if (strcmp(name, "") == 0) |
77 | return -EINVAL; | 84 | return -EINVAL; |
78 | return f2fs_getxattr(dentry->d_inode, type, name, | 85 | return f2fs_getxattr(dentry->d_inode, type, name, buffer, size); |
79 | buffer, size); | ||
80 | } | 86 | } |
81 | 87 | ||
82 | static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, | 88 | static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, |
@@ -93,13 +99,15 @@ static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, | |||
93 | if (!capable(CAP_SYS_ADMIN)) | 99 | if (!capable(CAP_SYS_ADMIN)) |
94 | return -EPERM; | 100 | return -EPERM; |
95 | break; | 101 | break; |
102 | case F2FS_XATTR_INDEX_SECURITY: | ||
103 | break; | ||
96 | default: | 104 | default: |
97 | return -EINVAL; | 105 | return -EINVAL; |
98 | } | 106 | } |
99 | if (strcmp(name, "") == 0) | 107 | if (strcmp(name, "") == 0) |
100 | return -EINVAL; | 108 | return -EINVAL; |
101 | 109 | ||
102 | return f2fs_setxattr(dentry->d_inode, type, name, value, size); | 110 | return f2fs_setxattr(dentry->d_inode, type, name, value, size, NULL); |
103 | } | 111 | } |
104 | 112 | ||
105 | static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list, | 113 | static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list, |
@@ -145,6 +153,31 @@ static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name, | |||
145 | return 0; | 153 | return 0; |
146 | } | 154 | } |
147 | 155 | ||
156 | #ifdef CONFIG_F2FS_FS_SECURITY | ||
157 | static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, | ||
158 | void *page) | ||
159 | { | ||
160 | const struct xattr *xattr; | ||
161 | int err = 0; | ||
162 | |||
163 | for (xattr = xattr_array; xattr->name != NULL; xattr++) { | ||
164 | err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY, | ||
165 | xattr->name, xattr->value, | ||
166 | xattr->value_len, (struct page *)page); | ||
167 | if (err < 0) | ||
168 | break; | ||
169 | } | ||
170 | return err; | ||
171 | } | ||
172 | |||
173 | int f2fs_init_security(struct inode *inode, struct inode *dir, | ||
174 | const struct qstr *qstr, struct page *ipage) | ||
175 | { | ||
176 | return security_inode_init_security(inode, dir, qstr, | ||
177 | &f2fs_initxattrs, ipage); | ||
178 | } | ||
179 | #endif | ||
180 | |||
148 | const struct xattr_handler f2fs_xattr_user_handler = { | 181 | const struct xattr_handler f2fs_xattr_user_handler = { |
149 | .prefix = XATTR_USER_PREFIX, | 182 | .prefix = XATTR_USER_PREFIX, |
150 | .flags = F2FS_XATTR_INDEX_USER, | 183 | .flags = F2FS_XATTR_INDEX_USER, |
@@ -169,6 +202,14 @@ const struct xattr_handler f2fs_xattr_advise_handler = { | |||
169 | .set = f2fs_xattr_advise_set, | 202 | .set = f2fs_xattr_advise_set, |
170 | }; | 203 | }; |
171 | 204 | ||
205 | const struct xattr_handler f2fs_xattr_security_handler = { | ||
206 | .prefix = XATTR_SECURITY_PREFIX, | ||
207 | .flags = F2FS_XATTR_INDEX_SECURITY, | ||
208 | .list = f2fs_xattr_generic_list, | ||
209 | .get = f2fs_xattr_generic_get, | ||
210 | .set = f2fs_xattr_generic_set, | ||
211 | }; | ||
212 | |||
172 | static const struct xattr_handler *f2fs_xattr_handler_map[] = { | 213 | static const struct xattr_handler *f2fs_xattr_handler_map[] = { |
173 | [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler, | 214 | [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler, |
174 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | 215 | #ifdef CONFIG_F2FS_FS_POSIX_ACL |
@@ -176,6 +217,9 @@ static const struct xattr_handler *f2fs_xattr_handler_map[] = { | |||
176 | [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler, | 217 | [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler, |
177 | #endif | 218 | #endif |
178 | [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler, | 219 | [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler, |
220 | #ifdef CONFIG_F2FS_FS_SECURITY | ||
221 | [F2FS_XATTR_INDEX_SECURITY] = &f2fs_xattr_security_handler, | ||
222 | #endif | ||
179 | [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler, | 223 | [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler, |
180 | }; | 224 | }; |
181 | 225 | ||
@@ -186,6 +230,9 @@ const struct xattr_handler *f2fs_xattr_handlers[] = { | |||
186 | &f2fs_xattr_acl_default_handler, | 230 | &f2fs_xattr_acl_default_handler, |
187 | #endif | 231 | #endif |
188 | &f2fs_xattr_trusted_handler, | 232 | &f2fs_xattr_trusted_handler, |
233 | #ifdef CONFIG_F2FS_FS_SECURITY | ||
234 | &f2fs_xattr_security_handler, | ||
235 | #endif | ||
189 | &f2fs_xattr_advise_handler, | 236 | &f2fs_xattr_advise_handler, |
190 | NULL, | 237 | NULL, |
191 | }; | 238 | }; |
@@ -218,6 +265,8 @@ int f2fs_getxattr(struct inode *inode, int name_index, const char *name, | |||
218 | return -ENODATA; | 265 | return -ENODATA; |
219 | 266 | ||
220 | page = get_node_page(sbi, fi->i_xattr_nid); | 267 | page = get_node_page(sbi, fi->i_xattr_nid); |
268 | if (IS_ERR(page)) | ||
269 | return PTR_ERR(page); | ||
221 | base_addr = page_address(page); | 270 | base_addr = page_address(page); |
222 | 271 | ||
223 | list_for_each_xattr(entry, base_addr) { | 272 | list_for_each_xattr(entry, base_addr) { |
@@ -268,6 +317,8 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
268 | return 0; | 317 | return 0; |
269 | 318 | ||
270 | page = get_node_page(sbi, fi->i_xattr_nid); | 319 | page = get_node_page(sbi, fi->i_xattr_nid); |
320 | if (IS_ERR(page)) | ||
321 | return PTR_ERR(page); | ||
271 | base_addr = page_address(page); | 322 | base_addr = page_address(page); |
272 | 323 | ||
273 | list_for_each_xattr(entry, base_addr) { | 324 | list_for_each_xattr(entry, base_addr) { |
@@ -296,7 +347,7 @@ cleanup: | |||
296 | } | 347 | } |
297 | 348 | ||
298 | int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | 349 | int f2fs_setxattr(struct inode *inode, int name_index, const char *name, |
299 | const void *value, size_t value_len) | 350 | const void *value, size_t value_len, struct page *ipage) |
300 | { | 351 | { |
301 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 352 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
302 | struct f2fs_inode_info *fi = F2FS_I(inode); | 353 | struct f2fs_inode_info *fi = F2FS_I(inode); |
@@ -335,7 +386,7 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
335 | set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid); | 386 | set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid); |
336 | mark_inode_dirty(inode); | 387 | mark_inode_dirty(inode); |
337 | 388 | ||
338 | page = new_node_page(&dn, XATTR_NODE_OFFSET); | 389 | page = new_node_page(&dn, XATTR_NODE_OFFSET, ipage); |
339 | if (IS_ERR(page)) { | 390 | if (IS_ERR(page)) { |
340 | alloc_nid_failed(sbi, fi->i_xattr_nid); | 391 | alloc_nid_failed(sbi, fi->i_xattr_nid); |
341 | fi->i_xattr_nid = 0; | 392 | fi->i_xattr_nid = 0; |
@@ -435,7 +486,10 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
435 | inode->i_ctime = CURRENT_TIME; | 486 | inode->i_ctime = CURRENT_TIME; |
436 | clear_inode_flag(fi, FI_ACL_MODE); | 487 | clear_inode_flag(fi, FI_ACL_MODE); |
437 | } | 488 | } |
438 | update_inode_page(inode); | 489 | if (ipage) |
490 | update_inode(inode, ipage); | ||
491 | else | ||
492 | update_inode_page(inode); | ||
439 | mutex_unlock_op(sbi, ilock); | 493 | mutex_unlock_op(sbi, ilock); |
440 | 494 | ||
441 | return 0; | 495 | return 0; |
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 49c9558305e3..3c0817bef25d 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h | |||
@@ -112,21 +112,19 @@ extern const struct xattr_handler f2fs_xattr_trusted_handler; | |||
112 | extern const struct xattr_handler f2fs_xattr_acl_access_handler; | 112 | extern const struct xattr_handler f2fs_xattr_acl_access_handler; |
113 | extern const struct xattr_handler f2fs_xattr_acl_default_handler; | 113 | extern const struct xattr_handler f2fs_xattr_acl_default_handler; |
114 | extern const struct xattr_handler f2fs_xattr_advise_handler; | 114 | extern const struct xattr_handler f2fs_xattr_advise_handler; |
115 | extern const struct xattr_handler f2fs_xattr_security_handler; | ||
115 | 116 | ||
116 | extern const struct xattr_handler *f2fs_xattr_handlers[]; | 117 | extern const struct xattr_handler *f2fs_xattr_handlers[]; |
117 | 118 | ||
118 | extern int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | 119 | extern int f2fs_setxattr(struct inode *, int, const char *, |
119 | const void *value, size_t value_len); | 120 | const void *, size_t, struct page *); |
120 | extern int f2fs_getxattr(struct inode *inode, int name_index, const char *name, | 121 | extern int f2fs_getxattr(struct inode *, int, const char *, void *, size_t); |
121 | void *buffer, size_t buffer_size); | 122 | extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t); |
122 | extern ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, | ||
123 | size_t buffer_size); | ||
124 | |||
125 | #else | 123 | #else |
126 | 124 | ||
127 | #define f2fs_xattr_handlers NULL | 125 | #define f2fs_xattr_handlers NULL |
128 | static inline int f2fs_setxattr(struct inode *inode, int name_index, | 126 | static inline int f2fs_setxattr(struct inode *inode, int name_index, |
129 | const char *name, const void *value, size_t value_len) | 127 | const char *name, const void *value, size_t value_len) |
130 | { | 128 | { |
131 | return -EOPNOTSUPP; | 129 | return -EOPNOTSUPP; |
132 | } | 130 | } |
@@ -142,4 +140,14 @@ static inline ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, | |||
142 | } | 140 | } |
143 | #endif | 141 | #endif |
144 | 142 | ||
143 | #ifdef CONFIG_F2FS_FS_SECURITY | ||
144 | extern int f2fs_init_security(struct inode *, struct inode *, | ||
145 | const struct qstr *, struct page *); | ||
146 | #else | ||
147 | static inline int f2fs_init_security(struct inode *inode, struct inode *dir, | ||
148 | const struct qstr *qstr, struct page *ipage) | ||
149 | { | ||
150 | return 0; | ||
151 | } | ||
152 | #endif | ||
145 | #endif /* __F2FS_XATTR_H__ */ | 153 | #endif /* __F2FS_XATTR_H__ */ |