diff options
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r-- | fs/f2fs/file.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index df6a0596eccf..a6f3f6186588 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -241,6 +241,8 @@ go_write: | |||
241 | * will be used only for fsynced inodes after checkpoint. | 241 | * will be used only for fsynced inodes after checkpoint. |
242 | */ | 242 | */ |
243 | try_to_fix_pino(inode); | 243 | try_to_fix_pino(inode); |
244 | clear_inode_flag(fi, FI_APPEND_WRITE); | ||
245 | clear_inode_flag(fi, FI_UPDATE_WRITE); | ||
244 | goto out; | 246 | goto out; |
245 | } | 247 | } |
246 | sync_nodes: | 248 | sync_nodes: |
@@ -433,8 +435,12 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) | |||
433 | continue; | 435 | continue; |
434 | 436 | ||
435 | dn->data_blkaddr = NULL_ADDR; | 437 | dn->data_blkaddr = NULL_ADDR; |
436 | update_extent_cache(dn); | 438 | set_data_blkaddr(dn); |
439 | f2fs_update_extent_cache(dn); | ||
437 | invalidate_blocks(sbi, blkaddr); | 440 | invalidate_blocks(sbi, blkaddr); |
441 | if (dn->ofs_in_node == 0 && IS_INODE(dn->node_page)) | ||
442 | clear_inode_flag(F2FS_I(dn->inode), | ||
443 | FI_FIRST_BLOCK_WRITTEN); | ||
438 | nr_free++; | 444 | nr_free++; |
439 | } | 445 | } |
440 | if (nr_free) { | 446 | if (nr_free) { |
@@ -454,15 +460,16 @@ void truncate_data_blocks(struct dnode_of_data *dn) | |||
454 | truncate_data_blocks_range(dn, ADDRS_PER_BLOCK); | 460 | truncate_data_blocks_range(dn, ADDRS_PER_BLOCK); |
455 | } | 461 | } |
456 | 462 | ||
457 | static int truncate_partial_data_page(struct inode *inode, u64 from) | 463 | static int truncate_partial_data_page(struct inode *inode, u64 from, |
464 | bool force) | ||
458 | { | 465 | { |
459 | unsigned offset = from & (PAGE_CACHE_SIZE - 1); | 466 | unsigned offset = from & (PAGE_CACHE_SIZE - 1); |
460 | struct page *page; | 467 | struct page *page; |
461 | 468 | ||
462 | if (!offset) | 469 | if (!offset && !force) |
463 | return 0; | 470 | return 0; |
464 | 471 | ||
465 | page = find_data_page(inode, from >> PAGE_CACHE_SHIFT, false); | 472 | page = find_data_page(inode, from >> PAGE_CACHE_SHIFT, force); |
466 | if (IS_ERR(page)) | 473 | if (IS_ERR(page)) |
467 | return 0; | 474 | return 0; |
468 | 475 | ||
@@ -473,7 +480,8 @@ static int truncate_partial_data_page(struct inode *inode, u64 from) | |||
473 | 480 | ||
474 | f2fs_wait_on_page_writeback(page, DATA); | 481 | f2fs_wait_on_page_writeback(page, DATA); |
475 | zero_user(page, offset, PAGE_CACHE_SIZE - offset); | 482 | zero_user(page, offset, PAGE_CACHE_SIZE - offset); |
476 | set_page_dirty(page); | 483 | if (!force) |
484 | set_page_dirty(page); | ||
477 | out: | 485 | out: |
478 | f2fs_put_page(page, 1); | 486 | f2fs_put_page(page, 1); |
479 | return 0; | 487 | return 0; |
@@ -487,6 +495,7 @@ int truncate_blocks(struct inode *inode, u64 from, bool lock) | |||
487 | pgoff_t free_from; | 495 | pgoff_t free_from; |
488 | int count = 0, err = 0; | 496 | int count = 0, err = 0; |
489 | struct page *ipage; | 497 | struct page *ipage; |
498 | bool truncate_page = false; | ||
490 | 499 | ||
491 | trace_f2fs_truncate_blocks_enter(inode, from); | 500 | trace_f2fs_truncate_blocks_enter(inode, from); |
492 | 501 | ||
@@ -502,7 +511,10 @@ int truncate_blocks(struct inode *inode, u64 from, bool lock) | |||
502 | } | 511 | } |
503 | 512 | ||
504 | if (f2fs_has_inline_data(inode)) { | 513 | if (f2fs_has_inline_data(inode)) { |
514 | if (truncate_inline_inode(ipage, from)) | ||
515 | set_page_dirty(ipage); | ||
505 | f2fs_put_page(ipage, 1); | 516 | f2fs_put_page(ipage, 1); |
517 | truncate_page = true; | ||
506 | goto out; | 518 | goto out; |
507 | } | 519 | } |
508 | 520 | ||
@@ -533,7 +545,7 @@ out: | |||
533 | 545 | ||
534 | /* lastly zero out the first data page */ | 546 | /* lastly zero out the first data page */ |
535 | if (!err) | 547 | if (!err) |
536 | err = truncate_partial_data_page(inode, from); | 548 | err = truncate_partial_data_page(inode, from, truncate_page); |
537 | 549 | ||
538 | trace_f2fs_truncate_blocks_exit(inode, err); | 550 | trace_f2fs_truncate_blocks_exit(inode, err); |
539 | return err; | 551 | return err; |
@@ -997,6 +1009,9 @@ static int f2fs_ioc_release_volatile_write(struct file *filp) | |||
997 | if (!f2fs_is_volatile_file(inode)) | 1009 | if (!f2fs_is_volatile_file(inode)) |
998 | return 0; | 1010 | return 0; |
999 | 1011 | ||
1012 | if (!f2fs_is_first_block_written(inode)) | ||
1013 | return truncate_partial_data_page(inode, 0, true); | ||
1014 | |||
1000 | punch_hole(inode, 0, F2FS_BLKSIZE); | 1015 | punch_hole(inode, 0, F2FS_BLKSIZE); |
1001 | return 0; | 1016 | return 0; |
1002 | } | 1017 | } |
@@ -1029,6 +1044,41 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp) | |||
1029 | return ret; | 1044 | return ret; |
1030 | } | 1045 | } |
1031 | 1046 | ||
1047 | static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg) | ||
1048 | { | ||
1049 | struct inode *inode = file_inode(filp); | ||
1050 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
1051 | struct super_block *sb = sbi->sb; | ||
1052 | __u32 in; | ||
1053 | |||
1054 | if (!capable(CAP_SYS_ADMIN)) | ||
1055 | return -EPERM; | ||
1056 | |||
1057 | if (get_user(in, (__u32 __user *)arg)) | ||
1058 | return -EFAULT; | ||
1059 | |||
1060 | switch (in) { | ||
1061 | case F2FS_GOING_DOWN_FULLSYNC: | ||
1062 | sb = freeze_bdev(sb->s_bdev); | ||
1063 | if (sb && !IS_ERR(sb)) { | ||
1064 | f2fs_stop_checkpoint(sbi); | ||
1065 | thaw_bdev(sb->s_bdev, sb); | ||
1066 | } | ||
1067 | break; | ||
1068 | case F2FS_GOING_DOWN_METASYNC: | ||
1069 | /* do checkpoint only */ | ||
1070 | f2fs_sync_fs(sb, 1); | ||
1071 | f2fs_stop_checkpoint(sbi); | ||
1072 | break; | ||
1073 | case F2FS_GOING_DOWN_NOSYNC: | ||
1074 | f2fs_stop_checkpoint(sbi); | ||
1075 | break; | ||
1076 | default: | ||
1077 | return -EINVAL; | ||
1078 | } | ||
1079 | return 0; | ||
1080 | } | ||
1081 | |||
1032 | static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) | 1082 | static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg) |
1033 | { | 1083 | { |
1034 | struct inode *inode = file_inode(filp); | 1084 | struct inode *inode = file_inode(filp); |
@@ -1078,6 +1128,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
1078 | return f2fs_ioc_release_volatile_write(filp); | 1128 | return f2fs_ioc_release_volatile_write(filp); |
1079 | case F2FS_IOC_ABORT_VOLATILE_WRITE: | 1129 | case F2FS_IOC_ABORT_VOLATILE_WRITE: |
1080 | return f2fs_ioc_abort_volatile_write(filp); | 1130 | return f2fs_ioc_abort_volatile_write(filp); |
1131 | case F2FS_IOC_SHUTDOWN: | ||
1132 | return f2fs_ioc_shutdown(filp, arg); | ||
1081 | case FITRIM: | 1133 | case FITRIM: |
1082 | return f2fs_ioc_fitrim(filp, arg); | 1134 | return f2fs_ioc_fitrim(filp, arg); |
1083 | default: | 1135 | default: |