Skip to content

Commit

Permalink
Merge tag 'for-f2fs-4.8' 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:
 "The major change in this version is mitigating cpu overheads on write
  paths by replacing redundant inode page updates with mark_inode_dirty
  calls.  And we tried to reduce lock contentions as well to improve
  filesystem scalability.  Other feature is setting F2FS automatically
  when detecting host-managed SMR.

  Enhancements:
   - ioctl to move a range of data between files
   - inject orphan inode errors
   - avoid flush commands congestion
   - support lazytime

  Bug fixes:
   - return proper results for some dentry operations
   - fix deadlock in add_link failure
   - disable extent_cache for fcollapse/finsert"

* tag 'for-f2fs-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (68 commits)
  f2fs: clean up coding style and redundancy
  f2fs: get victim segment again after new cp
  f2fs: handle error case with f2fs_bug_on
  f2fs: avoid data race when deciding checkpoin in f2fs_sync_file
  f2fs: support an ioctl to move a range of data blocks
  f2fs: fix to report error number of f2fs_find_entry
  f2fs: avoid memory allocation failure due to a long length
  f2fs: reset default idle interval value
  f2fs: use blk_plug in all the possible paths
  f2fs: fix to avoid data update racing between GC and DIO
  f2fs: add maximum prefree segments
  f2fs: disable extent_cache for fcollapse/finsert inodes
  f2fs: refactor __exchange_data_block for speed up
  f2fs: fix ERR_PTR returned by bio
  f2fs: avoid mark_inode_dirty
  f2fs: move i_size_write in f2fs_write_end
  f2fs: fix to avoid redundant discard during fstrim
  f2fs: avoid mismatching block range for discard
  f2fs: fix incorrect f_bfree calculation in ->statfs
  f2fs: use percpu_rw_semaphore
  ...
  • Loading branch information
Linus Torvalds committed Jul 27, 2016
2 parents 0e6acf0 + 5302fb0 commit 4fc29c1
Show file tree
Hide file tree
Showing 22 changed files with 1,387 additions and 750 deletions.
7 changes: 6 additions & 1 deletion Documentation/filesystems/f2fs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ background_gc=%s Turn on/off cleaning operations, namely garbage
disable_roll_forward Disable the roll-forward recovery routine
norecovery Disable the roll-forward recovery routine, mounted read-
only (i.e., -o ro,disable_roll_forward)
discard Issue discard/TRIM commands when a segment is cleaned.
discard/nodiscard Enable/disable real-time discard in f2fs, if discard is
enabled, f2fs will issue discard/TRIM commands when a
segment is cleaned.
no_heap Disable heap-style segment allocation which finds free
segments for data from the beginning of main area, while
for node from the end of main area.
Expand Down Expand Up @@ -151,6 +153,9 @@ noinline_data Disable the inline data feature, inline data feature is
enabled by default.
data_flush Enable data flushing before checkpoint in order to
persist data of regular and symlink.
mode=%s Control block allocation mode which supports "adaptive"
and "lfs". In "lfs" mode, there should be no random
writes towards main area.

================================================================================
DEBUGFS ENTRIES
Expand Down
9 changes: 5 additions & 4 deletions fs/f2fs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
static int __f2fs_set_acl(struct inode *inode, int type,
struct posix_acl *acl, struct page *ipage)
{
struct f2fs_inode_info *fi = F2FS_I(inode);
int name_index;
void *value = NULL;
size_t size = 0;
Expand All @@ -214,7 +213,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
error = posix_acl_equiv_mode(acl, &inode->i_mode);
if (error < 0)
return error;
set_acl_inode(fi, inode->i_mode);
set_acl_inode(inode, inode->i_mode);
if (error == 0)
acl = NULL;
}
Expand All @@ -233,7 +232,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
if (acl) {
value = f2fs_acl_to_disk(acl, &size);
if (IS_ERR(value)) {
clear_inode_flag(fi, FI_ACL_MODE);
clear_inode_flag(inode, FI_ACL_MODE);
return (int)PTR_ERR(value);
}
}
Expand All @@ -244,7 +243,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
if (!error)
set_cached_acl(inode, type, acl);

clear_inode_flag(fi, FI_ACL_MODE);
clear_inode_flag(inode, FI_ACL_MODE);
return error;
}

Expand Down Expand Up @@ -385,6 +384,8 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage,
if (error)
return error;

f2fs_mark_inode_dirty_sync(inode);

if (default_acl) {
error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl,
ipage);
Expand Down
2 changes: 1 addition & 1 deletion fs/f2fs/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct f2fs_acl_header {
#ifdef CONFIG_F2FS_FS_POSIX_ACL

extern struct posix_acl *f2fs_get_acl(struct inode *, int);
extern int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
extern int f2fs_set_acl(struct inode *, struct posix_acl *, int);
extern int f2fs_init_acl(struct inode *, struct inode *, struct page *,
struct page *);
#else
Expand Down
80 changes: 60 additions & 20 deletions fs/f2fs/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
goto repeat;
}
f2fs_wait_on_page_writeback(page, META, true);
SetPageUptodate(page);
if (!PageUptodate(page))
SetPageUptodate(page);
return page;
}

