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

Commit 0d90d638 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull f2fs updates from Jaegeuk Kim:
 "In this round, a couple of sysfs entries were introduced to tune the
  f2fs at runtime.

  In addition, f2fs starts to support inline_data and improves the
  read/write performance in some workloads by refactoring bio-related
  flows.

  This patch-set includes the following major enhancement patches.
   - support inline_data
   - refactor bio operations such as merge operations and rw type
     assignment
   - enhance the direct IO path
   - enhance bio operations
   - truncate a node page when it becomes obsolete
   - add sysfs entries: small_discards, max_victim_search, and
     in-place-update
   - add a sysfs entry to control max_victim_search

  The other bug fixes are as follows.
   - fix a bug in truncate_partial_nodes
   - avoid warnings during sparse and build process
   - fix error handling flows
   - fix potential bit overflows

  And, there are a bunch of cleanups"

* tag 'for-f2fs-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (95 commits)
  f2fs: drop obsolete node page when it is truncated
  f2fs: introduce NODE_MAPPING for code consistency
  f2fs: remove the orphan block page array
  f2fs: add help function META_MAPPING
  f2fs: move a branch for code redability
  f2fs: call mark_inode_dirty to flush dirty pages
  f2fs: clean checkpatch warnings
  f2fs: missing REQ_META and REQ_PRIO when sync_meta_pages(META_FLUSH)
  f2fs: avoid f2fs_balance_fs call during pageout
  f2fs: add delimiter to seperate name and value in debug phrase
  f2fs: use spinlock rather than mutex for better speed
  f2fs: move alloc new orphan node out of lock protection region
  f2fs: move grabing orphan pages out of protection region
  f2fs: remove the needless parameter of f2fs_wait_on_page_writeback
  f2fs: update documents and a MAINTAINERS entry
  f2fs: add a sysfs entry to control max_victim_search
  f2fs: improve write performance under frequent fsync calls
  f2fs: avoid to read inline data except first page
  f2fs: avoid to left uninitialized data in page when read inline data
  f2fs: fix truncate_partial_nodes bug
  ...
parents 1d32bdaf bf39c00a
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -24,3 +24,34 @@ Date: July 2013
Contact:	"Namjae Jeon" <namjae.jeon@samsung.com>
Description:
		 Controls the victim selection policy for garbage collection.

What:		/sys/fs/f2fs/<disk>/reclaim_segments
Date:		October 2013
Contact:	"Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Description:
		 Controls the issue rate of segment discard commands.

What:		/sys/fs/f2fs/<disk>/ipu_policy
Date:		November 2013
Contact:	"Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Description:
		 Controls the in-place-update policy.

What:		/sys/fs/f2fs/<disk>/min_ipu_util
Date:		November 2013
Contact:	"Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Description:
		 Controls the FS utilization condition for the in-place-update
		 policies.

What:		/sys/fs/f2fs/<disk>/max_small_discards
Date:		November 2013
Contact:	"Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Description:
		 Controls the issue rate of small discard commands.

What:		/sys/fs/f2fs/<disk>/max_victim_search
Date:		January 2014
Contact:	"Jaegeuk Kim" <jaegeuk.kim@samsung.com>
Description:
		 Controls the number of trials to find a victim segment.
+24 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ active_logs=%u Support configuring the number of active logs. In the
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.
inline_data            Enable the inline data feature: New created small(<~3.4k)
                       files can be written into inode block.

================================================================================
DEBUGFS ENTRIES
@@ -171,6 +173,28 @@ Files in /sys/fs/f2fs/<devname>
			      conduct checkpoint to reclaim the prefree segments
			      to free segments. By default, 100 segments, 200MB.

 max_small_discards	      This parameter controls the number of discard
			      commands that consist small blocks less than 2MB.
			      The candidates to be discarded are cached until
			      checkpoint is triggered, and issued during the
			      checkpoint. By default, it is disabled with 0.

 ipu_policy                   This parameter controls the policy of in-place
                              updates in f2fs. There are five policies:
                               0: F2FS_IPU_FORCE, 1: F2FS_IPU_SSR,
                               2: F2FS_IPU_UTIL,  3: F2FS_IPU_SSR_UTIL,
                               4: F2FS_IPU_DISABLE.

 min_ipu_util                 This parameter controls the threshold to trigger
                              in-place-updates. The number indicates percentage
                              of the filesystem utilization, and used by
                              F2FS_IPU_UTIL and F2FS_IPU_SSR_UTIL policies.

 max_victim_search	      This parameter controls the number of trials to
			      find a victim segment when conducting SSR and
			      cleaning operations. The default value is 4096
			      which covers 8GB block address range.

