Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd1d1399 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents a9986464 29e59c14
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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
@@ -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
================================================================================
+8 −0
Original line number Diff line number Diff line
@@ -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.
+19 −17
Original line number Diff line number Diff line
@@ -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);
@@ -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)
@@ -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)) {
@@ -276,10 +277,11 @@ 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);
		error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl, ipage);
		if (error)
			goto cleanup;
	}
@@ -287,8 +289,7 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir)
	if (error < 0)
		return error;
	if (error > 0)
			error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
	}
		error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, ipage);
cleanup:
	posix_acl_release(acl);
	return error;
@@ -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;
}
@@ -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);
+5 −4
Original line number Diff line number Diff line
@@ -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
@@ -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;
}
+38 −37
Original line number Diff line number Diff line
@@ -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++;
@@ -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);
@@ -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);
@@ -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);
}
@@ -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 */
@@ -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;
		}
@@ -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 */
@@ -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;

@@ -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;
}

@@ -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;
}

@@ -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);

@@ -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);

@@ -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;
		}
	}
@@ -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;
	}
@@ -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)
@@ -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);
Loading