Skip to content

Commit

Permalink
Merge tag 'f2fs-for-5.1' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jaegeuk/f2fs

Pull f2fs updates from Jaegeuk Kim:
 "We've continued mainly to fix bugs in this round, as f2fs has been
  shipped in more devices. Especially, we've focused on stabilizing
  checkpoint=disable feature, and provided some interfaces for QA.

  Enhancements:
   - expose FS_NOCOW_FL for pin_file
   - run discard jobs at unmount time with timeout
   - tune discarding thread to avoid idling which consumes power
   - some checking codes to address vulnerabilities
   - give random value to i_generation
   - shutdown with more flags for QA

  Bug fixes:
   - clean up stale objects when mount is failed along with
     checkpoint=disable
   - fix system being stuck due to wrong count by atomic writes
   - handle some corrupted disk cases
   - fix a deadlock in f2fs_read_inline_dir

  We've also added some minor build error fixes and clean-up patches"

* tag 'f2fs-for-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (53 commits)
  f2fs: set pin_file under CAP_SYS_ADMIN
  f2fs: fix to avoid deadlock in f2fs_read_inline_dir()
  f2fs: fix to adapt small inline xattr space in __find_inline_xattr()
  f2fs: fix to do sanity check with inode.i_inline_xattr_size
  f2fs: give some messages for inline_xattr_size
  f2fs: don't trigger read IO for beyond EOF page
  f2fs: fix to add refcount once page is tagged PG_private
  f2fs: remove wrong comment in f2fs_invalidate_page()
  f2fs: fix to use kvfree instead of kzfree
  f2fs: print more parameters in trace_f2fs_map_blocks
  f2fs: trace f2fs_ioc_shutdown
  f2fs: fix to avoid deadlock of atomic file operations
  f2fs: fix to dirty inode for i_mode recovery
  f2fs: give random value to i_generation
  f2fs: no need to take page lock in readdir
  f2fs: fix to update iostat correctly in IPU path
  f2fs: fix encrypted page memory leak
  f2fs: make fault injection covering __submit_flush_wait()
  f2fs: fix to retry fill_super only if recovery failed
  f2fs: silence VM_WARN_ON_ONCE in mempool_alloc
  ...
  • Loading branch information
torvalds committed Mar 15, 2019
2 parents f91f2ee + aff7b62 commit 5160bcc
Show file tree
Hide file tree
Showing 22 changed files with 424 additions and 185 deletions.
7 changes: 7 additions & 0 deletions Documentation/ABI/testing/sysfs-fs-f2fs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ Description:
The unit size is one block, now only support configuring in range
of [1, 512].

What: /sys/fs/f2fs/<disk>/umount_discard_timeout
Date: January 2019
Contact: "Jaegeuk Kim" <[email protected]>
Description:
Set timeout to issue discard commands during umount.
Default: 5 secs

What: /sys/fs/f2fs/<disk>/max_victim_search
Date: January 2014
Contact: "Jaegeuk Kim" <[email protected]>
Expand Down
2 changes: 2 additions & 0 deletions Documentation/filesystems/f2fs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ disable_ext_identify Disable the extension list configured by mkfs, so f2fs
does not aware of cold files such as media files.
inline_xattr Enable the inline xattrs feature.
noinline_xattr Disable the inline xattrs feature.
inline_xattr_size=%u Support configuring inline xattr size, it depends on
flexible inline xattr feature.
inline_data Enable the inline data feature: New created small(<~3.4k)
files can be written into inode block.
inline_dentry Enable the inline dir feature: data in new created
Expand Down
20 changes: 14 additions & 6 deletions fs/f2fs/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,9 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
goto skip_write;

/* collect a number of dirty meta pages and write together */
if (wbc->for_kupdate ||
get_pages(sbi, F2FS_DIRTY_META) < nr_pages_to_skip(sbi, META))
if (wbc->sync_mode != WB_SYNC_ALL &&
get_pages(sbi, F2FS_DIRTY_META) <
nr_pages_to_skip(sbi, META))
goto skip_write;

/* if locked failed, cp will flush dirty pages instead */
Expand Down Expand Up @@ -405,7 +406,7 @@ static int f2fs_set_meta_page_dirty(struct page *page)
if (!PageDirty(page)) {
__set_page_dirty_nobuffers(page);
inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
SetPagePrivate(page);
f2fs_set_page_private(page, 0);
f2fs_trace_pid(page);
return 1;
}
Expand Down Expand Up @@ -956,7 +957,7 @@ void f2fs_update_dirty_page(struct inode *inode, struct page *page)
inode_inc_dirty_pages(inode);
spin_unlock(&sbi->inode_lock[type]);

SetPagePrivate(page);
f2fs_set_page_private(page, 0);
f2fs_trace_pid(page);
}

Expand Down Expand Up @@ -1259,10 +1260,17 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc)
else
__clear_ckpt_flags(ckpt, CP_DISABLED_FLAG);

