Commit 5cdd4c04 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-f2fs-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs

Pull f2fs updates from Jaegeuk Kim:
 "In this round, we've added new features such as disk quota and statx,
  and modified internal bio management flow to merge more IOs depending
  on block types. We've also made internal threads freezeable for
  Android battery life. In addition to them, there are some patches to
  avoid lock contention as well as a couple of deadlock conditions.

  Enhancements:
   - support usrquota, grpquota, and statx
   - manage DATA/NODE typed bios separately to serialize more IOs
   - modify f2fs_lock_op/wio_mutex to avoid lock contention
   - prevent lock contention in migratepage

  Bug fixes:
   - fix missing load of written inode flag
   - fix worst case victim selection in GC
   - freezeable GC and discard threads for Android battery life
   - sanitize f2fs metadata to deal with security hole
   - clean up sysfs-related code and docs"

* tag 'for-f2fs-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (59 commits)
  f2fs: support plain user/group quota
  f2fs: avoid deadlock caused by lock order of page and lock_op
  f2fs: use spin_{,un}lock_irq{save,restore}
  f2fs: relax migratepage for atomic written page
  f2fs: don't count inode block in in-memory inode.i_blocks
  Revert "f2fs: fix to clean previous mount option when remount_fs"
  f2fs: do not set LOST_PINO for renamed dir
  f2fs: do not set LOST_PINO for newly created dir
  f2fs: skip ->writepages for {mete,node}_inode during recovery
  f2fs: introduce __check_sit_bitmap
  f2fs: stop gc/discard thread in prior during umount
  f2fs: introduce reserved_blocks in sysfs
  f2fs: avoid redundant f2fs_flush after remount
  f2fs: report # of free inodes more precisely
  f2fs: add ioctl to do gc with target block address
  f2fs: don't need to check encrypted inode for partial truncation
  f2fs: measure inode.i_blocks as generic filesystem
  f2fs: set CP_TRIMMED_FLAG correctly
  f2fs: require key for truncate(2) of encrypted file
  f2fs: move sysfs code from super.c to fs/f2fs/sysfs.c
  ...