================================================================================
USAGE
================================================================================
+1 −0
Original line number Diff line number Diff line
@@ -3634,6 +3634,7 @@ W: http://en.wikipedia.org/wiki/F2FS
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
S:	Maintained
F:	Documentation/filesystems/f2fs.txt
F:	Documentation/ABI/testing/sysfs-fs-f2fs
F:	fs/f2fs/
F:	include/linux/f2fs_fs.h

+1 −1
Original line number Diff line number Diff line
obj-$(CONFIG_F2FS_FS) += f2fs.o

f2fs-y		:= dir.o file.o inode.o namei.o hash.o super.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-$(CONFIG_F2FS_STAT_FS) += debug.o
f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
+107 −88
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ static struct kmem_cache *inode_entry_slab;
 */
struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
{
	struct address_space *mapping = sbi->meta_inode->i_mapping;
	struct address_space *mapping = META_MAPPING(sbi);
	struct page *page = NULL;
repeat:
	page = grab_cache_page(mapping, index);
@@ -50,7 +50,7 @@ struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
 */
struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
{
	struct address_space *mapping = sbi->meta_inode->i_mapping;
	struct address_space *mapping = META_MAPPING(sbi);
	struct page *page;
repeat:
	page = grab_cache_page(mapping, index);
@@ -61,11 +61,12 @@ struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
	if (PageUptodate(page))
		goto out;

	if (f2fs_readpage(sbi, page, index, READ_SYNC))
	if (f2fs_submit_page_bio(sbi, page, index,
				READ_SYNC | REQ_META | REQ_PRIO))
		goto repeat;

	lock_page(page);
	if (page->mapping != mapping) {
	if (unlikely(page->mapping != mapping)) {
		f2fs_put_page(page, 1);
		goto repeat;
	}
@@ -81,13 +82,12 @@ 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 || sbi->por_doing ||
			is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)) {
		dec_page_count(sbi, F2FS_DIRTY_META);
		wbc->pages_skipped++;
		set_page_dirty(page);
		return AOP_WRITEPAGE_ACTIVATE;
	}
	if (unlikely(sbi->por_doing ||
			is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
		goto redirty_out;

	if (wbc->for_reclaim)
		goto redirty_out;

	wait_on_page_writeback(page);

@@ -95,24 +95,31 @@ static int f2fs_write_meta_page(struct page *page,
	dec_page_count(sbi, F2FS_DIRTY_META);
	unlock_page(page);
	return 0;

redirty_out:
	dec_page_count(sbi, F2FS_DIRTY_META);
	wbc->pages_skipped++;
	set_page_dirty(page);
	return AOP_WRITEPAGE_ACTIVATE;
}

static int f2fs_write_meta_pages(struct address_space *mapping,
				struct writeback_control *wbc)
{
	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
	struct block_device *bdev = sbi->sb->s_bdev;
	int nrpages = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
	long written;

	if (wbc->for_kupdate)
		return 0;

	if (get_pages(sbi, F2FS_DIRTY_META) == 0)
	/* collect a number of dirty meta pages and write together */
	if (get_pages(sbi, F2FS_DIRTY_META) < nrpages)
		return 0;

	/* if mounting is failed, skip writing node pages */
	mutex_lock(&sbi->cp_mutex);
	written = sync_meta_pages(sbi, META, bio_get_nr_vecs(bdev));
	written = sync_meta_pages(sbi, META, nrpages);
	mutex_unlock(&sbi->cp_mutex);
	wbc->nr_to_write -= written;
	return 0;
@@ -121,7 +128,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
						long nr_to_write)
{
	struct address_space *mapping = sbi->meta_inode->i_mapping;
	struct address_space *mapping = META_MAPPING(sbi);
	pgoff_t index = 0, end = LONG_MAX;
	struct pagevec pvec;
	long nwritten = 0;
@@ -136,7 +143,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
				PAGECACHE_TAG_DIRTY,
				min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
		if (nr_pages == 0)
		if (unlikely(nr_pages == 0))
			break;

		for (i = 0; i < nr_pages; i++) {
@@ -149,7 +156,8 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
				unlock_page(page);
				break;
			}
			if (nwritten++ >= nr_to_write)
			nwritten++;
			if (unlikely(nwritten >= nr_to_write))
				break;
		}
		pagevec_release(&pvec);
@@ -157,7 +165,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
	}

	if (nwritten)
		f2fs_submit_bio(sbi, type, nr_to_write == LONG_MAX);
		f2fs_submit_merged_bio(sbi, type, WRITE);

	return nwritten;
}
@@ -186,31 +194,24 @@ const struct address_space_operations f2fs_meta_aops = {

int acquire_orphan_inode(struct f2fs_sb_info *sbi)
{
	unsigned int max_orphans;
	int err = 0;

	/*
	 * considering 512 blocks in a segment 5 blocks are needed for cp
	 * and log segment summaries. Remaining blocks are used to keep
	 * orphan entries with the limitation one reserved segment
	 * for cp pack we can have max 1020*507 orphan entries
	 */
	max_orphans = (sbi->blocks_per_seg - 5) * F2FS_ORPHANS_PER_BLOCK;
	mutex_lock(&sbi->orphan_inode_mutex);
	if (sbi->n_orphans >= max_orphans)
	spin_lock(&sbi->orphan_inode_lock);
	if (unlikely(sbi->n_orphans >= sbi->max_orphans))
		err = -ENOSPC;
	else
		sbi->n_orphans++;
	mutex_unlock(&sbi->orphan_inode_mutex);
	spin_unlock(&sbi->orphan_inode_lock);

	return err;
}

void release_orphan_inode(struct f2fs_sb_info *sbi)
{
	mutex_lock(&sbi->orphan_inode_mutex);
	spin_lock(&sbi->orphan_inode_lock);
	f2fs_bug_on(sbi->n_orphans == 0);
	sbi->n_orphans--;
	mutex_unlock(&sbi->orphan_inode_mutex);
	spin_unlock(&sbi->orphan_inode_lock);
}

void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
@@ -218,27 +219,30 @@ void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
	struct list_head *head, *this;
	struct orphan_inode_entry *new = NULL, *orphan = NULL;

	mutex_lock(&sbi->orphan_inode_mutex);
	new = f2fs_kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
	new->ino = ino;

	spin_lock(&sbi->orphan_inode_lock);
	head = &sbi->orphan_inode_list;
	list_for_each(this, head) {
		orphan = list_entry(this, struct orphan_inode_entry, list);
		if (orphan->ino == ino)
			goto out;
		if (orphan->ino == ino) {
			spin_unlock(&sbi->orphan_inode_lock);
			kmem_cache_free(orphan_entry_slab, new);
			return;
		}

		if (orphan->ino > ino)
			break;
		orphan = NULL;
	}

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

	/* add new_oentry into list which is sorted by inode number */
	if (orphan)
		list_add(&new->list, this->prev);
	else
		list_add_tail(&new->list, head);
out:
	mutex_unlock(&sbi->orphan_inode_mutex);
	spin_unlock(&sbi->orphan_inode_lock);
}

void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
@@ -246,7 +250,7 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
	struct list_head *head;
	struct orphan_inode_entry *orphan;

	mutex_lock(&sbi->orphan_inode_mutex);
	spin_lock(&sbi->orphan_inode_lock);
	head = &sbi->orphan_inode_list;
	list_for_each_entry(orphan, head, list) {
		if (orphan->ino == ino) {
@@ -257,7 +261,7 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
			break;
		}
	}
	mutex_unlock(&sbi->orphan_inode_mutex);
	spin_unlock(&sbi->orphan_inode_lock);
}