if (is_sbi_flag_set(sbi, SBI_CP_DISABLED_QUICK))
__set_ckpt_flags(ckpt, CP_DISABLED_QUICK_FLAG);
else
__clear_ckpt_flags(ckpt, CP_DISABLED_QUICK_FLAG);

if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH))
__set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG);
else
__clear_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG);
/*
* TODO: we count on fsck.f2fs to clear this flag until we figure out
* missing cases which clear it incorrectly.
*/

if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR))
__set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG);
Expand Down
59 changes: 28 additions & 31 deletions fs/f2fs/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,10 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi,
for (; start < F2FS_IO_SIZE(sbi); start++) {
struct page *page =
mempool_alloc(sbi->write_io_dummy,
GFP_NOIO | __GFP_ZERO | __GFP_NOFAIL);
GFP_NOIO | __GFP_NOFAIL);
f2fs_bug_on(sbi, !page);

zero_user_segment(page, 0, PAGE_SIZE);
SetPagePrivate(page);
set_page_private(page, (unsigned long)DUMMY_WRITTEN_PAGE);
lock_page(page);
Expand Down Expand Up @@ -1553,6 +1554,9 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
if (last_block > last_block_in_file)
last_block = last_block_in_file;

/* just zeroing out page which is beyond EOF */
if (block_in_file >= last_block)
goto zero_out;
/*
* Map blocks using the previous result first.
*/
Expand All @@ -1565,16 +1569,11 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
* Then do more f2fs_map_blocks() calls until we are
* done with this page.
*/
map.m_flags = 0;