parents 7cee9384 0abd675e
...@@ -75,7 +75,7 @@ Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com> ...@@ -75,7 +75,7 @@ Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Description: Description:
Controls the memory footprint used by f2fs. Controls the memory footprint used by f2fs.
What: /sys/fs/f2fs/<disk>/trim_sections What: /sys/fs/f2fs/<disk>/batched_trim_sections
Date: February 2015 Date: February 2015
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org> Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description: Description:
...@@ -112,3 +112,21 @@ Date: January 2016 ...@@ -112,3 +112,21 @@ Date: January 2016
Contact: "Shuoran Liu" <liushuoran@huawei.com> Contact: "Shuoran Liu" <liushuoran@huawei.com>
Description: Description:
Shows total written kbytes issued to disk. Shows total written kbytes issued to disk.
What: /sys/fs/f2fs/<disk>/inject_rate
Date: May 2016
Contact: "Sheng Yong" <shengyong1@huawei.com>
Description:
Controls the injection rate.
What: /sys/fs/f2fs/<disk>/inject_type
Date: May 2016
Contact: "Sheng Yong" <shengyong1@huawei.com>
Description:
Controls the injection type.
What: /sys/fs/f2fs/<disk>/reserved_blocks
Date: June 2017
Contact: "Chao Yu" <yuchao0@huawei.com>
Description:
Controls current reserved blocks in system.
...@@ -155,11 +155,15 @@ noinline_data Disable the inline data feature, inline data feature is ...@@ -155,11 +155,15 @@ noinline_data Disable the inline data feature, inline data feature is
enabled by default. enabled by default.
data_flush Enable data flushing before checkpoint in order to data_flush Enable data flushing before checkpoint in order to
persist data of regular and symlink. persist data of regular and symlink.
fault_injection=%d Enable fault injection in all supported types with
specified injection rate.
mode=%s Control block allocation mode which supports "adaptive" mode=%s Control block allocation mode which supports "adaptive"
and "lfs". In "lfs" mode, there should be no random and "lfs". In "lfs" mode, there should be no random
writes towards main area. writes towards main area.
io_bits=%u Set the bit size of write IO requests. It should be set io_bits=%u Set the bit size of write IO requests. It should be set
with "mode=lfs". with "mode=lfs".
usrquota Enable plain user disk quota accounting.
grpquota Enable plain group disk quota accounting.
================================================================================ ================================================================================
DEBUGFS ENTRIES DEBUGFS ENTRIES
......
...@@ -2,7 +2,7 @@ obj-$(CONFIG_F2FS_FS) += f2fs.o ...@@ -2,7 +2,7 @@ obj-$(CONFIG_F2FS_FS) += f2fs.o
f2fs-y := dir.o file.o inode.o namei.o hash.o super.o inline.o f2fs-y := dir.o file.o inode.o namei.o hash.o super.o inline.o
f2fs-y += checkpoint.o gc.o data.o node.o segment.o recovery.o f2fs-y += checkpoint.o gc.o data.o node.o segment.o recovery.o
f2fs-y += shrinker.o extent_cache.o f2fs-y += shrinker.o extent_cache.o sysfs.o
f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o
f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
......
...@@ -233,7 +233,7 @@ static int __f2fs_set_acl(struct inode *inode, int type, ...@@ -233,7 +233,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size); value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size);
if (IS_ERR(value)) { if (IS_ERR(value)) {
clear_inode_flag(inode, FI_ACL_MODE); clear_inode_flag(inode, FI_ACL_MODE);
return (int)PTR_ERR(value); return PTR_ERR(value);
} }
} }
......
...@@ -31,7 +31,7 @@ void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io) ...@@ -31,7 +31,7 @@ void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io)
set_ckpt_flags(sbi, CP_ERROR_FLAG); set_ckpt_flags(sbi, CP_ERROR_FLAG);
sbi->sb->s_flags |= MS_RDONLY; sbi->sb->s_flags |= MS_RDONLY;
if (!end_io) if (!end_io)
f2fs_flush_merged_bios(sbi); f2fs_flush_merged_writes(sbi);
} }
/* /*
...@@ -162,6 +162,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, ...@@ -162,6 +162,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
.op = REQ_OP_READ, .op = REQ_OP_READ,
.op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD, .op_flags = sync ? (REQ_META | REQ_PRIO) : REQ_RAHEAD,
.encrypted_page = NULL, .encrypted_page = NULL,
.in_list = false,
}; };
struct blk_plug plug; struct blk_plug plug;
...@@ -207,12 +208,10 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, ...@@ -207,12 +208,10 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
} }
fio.page = page; fio.page = page;
fio.old_blkaddr = fio.new_blkaddr; f2fs_submit_page_bio(&fio);
f2fs_submit_page_mbio(&fio);
f2fs_put_page(page, 0); f2fs_put_page(page, 0);
} }
out: out:
f2fs_submit_merged_bio(sbi, META, READ);
blk_finish_plug(&plug); blk_finish_plug(&plug);
return blkno - start; return blkno - start;
} }
...@@ -249,13 +248,13 @@ static int f2fs_write_meta_page(struct page *page, ...@@ -249,13 +248,13 @@ static int f2fs_write_meta_page(struct page *page,
dec_page_count(sbi, F2FS_DIRTY_META); dec_page_count(sbi, F2FS_DIRTY_META);
if (wbc->for_reclaim) if (wbc->for_reclaim)
f2fs_submit_merged_bio_cond(sbi, page->mapping->host, f2fs_submit_merged_write_cond(sbi, page->mapping->host,
0, page->index, META, WRITE); 0, page->index, META);
unlock_page(page); unlock_page(page);
if (unlikely(f2fs_cp_error(sbi))) if (unlikely(f2fs_cp_error(sbi)))
f2fs_submit_merged_bio(sbi, META, WRITE); f2fs_submit_merged_write(sbi, META);
return 0; return 0;
...@@ -270,6 +269,9 @@ static int f2fs_write_meta_pages(struct address_space *mapping, ...@@ -270,6 +269,9 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
long diff, written; long diff, written;
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
goto skip_write;
/* collect a number of dirty meta pages and write together */ /* collect a number of dirty meta pages and write together */
if (wbc->for_kupdate || if (wbc->for_kupdate ||
get_pages(sbi, F2FS_DIRTY_META) < nr_pages_to_skip(sbi, META)) get_pages(sbi, F2FS_DIRTY_META) < nr_pages_to_skip(sbi, META))
...@@ -358,7 +360,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, ...@@ -358,7 +360,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
} }
stop: stop:
if (nwritten) if (nwritten)
f2fs_submit_merged_bio(sbi, type, WRITE); f2fs_submit_merged_write(sbi, type);
blk_finish_plug(&plug); blk_finish_plug(&plug);
...@@ -906,7 +908,7 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type) ...@@ -906,7 +908,7 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
* We should submit bio, since it exists several * We should submit bio, since it exists several
* wribacking dentry pages in the freeing inode. * wribacking dentry pages in the freeing inode.
*/ */
f2fs_submit_merged_bio(sbi, DATA, WRITE); f2fs_submit_merged_write(sbi, DATA);
cond_resched(); cond_resched();
} }
goto retry; goto retry;
...@@ -1051,8 +1053,9 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) ...@@ -1051,8 +1053,9 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
{ {
unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num; unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num;
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
unsigned long flags;
spin_lock(&sbi->cp_lock); spin_lock_irqsave(&sbi->cp_lock, flags);
if ((cpc->reason & CP_UMOUNT) && if ((cpc->reason & CP_UMOUNT) &&
le32_to_cpu(ckpt->cp_pack_total_block_count) > le32_to_cpu(ckpt->cp_pack_total_block_count) >
...@@ -1083,14 +1086,14 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) ...@@ -1083,14 +1086,14 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
/* set this flag to activate crc|cp_ver for recovery */ /* set this flag to activate crc|cp_ver for recovery */
__set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG); __set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG);
spin_unlock(&sbi->cp_lock); spin_unlock_irqrestore(&sbi->cp_lock, flags);
} }
static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
{ {
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
struct f2fs_nm_info *nm_i = NM_I(sbi); struct f2fs_nm_info *nm_i = NM_I(sbi);
unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num; unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num, flags;
block_t start_blk; block_t start_blk;
unsigned int data_sum_blocks, orphan_blocks; unsigned int data_sum_blocks, orphan_blocks;
__u32 crc32 = 0; __u32 crc32 = 0;
...@@ -1132,12 +1135,12 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) ...@@ -1132,12 +1135,12 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
/* 2 cp + n data seg summary + orphan inode blocks */ /* 2 cp + n data seg summary + orphan inode blocks */
data_sum_blocks = npages_for_summary_flush(sbi, false); data_sum_blocks = npages_for_summary_flush(sbi, false);
spin_lock(&sbi->cp_lock); spin_lock_irqsave(&sbi->cp_lock, flags);
if (data_sum_blocks < NR_CURSEG_DATA_TYPE) if (data_sum_blocks < NR_CURSEG_DATA_TYPE)
__set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); __set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
else else
__clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); __clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
spin_unlock(&sbi->cp_lock); spin_unlock_irqrestore(&sbi->cp_lock, flags);
orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num); orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num);
ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks + ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks +
...@@ -1295,7 +1298,7 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) ...@@ -1295,7 +1298,7 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops"); trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops");
f2fs_flush_merged_bios(sbi); f2fs_flush_merged_writes(sbi);
/* this is the case of multiple fstrims without any changes */ /* this is the case of multiple fstrims without any changes */
if (cpc->reason & CP_DISCARD) { if (cpc->reason & CP_DISCARD) {
......
This diff is collapsed.
...@@ -415,6 +415,7 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir, ...@@ -415,6 +415,7 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
* We lost i_pino from now on. * We lost i_pino from now on.
*/ */
if (is_inode_flag_set(inode, FI_INC_LINK)) { if (is_inode_flag_set(inode, FI_INC_LINK)) {
if (!S_ISDIR(inode->i_mode))
file_lost_pino(inode); file_lost_pino(inode);
/* /*
* If link the tmpfile to alias through linkat path, * If link the tmpfile to alias through linkat path,
......
...@@ -320,7 +320,7 @@ static void __drop_largest_extent(struct inode *inode, ...@@ -320,7 +320,7 @@ static void __drop_largest_extent(struct inode *inode,
} }
/* return true, if inode page is changed */ /* return true, if inode page is changed */
bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext) static bool __f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
{ {
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct extent_tree *et; struct extent_tree *et;
...@@ -358,6 +358,16 @@ bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext) ...@@ -358,6 +358,16 @@ bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
return false; return false;
} }
bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
{
bool ret = __f2fs_init_extent_tree(inode, i_ext);
if (!F2FS_I(inode)->extent_tree)
set_inode_flag(inode, FI_NO_EXTENT);
return ret;
}
static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs, static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs,
struct extent_info *ei) struct extent_info *ei)
{ {
......
This diff is collapsed.
This diff is collapsed.
...@@ -32,13 +32,14 @@ static int gc_thread_func(void *data) ...@@ -32,13 +32,14 @@ static int gc_thread_func(void *data)
wait_ms = gc_th->min_sleep_time; wait_ms = gc_th->min_sleep_time;
set_freezable();
do { do {
if (try_to_freeze())
continue;
else
wait_event_interruptible_timeout(*wq, wait_event_interruptible_timeout(*wq,
kthread_should_stop(), kthread_should_stop() || freezing(current),
msecs_to_jiffies(wait_ms)); msecs_to_jiffies(wait_ms));
if (try_to_freeze())
continue;
if (kthread_should_stop()) if (kthread_should_stop())
break; break;
...@@ -258,11 +259,20 @@ static unsigned int get_greedy_cost(struct f2fs_sb_info *sbi, ...@@ -258,11 +259,20 @@ static unsigned int get_greedy_cost(struct f2fs_sb_info *sbi,
valid_blocks * 2 : valid_blocks; valid_blocks * 2 : valid_blocks;
} }
static unsigned int get_ssr_cost(struct f2fs_sb_info *sbi,
unsigned int segno)
{
struct seg_entry *se = get_seg_entry(sbi, segno);
return se->ckpt_valid_blocks > se->valid_blocks ?
se->ckpt_valid_blocks : se->valid_blocks;
}
static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi, static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi,
unsigned int segno, struct victim_sel_policy *p) unsigned int segno, struct victim_sel_policy *p)
{ {
if (p->alloc_mode == SSR) if (p->alloc_mode == SSR)
return get_seg_entry(sbi, segno)->ckpt_valid_blocks; return get_ssr_cost(sbi, segno);
/* alloc_mode == LFS */ /* alloc_mode == LFS */
if (p->gc_mode == GC_GREEDY) if (p->gc_mode == GC_GREEDY)
...@@ -586,9 +596,11 @@ static void move_encrypted_block(struct inode *inode, block_t bidx, ...@@ -586,9 +596,11 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
struct f2fs_io_info fio = { struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode), .sbi = F2FS_I_SB(inode),
.type = DATA, .type = DATA,
.temp = COLD,
.op = REQ_OP_READ, .op = REQ_OP_READ,
.op_flags = 0, .op_flags = 0,
.encrypted_page = NULL, .encrypted_page = NULL,
.in_list = false,
}; };
struct dnode_of_data dn; struct dnode_of_data dn;
struct f2fs_summary sum; struct f2fs_summary sum;
...@@ -632,7 +644,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx, ...@@ -632,7 +644,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr; fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr, allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
&sum, CURSEG_COLD_DATA); &sum, CURSEG_COLD_DATA, NULL, false);
fio.encrypted_page = pagecache_get_page(META_MAPPING(fio.sbi), newaddr, fio.encrypted_page = pagecache_get_page(META_MAPPING(fio.sbi), newaddr,
FGP_LOCK | FGP_CREAT, GFP_NOFS); FGP_LOCK | FGP_CREAT, GFP_NOFS);
...@@ -670,7 +682,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx, ...@@ -670,7 +682,7 @@ static void move_encrypted_block(struct inode *inode, block_t bidx,
fio.op = REQ_OP_WRITE; fio.op = REQ_OP_WRITE;
fio.op_flags = REQ_SYNC; fio.op_flags = REQ_SYNC;
fio.new_blkaddr = newaddr; fio.new_blkaddr = newaddr;
f2fs_submit_page_mbio(&fio); f2fs_submit_page_write(&fio);
f2fs_update_data_blkaddr(&dn, newaddr); f2fs_update_data_blkaddr(&dn, newaddr);
set_inode_flag(inode, FI_APPEND_WRITE); set_inode_flag(inode, FI_APPEND_WRITE);
...@@ -712,12 +724,13 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type, ...@@ -712,12 +724,13 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
struct f2fs_io_info fio = { struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode), .sbi = F2FS_I_SB(inode),
.type = DATA, .type = DATA,
.temp = COLD,
.op = REQ_OP_WRITE, .op = REQ_OP_WRITE,
.op_flags = REQ_SYNC, .op_flags = REQ_SYNC,
.old_blkaddr = NULL_ADDR, .old_blkaddr = NULL_ADDR,
.page = page, .page = page,
.encrypted_page = NULL, .encrypted_page = NULL,
.need_lock = true, .need_lock = LOCK_REQ,
}; };
bool is_dirty = PageDirty(page); bool is_dirty = PageDirty(page);
int err; int err;
...@@ -936,8 +949,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, ...@@ -936,8 +949,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
} }
if (gc_type == FG_GC) if (gc_type == FG_GC)
f2fs_submit_merged_bio(sbi, f2fs_submit_merged_write(sbi,
(type == SUM_TYPE_NODE) ? NODE : DATA, WRITE); (type == SUM_TYPE_NODE) ? NODE : DATA);
blk_finish_plug(&plug); blk_finish_plug(&plug);
...@@ -955,7 +968,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, ...@@ -955,7 +968,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
{ {
int gc_type = sync ? FG_GC : BG_GC; int gc_type = sync ? FG_GC : BG_GC;
int sec_freed = 0; int sec_freed = 0;
int ret = -EINVAL; int ret;
struct cp_control cpc; struct cp_control cpc;
unsigned int init_segno = segno; unsigned int init_segno = segno;
struct gc_inode_list gc_list = { struct gc_inode_list gc_list = {
...@@ -965,8 +978,10 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, ...@@ -965,8 +978,10 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
cpc.reason = __get_cp_reason(sbi); cpc.reason = __get_cp_reason(sbi);
gc_more: gc_more:
if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE))) if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE))) {
ret = -EINVAL;
goto stop; goto stop;
}
if (unlikely(f2fs_cp_error(sbi))) { if (unlikely(f2fs_cp_error(sbi))) {
ret = -EIO; ret = -EIO;
goto stop; goto stop;
...@@ -987,6 +1002,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, ...@@ -987,6 +1002,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
gc_type = FG_GC; gc_type = FG_GC;
} }
ret = -EINVAL;
/* f2fs_balance_fs doesn't need to do BG_GC in critical path. */ /* f2fs_balance_fs doesn't need to do BG_GC in critical path. */
if (gc_type == BG_GC && !background) if (gc_type == BG_GC && !background)
goto stop; goto stop;
......
...@@ -316,12 +316,12 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir, ...@@ -316,12 +316,12 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
int make_empty_inline_dir(struct inode *inode, struct inode *parent, int make_empty_inline_dir(struct inode *inode, struct inode *parent,
struct page *ipage) struct page *ipage)
{ {
struct f2fs_inline_dentry *dentry_blk; struct f2fs_inline_dentry *inline_dentry;
struct f2fs_dentry_ptr d; struct f2fs_dentry_ptr d;
dentry_blk = inline_data_addr(ipage); inline_dentry = inline_data_addr(ipage);
make_dentry_ptr_inline(NULL, &d, dentry_blk); make_dentry_ptr_inline(NULL, &d, inline_dentry);
do_make_empty_dir(inode, parent, &d); do_make_empty_dir(inode, parent, &d);
set_page_dirty(ipage); set_page_dirty(ipage);
...@@ -500,7 +500,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, ...@@ -500,7 +500,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
struct page *ipage; struct page *ipage;
unsigned int bit_pos; unsigned int bit_pos;
f2fs_hash_t name_hash; f2fs_hash_t name_hash;
struct f2fs_inline_dentry *dentry_blk = NULL; struct f2fs_inline_dentry *inline_dentry = NULL;
struct f2fs_dentry_ptr d; struct f2fs_dentry_ptr d;
int slots = GET_DENTRY_SLOTS(new_name->len); int slots = GET_DENTRY_SLOTS(new_name->len);
struct page *page = NULL; struct page *page = NULL;
...@@ -510,11 +510,11 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, ...@@ -510,11 +510,11 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
if (IS_ERR(ipage)) if (IS_ERR(ipage))
return PTR_ERR(ipage); return PTR_ERR(ipage);
dentry_blk = inline_data_addr(ipage); inline_dentry = inline_data_addr(ipage);
bit_pos = room_for_filename(&dentry_blk->dentry_bitmap, bit_pos = room_for_filename(&inline_dentry->dentry_bitmap,
slots, NR_INLINE_DENTRY); slots, NR_INLINE_DENTRY);
if (bit_pos >= NR_INLINE_DENTRY) { if (bit_pos >= NR_INLINE_DENTRY) {
err = f2fs_convert_inline_dir(dir, ipage, dentry_blk); err = f2fs_convert_inline_dir(dir, ipage, inline_dentry);
if (err) if (err)
return err; return err;
err = -EAGAIN; err = -EAGAIN;
...@@ -534,7 +534,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name, ...@@ -534,7 +534,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
f2fs_wait_on_page_writeback(ipage, NODE, true); f2fs_wait_on_page_writeback(ipage, NODE, true);
name_hash = f2fs_dentry_hash(new_name, NULL); name_hash = f2fs_dentry_hash(new_name, NULL);
make_dentry_ptr_inline(NULL, &d, dentry_blk); make_dentry_ptr_inline(NULL, &d, inline_dentry);
f2fs_update_dentry(ino, mode, &d, new_name, name_hash, bit_pos); f2fs_update_dentry(ino, mode, &d, new_name, name_hash, bit_pos);
set_page_dirty(ipage); set_page_dirty(ipage);
...@@ -586,14 +586,14 @@ bool f2fs_empty_inline_dir(struct inode *dir) ...@@ -586,14 +586,14 @@ bool f2fs_empty_inline_dir(struct inode *dir)
struct f2fs_sb_info *sbi = F2FS_I_SB(dir); struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
struct page *ipage; struct page *ipage;
unsigned int bit_pos = 2; unsigned int bit_pos = 2;
struct f2fs_inline_dentry *dentry_blk; struct f2fs_inline_dentry *inline_dentry;
ipage = get_node_page(sbi, dir->i_ino); ipage = get_node_page(sbi, dir->i_ino);
if (IS_ERR(ipage)) if (IS_ERR(ipage))
return false; return false;
dentry_blk = inline_data_addr(ipage); inline_dentry = inline_data_addr(ipage);
bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, bit_pos = find_next_bit_le(&inline_dentry->dentry_bitmap,
NR_INLINE_DENTRY, NR_INLINE_DENTRY,
bit_pos); bit_pos);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "f2fs.h" #include "f2fs.h"
#include "node.h" #include "node.h"
#include "segment.h"
#include <trace/events/f2fs.h> #include <trace/events/f2fs.h>
...@@ -44,7 +45,6 @@ void f2fs_set_inode_flags(struct inode *inode) ...@@ -44,7 +45,6 @@ void f2fs_set_inode_flags(struct inode *inode)
new_fl |= S_DIRSYNC; new_fl |= S_DIRSYNC;
inode_set_flags(inode, new_fl, inode_set_flags(inode, new_fl,
S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
f2fs_mark_inode_dirty_sync(inode, false);
} }
static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri) static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
...@@ -130,7 +130,7 @@ static int do_read_inode(struct inode *inode) ...@@ -130,7 +130,7 @@ static int do_read_inode(struct inode *inode)
i_gid_write(inode, le32_to_cpu(ri->i_gid)); i_gid_write(inode, le32_to_cpu(ri->i_gid));
set_nlink(inode, le32_to_cpu(ri->i_links)); set_nlink(inode, le32_to_cpu(ri->i_links));
inode->i_size = le64_to_cpu(ri->i_size); inode->i_size = le64_to_cpu(ri->i_size);
inode->i_blocks = le64_to_cpu(ri->i_blocks); inode->i_blocks = SECTOR_FROM_BLOCK(le64_to_cpu(ri->i_blocks) - 1);
inode->i_atime.tv_sec = le64_to_cpu(ri->i_atime); inode->i_atime.tv_sec = le64_to_cpu(ri->i_atime);
inode->i_ctime.tv_sec = le64_to_cpu(ri->i_ctime); inode->i_ctime.tv_sec = le64_to_cpu(ri->i_ctime);
...@@ -226,6 +226,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino) ...@@ -226,6 +226,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
ret = -EIO; ret = -EIO;
goto bad_inode; goto bad_inode;
} }
f2fs_set_inode_flags(inode);
unlock_new_inode(inode); unlock_new_inode(inode);
trace_f2fs_iget(inode); trace_f2fs_iget(inode);
return inode; return inode;
...@@ -267,7 +268,7 @@ int update_inode(struct inode *inode, struct page *node_page) ...@@ -267,7 +268,7 @@ int update_inode(struct inode *inode, struct page *node_page)
ri->i_gid = cpu_to_le32(i_gid_read(inode)); ri->i_gid = cpu_to_le32(i_gid_read(inode));
ri->i_links = cpu_to_le32(inode->i_nlink); ri->i_links = cpu_to_le32(inode->i_nlink);
ri->i_size = cpu_to_le64(i_size_read(inode)); ri->i_size = cpu_to_le64(i_size_read(inode));
ri->i_blocks = cpu_to_le64(inode->i_blocks); ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(inode->i_blocks) + 1);
if (et) { if (et) {
read_lock(&et->lock); read_lock(&et->lock);
...@@ -372,6 +373,8 @@ void f2fs_evict_inode(struct inode *inode) ...@@ -372,6 +373,8 @@ void f2fs_evict_inode(struct inode *inode)
if (inode->i_nlink || is_bad_inode(inode)) if (inode->i_nlink || is_bad_inode(inode))
goto no_delete; goto no_delete;
dquot_initialize(inode);
remove_ino_entry(sbi, inode->i_ino, APPEND_INO); remove_ino_entry(sbi, inode->i_ino, APPEND_INO);
remove_ino_entry(sbi, inode->i_ino, UPDATE_INO); remove_ino_entry(sbi, inode->i_ino, UPDATE_INO);
...@@ -404,8 +407,11 @@ void f2fs_evict_inode(struct inode *inode) ...@@ -404,8 +407,11 @@ void f2fs_evict_inode(struct inode *inode)
if (err) if (err)
update_inode_page(inode); update_inode_page(inode);
dquot_free_inode(inode);
sb_end_intwrite(inode->i_sb); sb_end_intwrite(inode->i_sb);
no_delete: no_delete:
dquot_drop(inode);
stat_dec_inline_xattr(inode); stat_dec_inline_xattr(inode);
stat_dec_inline_dir(inode); stat_dec_inline_dir(inode);
stat_dec_inline_inode(inode); stat_dec_inline_inode(inode);
...@@ -425,9 +431,10 @@ void f2fs_evict_inode(struct inode *inode) ...@@ -425,9 +431,10 @@ void f2fs_evict_inode(struct inode *inode)
if (is_inode_flag_set(inode, FI_FREE_NID)) { if (is_inode_flag_set(inode, FI_FREE_NID)) {
alloc_nid_failed(sbi, inode->i_ino); alloc_nid_failed(sbi, inode->i_ino);
clear_inode_flag(inode, FI_FREE_NID); clear_inode_flag(inode, FI_FREE_NID);
} } else {
f2fs_bug_on(sbi, err && f2fs_bug_on(sbi, err &&
!exist_written_data(sbi, inode->i_ino, ORPHAN_INO)); !exist_written_data(sbi, inode->i_ino, ORPHAN_INO));
}
out_clear: out_clear:
fscrypt_put_encryption_info(inode, NULL); fscrypt_put_encryption_info(inode, NULL);
clear_inode(inode); clear_inode(inode);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/quotaops.h>
#include "f2fs.h" #include "f2fs.h"
#include "node.h" #include "node.h"
...@@ -42,6 +43,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) ...@@ -42,6 +43,8 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
} }
f2fs_unlock_op(sbi); f2fs_unlock_op(sbi);
nid_free = true;
inode_init_owner(inode, dir, mode); inode_init_owner(inode, dir, mode);
inode->i_ino = ino; inode->i_ino = ino;
...@@ -52,10 +55,17 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) ...@@ -52,10 +55,17 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
err = insert_inode_locked(inode); err = insert_inode_locked(inode);
if (err) { if (err) {
err = -EINVAL; err = -EINVAL;
nid_free = true;
goto fail; goto fail;
} }
err = dquot_initialize(inode);
if (err)
goto fail_drop;
err = dquot_alloc_inode(inode);
if (err)
goto fail_drop;
/* If the directory encrypted, then we should encrypt the inode. */ /* If the directory encrypted, then we should encrypt the inode. */
if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode)) if (f2fs_encrypted_inode(dir) && f2fs_may_encrypt(inode))
f2fs_set_encrypted_inode(inode); f2fs_set_encrypted_inode(inode);
...@@ -85,6 +95,16 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) ...@@ -85,6 +95,16 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
set_inode_flag(inode, FI_FREE_NID); set_inode_flag(inode, FI_FREE_NID);
iput(inode); iput(inode);
return ERR_PTR(err); return ERR_PTR(err);
fail_drop:
trace_f2fs_new_inode(inode, err);
dquot_drop(inode);
inode->i_flags |= S_NOQUOTA;
if (nid_free)
set_inode_flag(inode, FI_FREE_NID);
clear_nlink(inode);
unlock_new_inode(inode);
iput(inode);
return ERR_PTR(err);
} }
static int is_multimedia_file(const unsigned char *s, const char *sub) static int is_multimedia_file(const unsigned char *s, const char *sub)
...@@ -136,6 +156,10 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ...@@ -136,6 +156,10 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
nid_t ino = 0; nid_t ino = 0;
int err; int err;
err = dquot_initialize(dir);
if (err)
return err;
inode = f2fs_new_inode(dir, mode); inode = f2fs_new_inode(dir, mode);
if (IS_ERR(inode)) if (IS_ERR(inode))
return PTR_ERR(inode); return PTR_ERR(inode);
...@@ -180,6 +204,10 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -180,6 +204,10 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
!fscrypt_has_permitted_context(dir, inode)) !fscrypt_has_permitted_context(dir, inode))
return -EPERM; return -EPERM;
err = dquot_initialize(dir);
if (err)
return err;
f2fs_balance_fs(sbi, true); f2fs_balance_fs(sbi, true);
inode->i_ctime = current_time(inode); inode->i_ctime = current_time(inode);
...@@ -347,6 +375,10 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -347,6 +375,10 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
trace_f2fs_unlink_enter(dir, dentry); trace_f2fs_unlink_enter(dir, dentry);
err = dquot_initialize(dir);
if (err)
return err;
de = f2fs_find_entry(dir, &dentry->d_name, &page); de = f2fs_find_entry(dir, &dentry->d_name, &page);
if (!de) { if (!de) {
if (IS_ERR(page)) if (IS_ERR(page))
...@@ -413,6 +445,10 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -413,6 +445,10 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
if (disk_link.len > dir->i_sb->s_blocksize) if (disk_link.len > dir->i_sb->s_blocksize)
return -ENAMETOOLONG; return -ENAMETOOLONG;
err = dquot_initialize(dir);
if (err)
return err;
inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO); inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
if (IS_ERR(inode)) if (IS_ERR(inode))
return PTR_ERR(inode); return PTR_ERR(inode);
...@@ -500,6 +536,10 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -500,6 +536,10 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct inode *inode; struct inode *inode;
int err; int err;
err = dquot_initialize(dir);
if (err)
return err;
inode = f2fs_new_inode(dir, S_IFDIR | mode); inode = f2fs_new_inode(dir, S_IFDIR | mode);
if (IS_ERR(inode)) if (IS_ERR(inode))
return PTR_ERR(inode); return PTR_ERR(inode);
...@@ -548,6 +588,10 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry, ...@@ -548,6 +588,10 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
struct inode *inode; struct inode *inode;
int err = 0; int err = 0;
err = dquot_initialize(dir);
if (err)
return err;
inode = f2fs_new_inode(dir, mode); inode = f2fs_new_inode(dir, mode);
if (IS_ERR(inode)) if (IS_ERR(inode))
return PTR_ERR(inode); return PTR_ERR(inode);
...@@ -583,6 +627,10 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry, ...@@ -583,6 +627,10 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry,
struct inode *inode; struct inode *inode;
int err; int err;
err = dquot_initialize(dir);
if (err)
return err;
inode = f2fs_new_inode(dir, mode); inode = f2fs_new_inode(dir, mode);
if (IS_ERR(inode)) if (IS_ERR(inode))
return PTR_ERR(inode); return PTR_ERR(inode);
...@@ -676,6 +724,14 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -676,6 +724,14 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto out; goto out;
} }
err = dquot_initialize(old_dir);
if (err)
goto out;
err = dquot_initialize(new_dir);
if (err)
goto out;
old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
if (!old_entry) { if (!old_entry) {
if (IS_ERR(old_page)) if (IS_ERR(old_page))
...@@ -772,7 +828,10 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -772,7 +828,10 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
down_write(&F2FS_I(old_inode)->i_sem); down_write(&F2FS_I(old_inode)->i_sem);
if (!old_dir_entry || whiteout)
file_lost_pino(old_inode); file_lost_pino(old_inode);
else
F2FS_I(old_inode)->i_pino = new_dir->i_ino;
up_write(&F2FS_I(old_inode)->i_sem); up_write(&F2FS_I(old_inode)->i_sem);
old_inode->i_ctime = current_time(old_inode); old_inode->i_ctime = current_time(old_inode);
...@@ -853,6 +912,14 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -853,6 +912,14 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
!fscrypt_has_permitted_context(old_dir, new_inode))) !fscrypt_has_permitted_context(old_dir, new_inode)))
return -EPERM; return -EPERM;
err = dquot_initialize(old_dir);
if (err)
goto out;
err = dquot_initialize(new_dir);
if (err)
goto out;
old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
if (!old_entry) { if (!old_entry) {
if (IS_ERR(old_page)) if (IS_ERR(old_page))
......
...@@ -158,9 +158,6 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, ...@@ -158,9 +158,6 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid);
struct nat_entry_set *head; struct nat_entry_set *head;
if (get_nat_flag(ne, IS_DIRTY))
return;
head = radix_tree_lookup(&nm_i->nat_set_root, set); head = radix_tree_lookup(&nm_i->nat_set_root, set);
if (!head) { if (!head) {
head = f2fs_kmem_cache_alloc(nat_entry_set_slab, GFP_NOFS); head = f2fs_kmem_cache_alloc(nat_entry_set_slab, GFP_NOFS);
...@@ -171,10 +168,18 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, ...@@ -171,10 +168,18 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
head->entry_cnt = 0; head->entry_cnt = 0;
f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head); f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head);
} }
list_move_tail(&ne->list, &head->entry_list);
if (get_nat_flag(ne, IS_DIRTY))
goto refresh_list;
nm_i->dirty_nat_cnt++; nm_i->dirty_nat_cnt++;
head->entry_cnt++; head->entry_cnt++;
set_nat_flag(ne, IS_DIRTY, true); set_nat_flag(ne, IS_DIRTY, true);
refresh_list:
if (nat_get_blkaddr(ne) == NEW_ADDR)
list_del_init(&ne->list);
else
list_move_tail(&ne->list, &head->entry_list);
} }
static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i, static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i,
...@@ -673,15 +678,11 @@ static void truncate_node(struct dnode_of_data *dn) ...@@ -673,15 +678,11 @@ static void truncate_node(struct dnode_of_data *dn)
struct node_info ni; struct node_info ni;
get_node_info(sbi, dn->nid, &ni); get_node_info(sbi, dn->nid, &ni);
if (dn->inode->i_blocks == 0) {
f2fs_bug_on(sbi, ni.blk_addr != NULL_ADDR);
goto invalidate;
}
f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR); f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR);
/* Deallocate node address */ /* Deallocate node address */
invalidate_blocks(sbi, ni.blk_addr); invalidate_blocks(sbi, ni.blk_addr);
dec_valid_node_count(sbi, dn->inode); dec_valid_node_count(sbi, dn->inode, dn->nid == dn->inode->i_ino);
set_node_addr(sbi, &ni, NULL_ADDR, false); set_node_addr(sbi, &ni, NULL_ADDR, false);
if (dn->nid == dn->inode->i_ino) { if (dn->nid == dn->inode->i_ino) {
...@@ -689,7 +690,7 @@ static void truncate_node(struct dnode_of_data *dn) ...@@ -689,7 +690,7 @@ static void truncate_node(struct dnode_of_data *dn)
dec_valid_inode_count(sbi); dec_valid_inode_count(sbi);
f2fs_inode_synced(dn->inode); f2fs_inode_synced(dn->inode);
} }
invalidate:
clear_node_page_dirty(dn->node_page); clear_node_page_dirty(dn->node_page);
set_sbi_flag(sbi, SBI_IS_DIRTY); set_sbi_flag(sbi, SBI_IS_DIRTY);
...@@ -1006,7 +1007,7 @@ int remove_inode_page(struct inode *inode) ...@@ -1006,7 +1007,7 @@ int remove_inode_page(struct inode *inode)
/* 0 is possible, after f2fs_new_inode() has failed */ /* 0 is possible, after f2fs_new_inode() has failed */
f2fs_bug_on(F2FS_I_SB(inode), f2fs_bug_on(F2FS_I_SB(inode),
inode->i_blocks != 0 && inode->i_blocks != 1); inode->i_blocks != 0 && inode->i_blocks != 8);
/* will put inode & node pages */ /* will put inode & node pages */
truncate_node(&dn); truncate_node(&dn);
...@@ -1039,10 +1040,9 @@ struct page *new_node_page(struct dnode_of_data *dn, ...@@ -1039,10 +1040,9 @@ struct page *new_node_page(struct dnode_of_data *dn,
if (!page) if (!page)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (unlikely(!inc_valid_node_count(sbi, dn->inode))) { if (unlikely((err = inc_valid_node_count(sbi, dn->inode, !ofs))))
err = -ENOSPC;
goto fail; goto fail;
}
#ifdef CONFIG_F2FS_CHECK_FS #ifdef CONFIG_F2FS_CHECK_FS
get_node_info(sbi, dn->nid, &new_ni); get_node_info(sbi, dn->nid, &new_ni);
f2fs_bug_on(sbi, new_ni.blk_addr != NULL_ADDR); f2fs_bug_on(sbi, new_ni.blk_addr != NULL_ADDR);
...@@ -1152,6 +1152,7 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid, ...@@ -1152,6 +1152,7 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid,
f2fs_put_page(page, 1); f2fs_put_page(page, 1);
return ERR_PTR(err); return ERR_PTR(err);
} else if (err == LOCKED_PAGE) { } else if (err == LOCKED_PAGE) {
err = 0;
goto page_hit; goto page_hit;
} }
...@@ -1165,15 +1166,22 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid, ...@@ -1165,15 +1166,22 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid,
goto repeat; goto repeat;
} }
if (unlikely(!PageUptodate(page))) if (unlikely(!PageUptodate(page))) {
err = -EIO;
goto out_err; goto out_err;
}
page_hit: page_hit:
if(unlikely(nid != nid_of_node(page))) { if(unlikely(nid != nid_of_node(page))) {
f2fs_bug_on(sbi, 1); f2fs_msg(sbi->sb, KERN_WARNING, "inconsistent node block, "
"nid:%lu, node_footer[nid:%u,ino:%u,ofs:%u,cpver:%llu,blkaddr:%u]",
nid, nid_of_node(page), ino_of_node(page),
ofs_of_node(page), cpver_of_node(page),
next_blkaddr_of_node(page));
ClearPageUptodate(page); ClearPageUptodate(page);
err = -EINVAL;
out_err: out_err:
f2fs_put_page(page, 1); f2fs_put_page(page, 1);
return ERR_PTR(-EIO); return ERR_PTR(err);
} }
return page; return page;
} }
...@@ -1373,15 +1381,15 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, ...@@ -1373,15 +1381,15 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
up_read(&sbi->node_write); up_read(&sbi->node_write);
if (wbc->for_reclaim) { if (wbc->for_reclaim) {
f2fs_submit_merged_bio_cond(sbi, page->mapping->host, 0, f2fs_submit_merged_write_cond(sbi, page->mapping->host, 0,
page->index, NODE, WRITE); page->index, NODE);
submitted = NULL; submitted = NULL;
} }
unlock_page(page); unlock_page(page);
if (unlikely(f2fs_cp_error(sbi))) { if (unlikely(f2fs_cp_error(sbi))) {
f2fs_submit_merged_bio(sbi, NODE, WRITE); f2fs_submit_merged_write(sbi, NODE);
submitted = NULL; submitted = NULL;
} }
if (submitted) if (submitted)
...@@ -1518,8 +1526,7 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, ...@@ -1518,8 +1526,7 @@ int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
} }
out: out:
if (last_idx != ULONG_MAX) if (last_idx != ULONG_MAX)
f2fs_submit_merged_bio_cond(sbi, NULL, ino, last_idx, f2fs_submit_merged_write_cond(sbi, NULL, ino, last_idx, NODE);
NODE, WRITE);
return ret ? -EIO: 0; return ret ? -EIO: 0;
} }
...@@ -1625,7 +1632,7 @@ int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc) ...@@ -1625,7 +1632,7 @@ int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc)
} }
out: out:
if (nwritten) if (nwritten)
f2fs_submit_merged_bio(sbi, NODE, WRITE); f2fs_submit_merged_write(sbi, NODE);
return ret; return ret;
} }
...@@ -1675,6 +1682,9 @@ static int f2fs_write_node_pages(struct address_space *mapping, ...@@ -1675,6 +1682,9 @@ static int f2fs_write_node_pages(struct address_space *mapping,
struct blk_plug plug; struct blk_plug plug;
long diff; long diff;
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
goto skip_write;
/* balancing f2fs's metadata in background */ /* balancing f2fs's metadata in background */
f2fs_balance_fs_bg(sbi); f2fs_balance_fs_bg(sbi);
...@@ -2192,14 +2202,14 @@ int recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr) ...@@ -2192,14 +2202,14 @@ int recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
get_node_info(sbi, prev_xnid, &ni); get_node_info(sbi, prev_xnid, &ni);
f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR); f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR);
invalidate_blocks(sbi, ni.blk_addr); invalidate_blocks(sbi, ni.blk_addr);
dec_valid_node_count(sbi, inode); dec_valid_node_count(sbi, inode, false);
set_node_addr(sbi, &ni, NULL_ADDR, false); set_node_addr(sbi, &ni, NULL_ADDR, false);
recover_xnid: recover_xnid:
/* 2: update xattr nid in inode */ /* 2: update xattr nid in inode */
remove_free_nid(sbi, new_xnid); remove_free_nid(sbi, new_xnid);
f2fs_i_xnid_write(inode, new_xnid); f2fs_i_xnid_write(inode, new_xnid);
if (unlikely(!inc_valid_node_count(sbi, inode))) if (unlikely(inc_valid_node_count(sbi, inode, false)))
f2fs_bug_on(sbi, 1); f2fs_bug_on(sbi, 1);
update_inode_page(inode); update_inode_page(inode);
...@@ -2257,7 +2267,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) ...@@ -2257,7 +2267,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
new_ni = old_ni; new_ni = old_ni;
new_ni.ino = ino; new_ni.ino = ino;
if (unlikely(!inc_valid_node_count(sbi, NULL))) if (unlikely(inc_valid_node_count(sbi, NULL, true)))
WARN_ON(1); WARN_ON(1);
set_node_addr(sbi, &new_ni, NEW_ADDR, false); set_node_addr(sbi, &new_ni, NEW_ADDR, false);
inc_valid_inode_count(sbi); inc_valid_inode_count(sbi);
...@@ -2424,8 +2434,7 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, ...@@ -2424,8 +2434,7 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
nid_t nid = nat_get_nid(ne); nid_t nid = nat_get_nid(ne);
int offset; int offset;
if (nat_get_blkaddr(ne) == NEW_ADDR) f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR);
continue;
if (to_journal) { if (to_journal) {
offset = lookup_journal_in_cursum(journal, offset = lookup_journal_in_cursum(journal,
...@@ -2553,7 +2562,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) ...@@ -2553,7 +2562,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
return 0; return 0;
} }
inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi) static inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi)
{ {
struct f2fs_nm_info *nm_i = NM_I(sbi); struct f2fs_nm_info *nm_i = NM_I(sbi);
unsigned int i = 0; unsigned int i = 0;
......
...@@ -224,11 +224,7 @@ static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi, ...@@ -224,11 +224,7 @@ static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi,
struct f2fs_nm_info *nm_i = NM_I(sbi); struct f2fs_nm_info *nm_i = NM_I(sbi);
block_addr -= nm_i->nat_blkaddr; block_addr -= nm_i->nat_blkaddr;
if ((block_addr >> sbi->log_blocks_per_seg) % 2) block_addr ^= 1 << sbi->log_blocks_per_seg;
block_addr -= sbi->blocks_per_seg;
else
block_addr += sbi->blocks_per_seg;
return block_addr + nm_i->nat_blkaddr; return block_addr + nm_i->nat_blkaddr;
} }
......
This diff is collapsed.
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
#define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA) #define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
#define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE) #define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
#define IS_CURSEG(sbi, seg) \ #define IS_CURSEG(sbi, seg) \
(((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \ (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \ ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
......
This diff is collapsed.
This diff is collapsed.
...@@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE); ...@@ -19,6 +19,9 @@ TRACE_DEFINE_ENUM(INMEM_INVALIDATE);
TRACE_DEFINE_ENUM(INMEM_REVOKE); TRACE_DEFINE_ENUM(INMEM_REVOKE);
TRACE_DEFINE_ENUM(IPU); TRACE_DEFINE_ENUM(IPU);
TRACE_DEFINE_ENUM(OPU); TRACE_DEFINE_ENUM(OPU);
TRACE_DEFINE_ENUM(HOT);
TRACE_DEFINE_ENUM(WARM);
TRACE_DEFINE_ENUM(COLD);
TRACE_DEFINE_ENUM(CURSEG_HOT_DATA); TRACE_DEFINE_ENUM(CURSEG_HOT_DATA);
TRACE_DEFINE_ENUM(CURSEG_WARM_DATA); TRACE_DEFINE_ENUM(CURSEG_WARM_DATA);
TRACE_DEFINE_ENUM(CURSEG_COLD_DATA); TRACE_DEFINE_ENUM(CURSEG_COLD_DATA);
...@@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED); ...@@ -59,6 +62,12 @@ TRACE_DEFINE_ENUM(CP_TRIMMED);
{ IPU, "IN-PLACE" }, \ { IPU, "IN-PLACE" }, \
{ OPU, "OUT-OF-PLACE" }) { OPU, "OUT-OF-PLACE" })
#define show_block_temp(temp) \
__print_symbolic(temp, \
{ HOT, "HOT" }, \
{ WARM, "WARM" }, \
{ COLD, "COLD" })
#define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \ #define F2FS_OP_FLAGS (REQ_RAHEAD | REQ_SYNC | REQ_META | REQ_PRIO | \
REQ_PREFLUSH | REQ_FUA) REQ_PREFLUSH | REQ_FUA)
#define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS) #define F2FS_BIO_FLAG_MASK(t) (t & F2FS_OP_FLAGS)
...@@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio, ...@@ -757,6 +766,7 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
__field(block_t, new_blkaddr) __field(block_t, new_blkaddr)
__field(int, op) __field(int, op)
__field(int, op_flags) __field(int, op_flags)
__field(int, temp)
__field(int, type) __field(int, type)
), ),
...@@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio, ...@@ -768,16 +778,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio,
__entry->new_blkaddr = fio->new_blkaddr; __entry->new_blkaddr = fio->new_blkaddr;
__entry->op = fio->op; __entry->op = fio->op;
__entry->op_flags = fio->op_flags; __entry->op_flags = fio->op_flags;
__entry->temp = fio->temp;
__entry->type = fio->type; __entry->type = fio->type;
), ),
TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, " TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
"oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s", "oldaddr = 0x%llx, newaddr = 0x%llx, rw = %s(%s), type = %s_%s",
show_dev_ino(__entry), show_dev_ino(__entry),
(unsigned long)__entry->index, (unsigned long)__entry->index,
(unsigned long long)__entry->old_blkaddr, (unsigned long long)__entry->old_blkaddr,
(unsigned long long)__entry->new_blkaddr, (unsigned long long)__entry->new_blkaddr,
show_bio_type(__entry->op, __entry->op_flags), show_bio_type(__entry->op, __entry->op_flags),
show_block_temp(__entry->temp),
show_block_type(__entry->type)) show_block_type(__entry->type))
); );
...@@ -790,7 +802,7 @@ DEFINE_EVENT_CONDITION(f2fs__submit_page_bio, f2fs_submit_page_bio, ...@@ -790,7 +802,7 @@ DEFINE_EVENT_CONDITION(f2fs__submit_page_bio, f2fs_submit_page_bio,
TP_CONDITION(page->mapping) TP_CONDITION(page->mapping)
); );
DEFINE_EVENT_CONDITION(f2fs__submit_page_bio, f2fs_submit_page_mbio, DEFINE_EVENT_CONDITION(f2fs__submit_page_bio, f2fs_submit_page_write,
TP_PROTO(struct page *page, struct f2fs_io_info *fio), TP_PROTO(struct page *page, struct f2fs_io_info *fio),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment