Skip to content

Commit

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

Pull f2fs updates from Jaegeuk Kim:
 "This patch-set includes the following major enhancement patches.
   - add a sysfs to control reclaiming free segments
   - enhance the f2fs global lock procedures
   - enhance the victim selection flow
   - wait for selected node blocks during fsync
   - add some tracepoints
   - add a config to remove abundant BUG_ONs

  The other bug fixes are as follows.
   - fix deadlock on acl operations
   - fix some bugs with respect to orphan inodes

  And, there are a bunch of cleanups"

* tag 'for-f2fs-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (42 commits)
  f2fs: issue more large discard command
  f2fs: fix memory leak after kobject init failed in fill_super
  f2fs: cleanup waiting routine for writeback pages in cp
  f2fs: avoid to use a NULL point in destroy_segment_manager
  f2fs: remove unnecessary TestClearPageError when wait pages writeback
  f2fs: update f2fs document
  f2fs: avoid to wait all the node blocks during fsync
  f2fs: check all ones or zeros bitmap with bitops for better mount performance
  f2fs: change the method of calculating the number summary blocks
  f2fs: fix calculating incorrect free size when update xattr in __f2fs_setxattr
  f2fs: add an option to avoid unnecessary BUG_ONs
  f2fs: introduce CONFIG_F2FS_CHECK_FS for BUG_ON control
  f2fs: fix a deadlock during init_acl procedure
  f2fs: clean up acl flow for better readability
  f2fs: remove unnecessary segment bitmap updates
  f2fs: add tracepoint for vm_page_mkwrite
  f2fs: add tracepoint for set_page_dirty
  f2fs: remove redundant set_page_dirty from write_compacted_summaries
  f2fs: add reclaiming control by sysfs
  f2fs: introduce f2fs_balance_fs_bg for some background jobs
  ...
  • Loading branch information
Linus Torvalds committed Nov 13, 2013
2 parents a998646 + 29e59c1 commit dd1d139
Show file tree
Hide file tree
Showing 19 changed files with 651 additions and 412 deletions.
7 changes: 7 additions & 0 deletions Documentation/filesystems/f2fs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ active_logs=%u Support configuring the number of active logs. In the
Default number is 6.
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.

================================================================================
DEBUGFS ENTRIES
Expand Down Expand Up @@ -164,6 +165,12 @@ Files in /sys/fs/f2fs/<devname>
gc_idle = 1 will select the Cost Benefit approach
& setting gc_idle = 2 will select the greedy aproach.

reclaim_segments This parameter controls the number of prefree
segments to be reclaimed. If the number of prefree
segments is larger than this number, f2fs tries to
conduct checkpoint to reclaim the prefree segments
to free segments. By default, 100 segments, 200MB.

================================================================================
USAGE
================================================================================
Expand Down
8 changes: 8 additions & 0 deletions fs/f2fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,11 @@ config F2FS_FS_SECURITY
the extended attribute support in advance.

If you are not using a security module, say N.

config F2FS_CHECK_FS
bool "F2FS consistency checking feature"
depends on F2FS_FS
help
Enables BUG_ONs which check the file system consistency in runtime.

If you want to improve the performance, say N.
36 changes: 19 additions & 17 deletions fs/f2fs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
return acl;
}

static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
static int f2fs_set_acl(struct inode *inode, int type,
struct posix_acl *acl, struct page *ipage)
{
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
struct f2fs_inode_info *fi = F2FS_I(inode);
Expand Down Expand Up @@ -250,7 +251,7 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
}
}

error = f2fs_setxattr(inode, name_index, "", value, size, NULL);
error = f2fs_setxattr(inode, name_index, "", value, size, ipage);

kfree(value);
if (!error)
Expand All @@ -260,10 +261,10 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
return error;
}

int f2fs_init_acl(struct inode *inode, struct inode *dir)
int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage)
{
struct posix_acl *acl = NULL;
struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
struct posix_acl *acl = NULL;
int error = 0;

if (!S_ISLNK(inode->i_mode)) {
Expand All @@ -276,19 +277,19 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir)
inode->i_mode &= ~current_umask();
}

if (test_opt(sbi, POSIX_ACL) && acl) {
if (!test_opt(sbi, POSIX_ACL) || !acl)
goto cleanup;

if (S_ISDIR(inode->i_mode)) {
error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
if (error)
goto cleanup;
}
error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
if (error < 0)
return error;
if (error > 0)
error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
if (S_ISDIR(inode->i_mode)) {
error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl, ipage);
if (error)
goto cleanup;
}
error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
if (error < 0)
return error;
if (error > 0)
error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, ipage);
cleanup:
posix_acl_release(acl);
return error;
Expand All @@ -313,7 +314,8 @@ int f2fs_acl_chmod(struct inode *inode)
error = posix_acl_chmod(&acl, GFP_KERNEL, mode);
if (error)
return error;
error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);

error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, NULL);
posix_acl_release(acl);
return error;
}
Expand Down Expand Up @@ -388,7 +390,7 @@ static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name,
acl = NULL;
}

error = f2fs_set_acl(inode, type, acl);
error = f2fs_set_acl(inode, type, acl, NULL);

release_and_out:
posix_acl_release(acl);
Expand Down
9 changes: 5 additions & 4 deletions fs/f2fs/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ struct f2fs_acl_header {

#ifdef CONFIG_F2FS_FS_POSIX_ACL

extern struct posix_acl *f2fs_get_acl(struct inode *inode, int type);
extern int f2fs_acl_chmod(struct inode *inode);
extern int f2fs_init_acl(struct inode *inode, struct inode *dir);
extern struct posix_acl *f2fs_get_acl(struct inode *, int);
extern int f2fs_acl_chmod(struct inode *);
extern int f2fs_init_acl(struct inode *, struct inode *, struct page *);
#else
#define f2fs_check_acl NULL
#define f2fs_get_acl NULL
Expand All @@ -49,7 +49,8 @@ static inline int f2fs_acl_chmod(struct inode *inode)
return 0;
}

static inline int f2fs_init_acl(struct inode *inode, struct inode *dir)
static inline int f2fs_init_acl(struct inode *inode, struct inode *dir,
struct page *page)
{
return 0;
}
Expand Down
75 changes: 38 additions & 37 deletions fs/f2fs/checkpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static int f2fs_write_meta_page(struct page *page,
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);

/* Should not write any meta pages, if any IO error was occurred */
if (wbc->for_reclaim ||
if (wbc->for_reclaim || sbi->por_doing ||
is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)) {
dec_page_count(sbi, F2FS_DIRTY_META);
wbc->pages_skipped++;
Expand Down Expand Up @@ -142,8 +142,8 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
for (i = 0; i < nr_pages; i++) {
struct page *page = pvec.pages[i];
lock_page(page);
BUG_ON(page->mapping != mapping);
BUG_ON(!PageDirty(page));
f2fs_bug_on(page->mapping != mapping);
f2fs_bug_on(!PageDirty(page));
clear_page_dirty_for_io(page);
if (f2fs_write_meta_page(page, &wbc)) {
unlock_page(page);
Expand All @@ -167,6 +167,8 @@ static int f2fs_set_meta_page_dirty(struct page *page)
struct address_space *mapping = page->mapping;
struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);

trace_f2fs_set_page_dirty(page, META);

SetPageUptodate(page);
if (!PageDirty(page)) {
__set_page_dirty_nobuffers(page);
Expand Down Expand Up @@ -206,6 +208,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)
void release_orphan_inode(struct f2fs_sb_info *sbi)
{
mutex_lock(&sbi->orphan_inode_mutex);
f2fs_bug_on(sbi->n_orphans == 0);
sbi->n_orphans--;
mutex_unlock(&sbi->orphan_inode_mutex);
}
Expand All @@ -225,12 +228,8 @@ void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
break;
orphan = NULL;
}
retry:
new = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
if (!new) {
cond_resched();
goto retry;
}

new = f2fs_kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
new->ino = ino;

/* add new_oentry into list which is sorted by inode number */
Expand All @@ -253,6 +252,7 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
if (orphan->ino == ino) {
list_del(&orphan->list);
kmem_cache_free(orphan_entry_slab, orphan);
f2fs_bug_on(sbi->n_orphans == 0);
sbi->n_orphans--;
break;
}
Expand All @@ -263,7 +263,7 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
{
struct inode *inode = f2fs_iget(sbi->sb, ino);
BUG_ON(IS_ERR(inode));
f2fs_bug_on(IS_ERR(inode));
clear_nlink(inode);

/* truncate all the data during iput */
Expand All @@ -277,7 +277,7 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
return 0;

sbi->por_doing = 1;
sbi->por_doing = true;
start_blk = __start_cp_addr(sbi) + 1;
orphan_blkaddr = __start_sum_addr(sbi) - 1;

Expand All @@ -294,7 +294,7 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
}
/* clear Orphan Flag */
clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG);
sbi->por_doing = 0;
sbi->por_doing = false;
return 0;
}

Expand Down Expand Up @@ -469,9 +469,7 @@ static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
return -EEXIST;
}
list_add_tail(&new->list, head);
#ifdef CONFIG_F2FS_STAT_FS
sbi->n_dirty_dirs++;
#endif
stat_inc_dirty_dir(sbi);
return 0;
}

Expand All @@ -482,12 +480,8 @@ void set_dirty_dir_page(struct inode *inode, struct page *page)

if (!S_ISDIR(inode->i_mode))
return;
retry:
new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
if (!new) {
cond_resched();
goto retry;
}

new = f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
new->inode = inode;
INIT_LIST_HEAD(&new->list);

Expand All @@ -504,13 +498,9 @@ void set_dirty_dir_page(struct inode *inode, struct page *page)
void add_dirty_dir_inode(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
struct dir_inode_entry *new;
retry:
new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
if (!new) {
cond_resched();
goto retry;
}
struct dir_inode_entry *new =
f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS);

new->inode = inode;
INIT_LIST_HEAD(&new->list);

Expand Down Expand Up @@ -541,9 +531,7 @@ void remove_dirty_dir_inode(struct inode *inode)
if (entry->inode == inode) {
list_del(&entry->list);
kmem_cache_free(inode_entry_slab, entry);
#ifdef CONFIG_F2FS_STAT_FS
sbi->n_dirty_dirs--;
#endif
stat_dec_dirty_dir(sbi);
break;
}
}
Expand Down Expand Up @@ -617,11 +605,10 @@ static void block_operations(struct f2fs_sb_info *sbi)
blk_start_plug(&plug);

retry_flush_dents:
mutex_lock_all(sbi);

f2fs_lock_all(sbi);
/* write all the dirty dentry pages */
if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
mutex_unlock_all(sbi);
f2fs_unlock_all(sbi);
sync_dirty_dir_inodes(sbi);
goto retry_flush_dents;
}
Expand All @@ -644,7 +631,22 @@ static void block_operations(struct f2fs_sb_info *sbi)
static void unblock_operations(struct f2fs_sb_info *sbi)
{
mutex_unlock(&sbi->node_write);
mutex_unlock_all(sbi);
f2fs_unlock_all(sbi);
}

static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
{
DEFINE_WAIT(wait);

for (;;) {
prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE);

if (!get_pages(sbi, F2FS_WRITEBACK))
break;

io_schedule();
}
finish_wait(&sbi->cp_wait, &wait);
}

static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
Expand Down Expand Up @@ -756,8 +758,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
f2fs_put_page(cp_page, 1);

/* wait for previous submitted node/meta pages writeback */
while (get_pages(sbi, F2FS_WRITEBACK))
congestion_wait(BLK_RW_ASYNC, HZ / 50);
wait_on_all_pages_writeback(sbi);

filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX);
filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX);
Expand Down
Loading

0 comments on commit dd1d139

Please sign in to comment.