if (block_in_file < last_block) {
map.m_lblk = block_in_file;
map.m_len = last_block - block_in_file;
map.m_lblk = block_in_file;
map.m_len = last_block - block_in_file;

if (f2fs_map_blocks(inode, &map, 0,
F2FS_GET_BLOCK_DEFAULT))
goto set_error_page;
}
if (f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_DEFAULT))
goto set_error_page;
got_it:
if ((map.m_flags & F2FS_MAP_MAPPED)) {
block_nr = map.m_pblk + block_in_file - map.m_lblk;
Expand All @@ -1589,6 +1588,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
DATA_GENERIC))
goto set_error_page;
} else {
zero_out:
zero_user_segment(page, 0, PAGE_SIZE);
if (!PageUptodate(page))
SetPageUptodate(page);
Expand Down Expand Up @@ -1863,8 +1863,13 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
if (fio->need_lock == LOCK_REQ)
f2fs_unlock_op(fio->sbi);
err = f2fs_inplace_write_data(fio);
if (err && PageWriteback(page))
end_page_writeback(page);
if (err) {
if (f2fs_encrypted_file(inode))
fscrypt_pullback_bio_page(&fio->encrypted_page,
true);
if (PageWriteback(page))
end_page_writeback(page);
}
trace_f2fs_do_write_data_page(fio->page, IPU);
set_inode_flag(inode, FI_UPDATE_WRITE);
return err;
Expand Down Expand Up @@ -2315,7 +2320,8 @@ static void f2fs_write_failed(struct address_space *mapping, loff_t to)
down_write(&F2FS_I(inode)->i_mmap_sem);

truncate_pagecache(inode, i_size);
f2fs_truncate_blocks(inode, i_size, true, true);
if (!IS_NOQUOTA(inode))
f2fs_truncate_blocks(inode, i_size, true);

up_write(&F2FS_I(inode)->i_mmap_sem);
up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
Expand Down Expand Up @@ -2585,14 +2591,11 @@ static void f2fs_dio_submit_bio(struct bio *bio, struct inode *inode,
{
struct f2fs_private_dio *dio;
bool write = (bio_op(bio) == REQ_OP_WRITE);
int err;

dio = f2fs_kzalloc(F2FS_I_SB(inode),
sizeof(struct f2fs_private_dio), GFP_NOFS);
if (!dio) {
err = -ENOMEM;
if (!dio)
goto out;
}

dio->inode = inode;
dio->orig_end_io = bio->bi_end_io;
Expand Down Expand Up @@ -2710,12 +2713,10 @@ void f2fs_invalidate_page(struct page *page, unsigned int offset,

clear_cold_data(page);

/* This is atomic written page, keep Private */
if (IS_ATOMIC_WRITTEN_PAGE(page))
return f2fs_drop_inmem_page(inode, page);

set_page_private(page, 0);
ClearPagePrivate(page);
f2fs_clear_page_private(page);
}

int f2fs_release_page(struct page *page, gfp_t wait)
Expand All @@ -2729,8 +2730,7 @@ int f2fs_release_page(struct page *page, gfp_t wait)
return 0;

clear_cold_data(page);
set_page_private(page, 0);
ClearPagePrivate(page);
f2fs_clear_page_private(page);
return 1;
}

Expand Down Expand Up @@ -2798,12 +2798,8 @@ int f2fs_migrate_page(struct address_space *mapping,
return -EAGAIN;
}

/*
* A reference is expected if PagePrivate set when move mapping,
* however F2FS breaks this for maintaining dirty page counts when
* truncating pages. So here adjusting the 'extra_count' make it work.
*/
extra_count = (atomic_written ? 1 : 0) - page_has_private(page);
/* one extra reference was held for atomic_write page */
extra_count = atomic_written ? 1 : 0;
rc = migrate_page_move_mapping(mapping, newpage,
page, mode, extra_count);
if (rc != MIGRATEPAGE_SUCCESS) {
Expand All @@ -2824,9 +2820,10 @@ int f2fs_migrate_page(struct address_space *mapping,
get_page(newpage);
}

if (PagePrivate(page))
SetPagePrivate(newpage);
set_page_private(newpage, page_private(page));
if (PagePrivate(page)) {
f2fs_set_page_private(newpage, page_private(page));
f2fs_clear_page_private(page);
}

if (mode != MIGRATE_SYNC_NO_COPY)
migrate_page_copy(newpage, page);
Expand Down
19 changes: 12 additions & 7 deletions fs/f2fs/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,10 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->free_secs = free_sections(sbi);
si->prefree_count = prefree_segments(sbi);
si->dirty_count = dirty_segments(sbi);
si->node_pages = NODE_MAPPING(sbi)->nrpages;
si->meta_pages = META_MAPPING(sbi)->nrpages;
if (sbi->node_inode)
si->node_pages = NODE_MAPPING(sbi)->nrpages;
if (sbi->meta_inode)
si->meta_pages = META_MAPPING(sbi)->nrpages;
si->nats = NM_I(sbi)->nat_cnt;
si->dirty_nats = NM_I(sbi)->dirty_nat_cnt;
si->sits = MAIN_SEGS(sbi);
Expand Down Expand Up @@ -175,7 +177,6 @@ static void update_sit_info(struct f2fs_sb_info *sbi)
static void update_mem_info(struct f2fs_sb_info *sbi)
{
struct f2fs_stat_info *si = F2FS_STAT(sbi);
unsigned npages;
int i;

if (si->base_mem)
Expand Down Expand Up @@ -258,10 +259,14 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
sizeof(struct extent_node);

si->page_mem = 0;
npages = NODE_MAPPING(sbi)->nrpages;
si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
npages = META_MAPPING(sbi)->nrpages;
si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
if (sbi->node_inode) {
unsigned npages = NODE_MAPPING(sbi)->nrpages;
si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
}
if (sbi->meta_inode) {
unsigned npages = META_MAPPING(sbi)->nrpages;
si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
}
}

static int stat_show(struct seq_file *s, void *v)
Expand Down
15 changes: 10 additions & 5 deletions fs/f2fs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
!f2fs_truncate_hole(dir, page->index, page->index + 1)) {
f2fs_clear_page_cache_dirty_tag(page);
clear_page_dirty_for_io(page);
ClearPagePrivate(page);
f2fs_clear_page_private(page);
ClearPageUptodate(page);
clear_cold_data(page);
inode_dec_dirty_pages(dir);
Expand Down Expand Up @@ -800,6 +800,10 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
if (de->name_len == 0) {
bit_pos++;
ctx->pos = start_pos + bit_pos;
printk_ratelimited(
"%s, invalid namelen(0), ino:%u, run fsck to fix.",
KERN_WARNING, le32_to_cpu(de->ino));
set_sbi_flag(sbi, SBI_NEED_FSCK);
continue;
}

Expand All @@ -810,7 +814,8 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,

/* check memory boundary before moving forward */
bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
if (unlikely(bit_pos > d->max)) {
if (unlikely(bit_pos > d->max ||
le16_to_cpu(de->name_len) > F2FS_NAME_LEN)) {
f2fs_msg(sbi->sb, KERN_WARNING,
"%s: corrupted namelen=%d, run fsck to fix.",
__func__, le16_to_cpu(de->name_len));
Expand Down Expand Up @@ -891,7 +896,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
page_cache_sync_readahead(inode->i_mapping, ra, file, n,
min(npages - n, (pgoff_t)MAX_DIR_RA_PAGES));

dentry_page = f2fs_get_lock_data_page(inode, n, false);
dentry_page = f2fs_find_data_page(inode, n);
if (IS_ERR(dentry_page)) {
err = PTR_ERR(dentry_page);
if (err == -ENOENT) {
Expand All @@ -909,11 +914,11 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
err = f2fs_fill_dentries(ctx, &d,
n * NR_DENTRY_IN_BLOCK, &fstr);
if (err) {
f2fs_put_page(dentry_page, 1);
f2fs_put_page(dentry_page, 0);
break;
}

f2fs_put_page(dentry_page, 1);
f2fs_put_page(dentry_page, 0);
}
out_free:
fscrypt_fname_free_buffer(&fstr);
Expand Down
2 changes: 1 addition & 1 deletion fs/f2fs/extent_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ static void f2fs_update_extent_tree_range(struct inode *inode,
unsigned int end = fofs + len;
unsigned int pos = (unsigned int)fofs;
bool updated = false;
bool leftmost;
bool leftmost = false;

if (!et)
return;
Expand Down
Loading

0 comments on commit 5160bcc

Please sign in to comment.