Expand Down Expand Up @@ -266,6 +267,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
struct writeback_control *wbc)
{
struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
struct blk_plug plug;
long diff, written;

/* collect a number of dirty meta pages and write together */
Expand All @@ -278,7 +280,9 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
/* if mounting is failed, skip writing node pages */
mutex_lock(&sbi->cp_mutex);
diff = nr_pages_to_write(sbi, META, wbc);
blk_start_plug(&plug);
written = sync_meta_pages(sbi, META, wbc->nr_to_write);
blk_finish_plug(&plug);
mutex_unlock(&sbi->cp_mutex);
wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff);
return 0;
Expand Down Expand Up @@ -366,9 +370,10 @@ static int f2fs_set_meta_page_dirty(struct page *page)
{
trace_f2fs_set_page_dirty(page, META);

SetPageUptodate(page);
if (!PageUptodate(page))
SetPageUptodate(page);
if (!PageDirty(page)) {
__set_page_dirty_nobuffers(page);
f2fs_set_page_dirty_nobuffers(page);
inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
SetPagePrivate(page);
f2fs_trace_pid(page);
Expand Down Expand Up @@ -510,10 +515,11 @@ void release_orphan_inode(struct f2fs_sb_info *sbi)
spin_unlock(&im->ino_lock);
}

void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
void add_orphan_inode(struct inode *inode)
{
/* add new orphan ino entry into list */
__add_ino_entry(sbi, ino, ORPHAN_INO);
__add_ino_entry(F2FS_I_SB(inode), inode->i_ino, ORPHAN_INO);
update_inode_page(inode);
}

void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
Expand Down Expand Up @@ -761,28 +767,25 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
static void __add_dirty_inode(struct inode *inode, enum inode_type type)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode_info *fi = F2FS_I(inode);
int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;

if (is_inode_flag_set(fi, flag))
if (is_inode_flag_set(inode, flag))
return;

set_inode_flag(fi, flag);
list_add_tail(&fi->dirty_list, &sbi->inode_list[type]);
set_inode_flag(inode, flag);
list_add_tail(&F2FS_I(inode)->dirty_list, &sbi->inode_list[type]);
stat_inc_dirty_inode(sbi, type);
}

static void __remove_dirty_inode(struct inode *inode, enum inode_type type)
{
struct f2fs_inode_info *fi = F2FS_I(inode);
int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;

if (get_dirty_pages(inode) ||
!is_inode_flag_set(F2FS_I(inode), flag))
if (get_dirty_pages(inode) || !is_inode_flag_set(inode, flag))
return;

list_del_init(&fi->dirty_list);
clear_inode_flag(fi, flag);
list_del_init(&F2FS_I(inode)->dirty_list);
clear_inode_flag(inode, flag);
stat_dec_dirty_inode(F2FS_I_SB(inode), type);
}

Expand All @@ -795,13 +798,12 @@ void update_dirty_page(struct inode *inode, struct page *page)
!S_ISLNK(inode->i_mode))
return;

if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH)) {
spin_lock(&sbi->inode_lock[type]);
spin_lock(&sbi->inode_lock[type]);
if (type != FILE_INODE || test_opt(sbi, DATA_FLUSH))
__add_dirty_inode(inode, type);
spin_unlock(&sbi->inode_lock[type]);
}

inode_inc_dirty_pages(inode);
spin_unlock(&sbi->inode_lock[type]);

SetPagePrivate(page);
f2fs_trace_pid(page);
}
Expand Down Expand Up @@ -864,6 +866,34 @@ int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
goto retry;
}

int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi)
{
struct list_head *head = &sbi->inode_list[DIRTY_META];
struct inode *inode;
struct f2fs_inode_info *fi;
s64 total = get_pages(sbi, F2FS_DIRTY_IMETA);

while (total--) {
if (unlikely(f2fs_cp_error(sbi)))
return -EIO;

spin_lock(&sbi->inode_lock[DIRTY_META]);
if (list_empty(head)) {
spin_unlock(&sbi->inode_lock[DIRTY_META]);
return 0;
}
fi = list_entry(head->next, struct f2fs_inode_info,
gdirty_list);
inode = igrab(&fi->vfs_inode);
spin_unlock(&sbi->inode_lock[DIRTY_META]);
if (inode) {
update_inode_page(inode);
iput(inode);
}
};
return 0;
}

/*
* Freeze all the FS-operations for checkpoint.
*/
Expand All @@ -890,6 +920,14 @@ static int block_operations(struct f2fs_sb_info *sbi)
goto retry_flush_dents;
}

if (get_pages(sbi, F2FS_DIRTY_IMETA)) {
f2fs_unlock_all(sbi);
err = f2fs_sync_inode_meta(sbi);
if (err)
goto out;
goto retry_flush_dents;
}

/*
* POR: we should ensure that there are no dirty node pages
* until finishing nat/sit flush.
Expand All @@ -914,6 +952,8 @@ static int block_operations(struct f2fs_sb_info *sbi)
static void unblock_operations(struct f2fs_sb_info *sbi)
{
up_write(&sbi->node_write);

build_free_nids(sbi);
f2fs_unlock_all(sbi);
}

Expand Down Expand Up @@ -954,7 +994,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
* This avoids to conduct wrong roll-forward operations and uses
* metapages, so should be called prior to sync_meta_pages below.
*/
if (discard_next_dnode(sbi, discard_blk))
if (!test_opt(sbi, LFS) && discard_next_dnode(sbi, discard_blk))
invalidate = true;

/* Flush all the NAT/SIT pages */
Expand Down
Loading

0 comments on commit 4fc29c1

Please sign in to comment.