static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
@@ -270,12 +274,12 @@ static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
	iput(inode);
}

int recover_orphan_inodes(struct f2fs_sb_info *sbi)
void recover_orphan_inodes(struct f2fs_sb_info *sbi)
{
	block_t start_blk, orphan_blkaddr, i, j;

	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
		return 0;
		return;

	sbi->por_doing = true;
	start_blk = __start_cp_addr(sbi) + 1;
@@ -295,29 +299,39 @@ 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 = false;
	return 0;
	return;
}

static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
{
	struct list_head *head, *this, *next;
	struct list_head *head;
	struct f2fs_orphan_block *orphan_blk = NULL;
	struct page *page = NULL;
	unsigned int nentries = 0;
	unsigned short index = 1;
	unsigned short orphan_blocks;

	orphan_blocks = (unsigned short)((sbi->n_orphans +
	unsigned short index;
	unsigned short orphan_blocks = (unsigned short)((sbi->n_orphans +
		(F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK);
	struct page *page = NULL;
	struct orphan_inode_entry *orphan = NULL;

	mutex_lock(&sbi->orphan_inode_mutex);
	for (index = 0; index < orphan_blocks; index++)
		grab_meta_page(sbi, start_blk + index);

	index = 1;
	spin_lock(&sbi->orphan_inode_lock);
	head = &sbi->orphan_inode_list;

	/* loop for each orphan inode entry and write them in Jornal block */
	list_for_each_safe(this, next, head) {
		struct orphan_inode_entry *orphan;
	list_for_each_entry(orphan, head, list) {
		if (!page) {
			page = find_get_page(META_MAPPING(sbi), start_blk++);
			f2fs_bug_on(!page);
			orphan_blk =
				(struct f2fs_orphan_block *)page_address(page);
			memset(orphan_blk, 0, sizeof(*orphan_blk));
			f2fs_put_page(page, 0);
		}

		orphan = list_entry(this, struct orphan_inode_entry, list);
		orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);

		if (nentries == F2FS_ORPHANS_PER_BLOCK) {
			/*
@@ -331,29 +345,20 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
			set_page_dirty(page);
			f2fs_put_page(page, 1);
			index++;
			start_blk++;
			nentries = 0;
			page = NULL;
		}
		if (page)
			goto page_exist;

		page = grab_meta_page(sbi, start_blk);
		orphan_blk = (struct f2fs_orphan_block *)page_address(page);
		memset(orphan_blk, 0, sizeof(*orphan_blk));
page_exist:
		orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
	}
	if (!page)
		goto end;

	if (page) {
		orphan_blk->blk_addr = cpu_to_le16(index);
		orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
		orphan_blk->entry_count = cpu_to_le32(nentries);
		set_page_dirty(page);
		f2fs_put_page(page, 1);
end:
	mutex_unlock(&sbi->orphan_inode_mutex);
	}

	spin_unlock(&sbi->orphan_inode_lock);
}

static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
@@ -428,7 +433,8 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
	cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);

	/* The second checkpoint pack should start at the next segment */
	cp_start_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
	cp_start_blk_no += ((unsigned long long)1) <<
				le32_to_cpu(fsb->log_blocks_per_seg);
	cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);

	if (cp1 && cp2) {
@@ -465,7 +471,7 @@ static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
	list_for_each(this, head) {
		struct dir_inode_entry *entry;
		entry = list_entry(this, struct dir_inode_entry, list);
		if (entry->inode == inode)
		if (unlikely(entry->inode == inode))
			return -EEXIST;
	}
	list_add_tail(&new->list, head);
@@ -513,8 +519,8 @@ void add_dirty_dir_inode(struct inode *inode)
void remove_dirty_dir_inode(struct inode *inode)
{
	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
	struct list_head *head = &sbi->dir_inode_list;
	struct list_head *this;

	struct list_head *this, *head;

	if (!S_ISDIR(inode->i_mode))
		return;
@@ -525,6 +531,7 @@ void remove_dirty_dir_inode(struct inode *inode)
		return;
	}

	head = &sbi->dir_inode_list;
	list_for_each(this, head) {
		struct dir_inode_entry *entry;
		entry = list_entry(this, struct dir_inode_entry, list);
@@ -546,11 +553,13 @@ void remove_dirty_dir_inode(struct inode *inode)

struct inode *check_dirty_dir_inode(struct f2fs_sb_info *sbi, nid_t ino)
{
	struct list_head *head = &sbi->dir_inode_list;
	struct list_head *this;

	struct list_head *this, *head;
	struct inode *inode = NULL;

	spin_lock(&sbi->dir_inode_lock);

	head = &sbi->dir_inode_list;
	list_for_each(this, head) {
		struct dir_inode_entry *entry;
		entry = list_entry(this, struct dir_inode_entry, list);
@@ -565,11 +574,13 @@ struct inode *check_dirty_dir_inode(struct f2fs_sb_info *sbi, nid_t ino)

void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
{
	struct list_head *head = &sbi->dir_inode_list;
	struct list_head *head;
	struct dir_inode_entry *entry;
	struct inode *inode;
retry:
	spin_lock(&sbi->dir_inode_lock);

	head = &sbi->dir_inode_list;
	if (list_empty(head)) {
		spin_unlock(&sbi->dir_inode_lock);
		return;
@@ -585,7 +596,7 @@ void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
		 * We should submit bio, since it exists several
		 * wribacking dentry pages in the freeing inode.
		 */
		f2fs_submit_bio(sbi, DATA, true);
		f2fs_submit_merged_bio(sbi, DATA, WRITE);
	}
	goto retry;
}
@@ -760,8 +771,8 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
	/* wait for previous submitted node/meta pages writeback */
	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);
	filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX);
	filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX);

	/* update user_block_counts */
	sbi->last_valid_block_count = sbi->total_valid_block_count;
@@ -770,7 +781,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
	/* Here, we only have one bio having CP pack */
	sync_meta_pages(sbi, META_FLUSH, LONG_MAX);

	if (!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) {
	if (unlikely(!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))) {
		clear_prefree_segments(sbi);
		F2FS_RESET_SB_DIRT(sbi);
	}
@@ -791,9 +802,9 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)

	trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops");

	f2fs_submit_bio(sbi, DATA, true);
	f2fs_submit_bio(sbi, NODE, true);
	f2fs_submit_bio(sbi, META, true);
	f2fs_submit_merged_bio(sbi, DATA, WRITE);
	f2fs_submit_merged_bio(sbi, NODE, WRITE);
	f2fs_submit_merged_bio(sbi, META, WRITE);

	/*
	 * update checkpoint pack index
@@ -818,20 +829,28 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)

void init_orphan_info(struct f2fs_sb_info *sbi)
{
	mutex_init(&sbi->orphan_inode_mutex);
	spin_lock_init(&sbi->orphan_inode_lock);
	INIT_LIST_HEAD(&sbi->orphan_inode_list);
	sbi->n_orphans = 0;
	/*
	 * considering 512 blocks in a segment 8 blocks are needed for cp
	 * and log segment summaries. Remaining blocks are used to keep
	 * orphan entries with the limitation one reserved segment
	 * for cp pack we can have max 1020*504 orphan entries
	 */
	sbi->max_orphans = (sbi->blocks_per_seg - 2 - NR_CURSEG_TYPE)
				* F2FS_ORPHANS_PER_BLOCK;
}

int __init create_checkpoint_caches(void)
{
	orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
			sizeof(struct orphan_inode_entry), NULL);
	if (unlikely(!orphan_entry_slab))
	if (!orphan_entry_slab)
		return -ENOMEM;
	inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry",
			sizeof(struct dir_inode_entry), NULL);
	if (unlikely(!inode_entry_slab)) {
	if (!inode_entry_slab) {
		kmem_cache_destroy(orphan_entry_slab);
		return -ENOMEM;
	}
Loading