linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/11] f2fs: introduce macros for proc entries
@ 2016-05-03 18:21 Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 02/11] f2fs: add proc entry to show valid block bitmap Jaegeuk Kim
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This adds macros to be used multiple proc entries.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/super.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 19a85cf..b006de6 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -745,19 +745,22 @@ static int segment_info_seq_show(struct seq_file *seq, void *offset)
 	return 0;
 }
 
-static int segment_info_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, segment_info_seq_show, PDE_DATA(inode));
-}
-
-static const struct file_operations f2fs_seq_segment_info_fops = {
-	.owner = THIS_MODULE,
-	.open = segment_info_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
+#define F2FS_PROC_FILE_DEF(_name)					\
+static int _name##_open_fs(struct inode *inode, struct file *file)	\
+{									\
+	return single_open(file, _name##_seq_show, PDE_DATA(inode));	\
+}									\
+									\
+static const struct file_operations f2fs_seq_##_name##_fops = {		\
+	.owner = THIS_MODULE,						\
+	.open = _name##_open_fs,					\
+	.read = seq_read,						\
+	.llseek = seq_lseek,						\
+	.release = single_release,					\
 };
 
+F2FS_PROC_FILE_DEF(segment_info);
+
 static void default_options(struct f2fs_sb_info *sbi)
 {
 	/* init some FS parameters */
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/11] f2fs: add proc entry to show valid block bitmap
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 03/11] f2fs: introduce f2fs_kmalloc to wrap kmalloc Jaegeuk Kim
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch adds a new proc entry to show segment information in more detail.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/super.c | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index b006de6..90d4b86 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -539,6 +539,7 @@ static void f2fs_put_super(struct super_block *sb)
 
 	if (sbi->s_proc) {
 		remove_proc_entry("segment_info", sbi->s_proc);
+		remove_proc_entry("segment_bits", sbi->s_proc);
 		remove_proc_entry(sb->s_id, f2fs_proc_root);
 	}
 	kobject_del(&sbi->s_kobj);
@@ -745,6 +746,30 @@ static int segment_info_seq_show(struct seq_file *seq, void *offset)
 	return 0;
 }
 
+static int segment_bits_seq_show(struct seq_file *seq, void *offset)
+{
+	struct super_block *sb = seq->private;
+	struct f2fs_sb_info *sbi = F2FS_SB(sb);
+	unsigned int total_segs =
+			le32_to_cpu(sbi->raw_super->segment_count_main);
+	int i, j;
+
+	seq_puts(seq, "format: segment_type|valid_blocks|bitmaps\n"
+		"segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");
+
+	for (i = 0; i < total_segs; i++) {
+		struct seg_entry *se = get_seg_entry(sbi, i);
+
+		seq_printf(seq, "%-10d", i);
+		seq_printf(seq, "%d|%-3u|", se->type,
+					get_valid_blocks(sbi, i, 1));
+		for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++)
+			seq_printf(seq, "%x ", se->cur_valid_map[j]);
+		seq_putc(seq, '\n');
+	}
+	return 0;
+}
+
 #define F2FS_PROC_FILE_DEF(_name)					\
 static int _name##_open_fs(struct inode *inode, struct file *file)	\
 {									\
@@ -760,6 +785,7 @@ static const struct file_operations f2fs_seq_##_name##_fops = {		\
 };
 
 F2FS_PROC_FILE_DEF(segment_info);
+F2FS_PROC_FILE_DEF(segment_bits);
 
 static void default_options(struct f2fs_sb_info *sbi)
 {
@@ -1541,9 +1567,12 @@ try_onemore:
 	if (f2fs_proc_root)
 		sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
 
-	if (sbi->s_proc)
+	if (sbi->s_proc) {
 		proc_create_data("segment_info", S_IRUGO, sbi->s_proc,
 				 &f2fs_seq_segment_info_fops, sb);
+		proc_create_data("segment_bits", S_IRUGO, sbi->s_proc,
+				 &f2fs_seq_segment_bits_fops, sb);
+	}
 
 	sbi->s_kobj.kset = f2fs_kset;
 	init_completion(&sbi->s_kobj_unregister);
@@ -1619,6 +1648,7 @@ free_kobj:
 free_proc:
 	if (sbi->s_proc) {
 		remove_proc_entry("segment_info", sbi->s_proc);
+		remove_proc_entry("segment_bits", sbi->s_proc);
 		remove_proc_entry(sb->s_id, f2fs_proc_root);
 	}
 	f2fs_destroy_stats(sbi);
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/11] f2fs: introduce f2fs_kmalloc to wrap kmalloc
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 02/11] f2fs: add proc entry to show valid block bitmap Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 04/11] f2fs: use f2fs_grab_cache_page instead of grab_cache_page Jaegeuk Kim
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch adds f2fs_kmalloc.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/acl.c    | 4 ++--
 fs/f2fs/dir.c    | 2 +-
 fs/f2fs/f2fs.h   | 5 +++++
 fs/f2fs/gc.c     | 2 +-
 fs/f2fs/inline.c | 2 +-
 5 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index c8f25f7..d757d79 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -115,7 +115,7 @@ static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size)
 	struct f2fs_acl_entry *entry;
 	int i;
 
-	f2fs_acl = kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count *
+	f2fs_acl = f2fs_kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count *
 			sizeof(struct f2fs_acl_entry), GFP_NOFS);
 	if (!f2fs_acl)
 		return ERR_PTR(-ENOMEM);
@@ -175,7 +175,7 @@ static struct posix_acl *__f2fs_get_acl(struct inode *inode, int type,
 
 	retval = f2fs_getxattr(inode, name_index, "", NULL, 0, dpage);
 	if (retval > 0) {
-		value = kmalloc(retval, GFP_F2FS_ZERO);
+		value = f2fs_kmalloc(retval, GFP_F2FS_ZERO);
 		if (!value)
 			return ERR_PTR(-ENOMEM);
 		retval = f2fs_getxattr(inode, name_index, "", value,
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index dbfc1d1..6bd0595 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -805,7 +805,7 @@ bool f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
 			int save_len = fstr->len;
 			int ret;
 
-			de_name.name = kmalloc(de_name.len, GFP_NOFS);
+			de_name.name = f2fs_kmalloc(de_name.len, GFP_NOFS);
 			if (!de_name.name)
 				return false;
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 38aa75c..364d5fd 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1643,6 +1643,11 @@ static inline bool f2fs_may_extent_tree(struct inode *inode)
 	return S_ISREG(inode->i_mode);
 }
 
+static inline void *f2fs_kmalloc(size_t size, gfp_t flags)
+{
+	return kmalloc(size, flags);
+}
+
 static inline void *f2fs_kvmalloc(size_t size, gfp_t flags)
 {
 	void *ret;
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 19e9faf..38d56f6 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -96,7 +96,7 @@ int start_gc_thread(struct f2fs_sb_info *sbi)
 	dev_t dev = sbi->sb->s_bdev->bd_dev;
 	int err = 0;
 
-	gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
+	gc_th = f2fs_kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
 	if (!gc_th) {
 		err = -ENOMEM;
 		goto out;
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index e61084c..33830b2 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -465,7 +465,7 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,
 	struct f2fs_inline_dentry *backup_dentry;
 	int err;
 
-	backup_dentry = kmalloc(sizeof(struct f2fs_inline_dentry),
+	backup_dentry = f2fs_kmalloc(sizeof(struct f2fs_inline_dentry),
 							GFP_F2FS_ZERO);
 	if (!backup_dentry)
 		return -ENOMEM;
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/11] f2fs: use f2fs_grab_cache_page instead of grab_cache_page
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 02/11] f2fs: add proc entry to show valid block bitmap Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 03/11] f2fs: introduce f2fs_kmalloc to wrap kmalloc Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 05/11] f2fs: add mount option to select fault injection ratio Jaegeuk Kim
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch converts grab_cache_page to f2fs_grab_cache_page.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/checkpoint.c | 7 ++++---
 fs/f2fs/inline.c     | 4 ++--
 fs/f2fs/node.c       | 8 ++++----
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index dc7bc72..ac87cd9 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -34,7 +34,7 @@ struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
 	struct address_space *mapping = META_MAPPING(sbi);
 	struct page *page = NULL;
 repeat:
-	page = grab_cache_page(mapping, index);
+	page = f2fs_grab_cache_page(mapping, index, false);
 	if (!page) {
 		cond_resched();
 		goto repeat;
@@ -64,7 +64,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
 	if (unlikely(!is_meta))
 		fio.rw &= ~REQ_META;
 repeat:
-	page = grab_cache_page(mapping, index);
+	page = f2fs_grab_cache_page(mapping, index, false);
 	if (!page) {
 		cond_resched();
 		goto repeat;
@@ -186,7 +186,8 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
 			BUG();
 		}
 
-		page = grab_cache_page(META_MAPPING(sbi), fio.new_blkaddr);
+		page = f2fs_grab_cache_page(META_MAPPING(sbi),
+						fio.new_blkaddr, false);
 		if (!page)
 			continue;
 		if (PageUptodate(page)) {
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 33830b2..8a51955 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -161,7 +161,7 @@ int f2fs_convert_inline_inode(struct inode *inode)
 	if (!f2fs_has_inline_data(inode))
 		return 0;
 
-	page = grab_cache_page(inode->i_mapping, 0);
+	page = f2fs_grab_cache_page(inode->i_mapping, 0, false);
 	if (!page)
 		return -ENOMEM;
 
@@ -358,7 +358,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
 	struct f2fs_dentry_block *dentry_blk;
 	int err;
 
-	page = grab_cache_page(dir->i_mapping, 0);
+	page = f2fs_grab_cache_page(dir->i_mapping, 0, false);
 	if (!page) {
 		f2fs_put_page(ipage, 1);
 		return -ENOMEM;
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index f80cfb6..af010f5 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -995,7 +995,7 @@ struct page *new_node_page(struct dnode_of_data *dn,
 	if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
 		return ERR_PTR(-EPERM);
 
-	page = grab_cache_page(NODE_MAPPING(sbi), dn->nid);
+	page = f2fs_grab_cache_page(NODE_MAPPING(sbi), dn->nid, false);
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
@@ -1087,7 +1087,7 @@ void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
 	if (apage)
 		return;
 
-	apage = grab_cache_page(NODE_MAPPING(sbi), nid);
+	apage = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false);
 	if (!apage)
 		return;
 
@@ -1128,7 +1128,7 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid,
 		return ERR_PTR(-ENOENT);
 	f2fs_bug_on(sbi, check_nid_range(sbi, nid));
 repeat:
-	page = grab_cache_page(NODE_MAPPING(sbi), nid);
+	page = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false);
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
@@ -2012,7 +2012,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
 	if (unlikely(old_ni.blk_addr != NULL_ADDR))
 		return -EINVAL;
 
-	ipage = grab_cache_page(NODE_MAPPING(sbi), ino);
+	ipage = f2fs_grab_cache_page(NODE_MAPPING(sbi), ino, false);
 	if (!ipage)
 		return -ENOMEM;
 
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/11] f2fs: add mount option to select fault injection ratio
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
                   ` (2 preceding siblings ...)
  2016-05-03 18:21 ` [PATCH 04/11] f2fs: use f2fs_grab_cache_page instead of grab_cache_page Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-09 12:00   ` [f2fs-dev] " Chao Yu
  2016-05-03 18:21 ` [PATCH 06/11] f2fs: inject kmalloc failure Jaegeuk Kim
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch adds a mount option to select fault ratio.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/Kconfig |  8 ++++++++
 fs/f2fs/f2fs.h  |  1 +
 fs/f2fs/super.c | 16 ++++++++++++++++
 3 files changed, 25 insertions(+)

diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
index 1f8982a..378c221 100644
--- a/fs/f2fs/Kconfig
+++ b/fs/f2fs/Kconfig
@@ -94,3 +94,11 @@ config F2FS_IO_TRACE
 	  information and block IO patterns in the filesystem level.
 
 	  If unsure, say N.
+
+config F2FS_FAULT_INJECTION
+	bool "F2FS fault injection facility"
+	depends on F2FS_FS
+	help
+	  Test F2FS to inject faults such as ENOMEM, ENOSPC, and so on.
+
+	  If unsure, say N.
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 364d5fd..0684d3e 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -56,6 +56,7 @@
 #define F2FS_MOUNT_EXTENT_CACHE		0x00002000
 #define F2FS_MOUNT_FORCE_FG_GC		0x00004000
 #define F2FS_MOUNT_DATA_FLUSH		0x00008000
+#define F2FS_MOUNT_FAULT_INJECTION	0x00010000
 
 #define clear_opt(sbi, option)	(sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
 #define set_opt(sbi, option)	(sbi->mount_opt.opt |= F2FS_MOUNT_##option)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 90d4b86..b27febd 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -39,6 +39,10 @@ static struct proc_dir_entry *f2fs_proc_root;
 static struct kmem_cache *f2fs_inode_cachep;
 static struct kset *f2fs_kset;
 
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+u32 f2fs_fault_rate = 0;
+#endif
+
 /* f2fs-wide shrinker description */
 static struct shrinker f2fs_shrinker_info = {
 	.scan_objects = f2fs_shrink_scan,
@@ -68,6 +72,7 @@ enum {
 	Opt_noextent_cache,
 	Opt_noinline_data,
 	Opt_data_flush,
+	Opt_fault_injection,
 	Opt_err,
 };
 
@@ -93,6 +98,7 @@ static match_table_t f2fs_tokens = {
 	{Opt_noextent_cache, "noextent_cache"},
 	{Opt_noinline_data, "noinline_data"},
 	{Opt_data_flush, "data_flush"},
+	{Opt_fault_injection, "fault_injection=%u"},
 	{Opt_err, NULL},
 };
 
@@ -433,6 +439,16 @@ static int parse_options(struct super_block *sb, char *options)
 		case Opt_data_flush:
 			set_opt(sbi, DATA_FLUSH);
 			break;
+		case Opt_fault_injection:
+			if (args->from && match_int(args, &arg))
+				return -EINVAL;
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+			f2fs_fault_rate = arg;
+#else
+			f2fs_msg(sb, KERN_INFO,
+				"FAULT_INJECTION was not selected");
+#endif
+			break;
 		default:
 			f2fs_msg(sb, KERN_ERR,
 				"Unrecognized mount option \"%s\" or missing value",
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/11] f2fs: inject kmalloc failure
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
                   ` (3 preceding siblings ...)
  2016-05-03 18:21 ` [PATCH 05/11] f2fs: add mount option to select fault injection ratio Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 07/11] f2fs: inject page allocation failures Jaegeuk Kim
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch injects kmalloc failure given a fault injection rate.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/f2fs.h  | 29 +++++++++++++++++++++++++++++
 fs/f2fs/super.c |  6 ++++++
 2 files changed, 35 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 0684d3e..60098df 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -37,6 +37,31 @@
 	} while (0)
 #endif
 
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+enum {
+	FAULT_KMALLOC,
+	FAULT_MAX,
+};
+
+extern u32 f2fs_fault_rate;
+extern atomic_t f2fs_ops;
+extern char *fault_name[FAULT_MAX];
+
+static inline bool time_to_inject(int type)
+{
+	atomic_inc(&f2fs_ops);
+	if (f2fs_fault_rate && (atomic_read(&f2fs_ops) >= f2fs_fault_rate)) {
+		atomic_set(&f2fs_ops, 0);
+		printk("%sF2FS-fs : inject %s in %pF\n",
+				KERN_INFO,
+				fault_name[type],
+				__builtin_return_address(0));
+		return true;
+	}
+	return false;
+}
+#endif
+
 /*
  * For mount options
  */
@@ -1646,6 +1671,10 @@ static inline bool f2fs_may_extent_tree(struct inode *inode)
 
 static inline void *f2fs_kmalloc(size_t size, gfp_t flags)
 {
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+	if (time_to_inject(FAULT_KMALLOC))
+		return NULL;
+#endif
 	return kmalloc(size, flags);
 }
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index b27febd..76f4d2c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -41,6 +41,11 @@ static struct kset *f2fs_kset;
 
 #ifdef CONFIG_F2FS_FAULT_INJECTION
 u32 f2fs_fault_rate = 0;
+atomic_t f2fs_ops;
+
+char *fault_name[FAULT_MAX] = {
+	[FAULT_KMALLOC]		= "kmalloc",
+};
 #endif
 
 /* f2fs-wide shrinker description */
@@ -444,6 +449,7 @@ static int parse_options(struct super_block *sb, char *options)
 				return -EINVAL;
 #ifdef CONFIG_F2FS_FAULT_INJECTION
 			f2fs_fault_rate = arg;
+			atomic_set(&f2fs_ops, 0);
 #else
 			f2fs_msg(sb, KERN_INFO,
 				"FAULT_INJECTION was not selected");
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/11] f2fs: inject page allocation failures
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
                   ` (4 preceding siblings ...)
  2016-05-03 18:21 ` [PATCH 06/11] f2fs: inject kmalloc failure Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 08/11] f2fs: inject ENOSPC failures Jaegeuk Kim
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch adds page allocation failures.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/f2fs.h  | 9 +++++++++
 fs/f2fs/super.c | 1 +
 2 files changed, 10 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 60098df..02c2c96 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -40,6 +40,7 @@
 #ifdef CONFIG_F2FS_FAULT_INJECTION
 enum {
 	FAULT_KMALLOC,
+	FAULT_PAGE_ALLOC,
 	FAULT_MAX,
 };
 
@@ -1296,6 +1297,14 @@ static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
 static inline struct page *f2fs_grab_cache_page(struct address_space *mapping,
 						pgoff_t index, bool for_write)
 {
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+	struct page *page = find_lock_page(mapping, index);
+	if (page)
+		return page;
+
+	if (time_to_inject(FAULT_PAGE_ALLOC))
+		return NULL;
+#endif
 	if (!for_write)
 		return grab_cache_page(mapping, index);
 	return grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 76f4d2c..1715794 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -45,6 +45,7 @@ atomic_t f2fs_ops;
 
 char *fault_name[FAULT_MAX] = {
 	[FAULT_KMALLOC]		= "kmalloc",
+	[FAULT_PAGE_ALLOC]	= "page alloc",
 };
 #endif
 
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/11] f2fs: inject ENOSPC failures
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
                   ` (5 preceding siblings ...)
  2016-05-03 18:21 ` [PATCH 07/11] f2fs: inject page allocation failures Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 09/11] f2fs: revisit error handling flows Jaegeuk Kim
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch injects ENOSPC failures.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/checkpoint.c |  7 +++++++
 fs/f2fs/dir.c        |  4 ++++
 fs/f2fs/f2fs.h       | 10 ++++++++++
 fs/f2fs/node.c       |  4 ++++
 fs/f2fs/super.c      |  4 ++++
 5 files changed, 29 insertions(+)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index ac87cd9..9169dab 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -474,6 +474,13 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)
 	int err = 0;
 
 	spin_lock(&im->ino_lock);
+
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+	if (time_to_inject(FAULT_ORPHAN)) {
+		spin_unlock(&im->ino_lock);
+		return -ENOSPC;
+	}
+#endif
 	if (unlikely(im->ino_num >= sbi->max_orphans))
 		err = -ENOSPC;
 	else
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 6bd0595..50f42be 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -537,6 +537,10 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
 	}
 
 start:
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+	if (time_to_inject(FAULT_DIR_DEPTH))
+		return -ENOSPC;
+#endif
 	if (unlikely(current_depth == MAX_DIR_HASH_DEPTH))
 		return -ENOSPC;
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 02c2c96..659fdea 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -41,6 +41,10 @@
 enum {
 	FAULT_KMALLOC,
 	FAULT_PAGE_ALLOC,
+	FAULT_ALLOC_NID,
+	FAULT_ORPHAN,
+	FAULT_BLOCK,
+	FAULT_DIR_DEPTH,
 	FAULT_MAX,
 };
 
@@ -1087,6 +1091,12 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
 	block_t	valid_block_count;
 
 	spin_lock(&sbi->stat_lock);
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+	if (time_to_inject(FAULT_BLOCK)) {
+		spin_unlock(&sbi->stat_lock);
+		return false;
+	}
+#endif
 	valid_block_count =
 		sbi->total_valid_block_count + (block_t)count;
 	if (unlikely(valid_block_count > sbi->user_block_count)) {
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index af010f5..78b98db 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1838,6 +1838,10 @@ bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
 	struct f2fs_nm_info *nm_i = NM_I(sbi);
 	struct free_nid *i = NULL;
 retry:
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+	if (time_to_inject(FAULT_ALLOC_NID))
+		return false;
+#endif
 	if (unlikely(sbi->total_valid_node_count + 1 > nm_i->available_nids))
 		return false;
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 1715794..55e8eb0 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -46,6 +46,10 @@ atomic_t f2fs_ops;
 char *fault_name[FAULT_MAX] = {
 	[FAULT_KMALLOC]		= "kmalloc",
 	[FAULT_PAGE_ALLOC]	= "page alloc",
+	[FAULT_ALLOC_NID]	= "alloc nid",
+	[FAULT_ORPHAN]		= "orphan",
+	[FAULT_BLOCK]		= "no more block",
+	[FAULT_DIR_DEPTH]	= "too big dir depth",
 };
 #endif
 
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/11] f2fs: revisit error handling flows
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
                   ` (6 preceding siblings ...)
  2016-05-03 18:21 ` [PATCH 08/11] f2fs: inject ENOSPC failures Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 10/11] f2fs: fix leak of orphan inode objects Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case Jaegeuk Kim
  9 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch fixes a couple of bugs regarding to orphan inodes when handling
errors.

This tries to
 - call alloc_nid_done with add_orphan_inode in handle_failed_inode
 - let truncate blocks in f2fs_evict_inode
 - not make a bad inode due to i_mode change

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/dir.c   | 20 ++++++++++++--------
 fs/f2fs/inode.c | 40 ++++++++++++++++------------------------
 2 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 50f42be..5373f33 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -391,9 +391,14 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
 			return page;
 
 		if (S_ISDIR(inode->i_mode)) {
+			/* in order to handle error case */
+			get_page(page);
 			err = make_empty_dir(inode, dir, page);
-			if (err)
-				goto error;
+			if (err) {
+				lock_page(page);
+				goto put_error;
+			}
+			put_page(page);
 		}
 
 		err = f2fs_init_acl(inode, dir, page, dpage);
@@ -437,13 +442,12 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
 	return page;
 
 put_error:
-	f2fs_put_page(page, 1);
-error:
-	/* once the failed inode becomes a bad inode, i_mode is S_IFREG */
+	/* truncate empty dir pages */
 	truncate_inode_pages(&inode->i_data, 0);
-	truncate_blocks(inode, 0, false);
-	remove_dirty_inode(inode);
-	remove_inode_page(inode);
+
+	clear_nlink(inode);
+	update_inode(inode, page);
+	f2fs_put_page(page, 1);
 	return ERR_PTR(err);
 }
 
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index cb269c4..f4ac851 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -368,10 +368,7 @@ no_delete:
 	if (is_inode_flag_set(fi, FI_UPDATE_WRITE))
 		add_ino_entry(sbi, inode->i_ino, UPDATE_INO);
 	if (is_inode_flag_set(fi, FI_FREE_NID)) {
-		if (err && err != -ENOENT)
-			alloc_nid_done(sbi, inode->i_ino);
-		else
-			alloc_nid_failed(sbi, inode->i_ino);
+		alloc_nid_failed(sbi, inode->i_ino);
 		clear_inode_flag(fi, FI_FREE_NID);
 	}
 
@@ -397,37 +394,32 @@ out_clear:
 void handle_failed_inode(struct inode *inode)
 {
 	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-	int err = 0;
+	struct node_info ni;
 
-	clear_nlink(inode);
-	make_bad_inode(inode);
+	/* don't make bad inode, since it becomes a regular file. */
 	unlock_new_inode(inode);
 
-	i_size_write(inode, 0);
-	if (F2FS_HAS_BLOCKS(inode))
-		err = f2fs_truncate(inode, false);
-
-	if (!err)
-		err = remove_inode_page(inode);
-
 	/*
-	 * if we skip truncate_node in remove_inode_page bacause we failed
-	 * before, it's better to find another way to release resource of
-	 * this inode (e.g. valid block count, node block or nid). Here we
-	 * choose to add this inode to orphan list, so that we can call iput
-	 * for releasing in orphan recovery flow.
-	 *
 	 * Note: we should add inode to orphan list before f2fs_unlock_op()
 	 * so we can prevent losing this orphan when encoutering checkpoint
 	 * and following suddenly power-off.
 	 */
-	if (err && err != -ENOENT) {
-		err = acquire_orphan_inode(sbi);
-		if (!err)
+	get_node_info(sbi, inode->i_ino, &ni);
+
+	if (ni.blk_addr != NULL_ADDR) {
+		int err = acquire_orphan_inode(sbi);
+		if (err) {
+			set_sbi_flag(sbi, SBI_NEED_FSCK);
+			f2fs_msg(sbi->sb, KERN_WARNING,
+				"Too many orphan inodes, run fsck to fix.");
+		} else {
 			add_orphan_inode(sbi, inode->i_ino);
+		}
+		alloc_nid_done(sbi, inode->i_ino);
+	} else {
+		set_inode_flag(F2FS_I(inode), FI_FREE_NID);
 	}
 
-	set_inode_flag(F2FS_I(inode), FI_FREE_NID);
 	f2fs_unlock_op(sbi);
 
 	/* iput will drop the inode object */
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/11] f2fs: fix leak of orphan inode objects
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
                   ` (7 preceding siblings ...)
  2016-05-03 18:21 ` [PATCH 09/11] f2fs: revisit error handling flows Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-03 18:21 ` [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case Jaegeuk Kim
  9 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

When unmounting filesystem, we should release all the ino entries.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/checkpoint.c | 6 +++---
 fs/f2fs/f2fs.h       | 2 +-
 fs/f2fs/super.c      | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 9169dab..6402e93 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -449,12 +449,12 @@ bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
 	return e ? true : false;
 }
 
-void release_ino_entry(struct f2fs_sb_info *sbi)
+void release_ino_entry(struct f2fs_sb_info *sbi, bool all)
 {
 	struct ino_entry *e, *tmp;
 	int i;
 
-	for (i = APPEND_INO; i <= UPDATE_INO; i++) {
+	for (i = all ? ORPHAN_INO: APPEND_INO; i <= UPDATE_INO; i++) {
 		struct inode_management *im = &sbi->im[i];
 
 		spin_lock(&im->ino_lock);
@@ -1090,7 +1090,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 		invalidate_mapping_pages(META_MAPPING(sbi), discard_blk,
 								discard_blk);
 
-	release_ino_entry(sbi);
+	release_ino_entry(sbi, false);
 
 	if (unlikely(f2fs_cp_error(sbi)))
 		return -EIO;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 659fdea..6e6fd0b 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1910,7 +1910,7 @@ void ra_meta_pages_cond(struct f2fs_sb_info *, pgoff_t);
 long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
 void add_ino_entry(struct f2fs_sb_info *, nid_t, int type);
 void remove_ino_entry(struct f2fs_sb_info *, nid_t, int type);
-void release_ino_entry(struct f2fs_sb_info *);
+void release_ino_entry(struct f2fs_sb_info *, bool);
 bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
 int acquire_orphan_inode(struct f2fs_sb_info *);
 void release_orphan_inode(struct f2fs_sb_info *);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 55e8eb0..6b5f0af 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -596,7 +596,7 @@ static void f2fs_put_super(struct super_block *sb)
 	 * normally superblock is clean, so we need to release this.
 	 * In addition, EIO will skip do checkpoint, we need this as well.
 	 */
-	release_ino_entry(sbi);
+	release_ino_entry(sbi, true);
 	release_discard_addrs(sbi);
 
 	f2fs_leave_shrinker(sbi);
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case
  2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
                   ` (8 preceding siblings ...)
  2016-05-03 18:21 ` [PATCH 10/11] f2fs: fix leak of orphan inode objects Jaegeuk Kim
@ 2016-05-03 18:21 ` Jaegeuk Kim
  2016-05-05  2:00   ` [f2fs-dev] " Hou Pengyang
  9 siblings, 1 reply; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-03 18:21 UTC (permalink / raw)
  To: linux-kernel, linux-fsdevel, linux-f2fs-devel; +Cc: Jaegeuk Kim

This patch modifies to retry truncating node blocks in -ENOMEM case.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/inode.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index f4ac851..5cccd7a 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -344,7 +344,7 @@ void f2fs_evict_inode(struct inode *inode)
 	sb_start_intwrite(inode->i_sb);
 	set_inode_flag(fi, FI_NO_ALLOC);
 	i_size_write(inode, 0);
-
+retry:
 	if (F2FS_HAS_BLOCKS(inode))
 		err = f2fs_truncate(inode, true);
 
@@ -374,6 +374,11 @@ no_delete:
 
 	if (err && err != -ENOENT) {
 		if (!exist_written_data(sbi, inode->i_ino, ORPHAN_INO)) {
+			/* give more chances, if ENOMEM case */
+			if (err == -ENOMEM) {
+				err = 0;
+				goto retry;
+			}
 			/*
 			 * get here because we failed to release resource
 			 * of inode previously, reminder our user to run fsck
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [f2fs-dev] [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case
  2016-05-03 18:21 ` [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case Jaegeuk Kim
@ 2016-05-05  2:00   ` Hou Pengyang
  2016-05-05  2:59     ` Jaegeuk Kim
  0 siblings, 1 reply; 14+ messages in thread
From: Hou Pengyang @ 2016-05-05  2:00 UTC (permalink / raw)
  To: Jaegeuk Kim
  Cc: linux-kernel, linux-fsdevel, linux-f2fs-devel, wangbintian 00221568

On 2016/5/4 2:21, Jaegeuk Kim wrote:
> This patch modifies to retry truncating node blocks in -ENOMEM case.
>
Hi, Kim. in this patch, I think there is NO chance to retry for -ENOMEM.

This is because if exist_written_data returns false, we can confirm that
this inode has been released from orphan radix-tree:
f2fs_evict_inode
  ---> remove_inode_page
     ---> truncate_node
         ---> remove_orphan_inode
On this condition, err is 0, So it won't enter:
if (err && err != -ENOENT)
{
     ...
}
sequentially, there is no chance to truncate node blocks again.
I miss something else?

How about this patch?

--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -345,6 +345,7 @@ void f2fs_evict_inode(struct inode *inode)
         set_inode_flag(fi, FI_NO_ALLOC);
         i_size_write(inode, 0);

+retry:
         if (F2FS_HAS_BLOCKS(inode))
                 err = f2fs_truncate(inode, true);

@@ -354,6 +355,11 @@ void f2fs_evict_inode(struct inode *inode)
                 f2fs_unlock_op(sbi);
         }

+       if (err == -ENOMEM) {
+               err = 0;
+               goto retry;
+       }
+
         sb_end_intwrite(inode->i_sb);
  no_delete:
         stat_dec_inline_xattr(inode);
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> ---
>   fs/f2fs/inode.c | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> index f4ac851..5cccd7a 100644
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -344,7 +344,7 @@ void f2fs_evict_inode(struct inode *inode)
>   	sb_start_intwrite(inode->i_sb);
>   	set_inode_flag(fi, FI_NO_ALLOC);
>   	i_size_write(inode, 0);
> -
> +retry:
>   	if (F2FS_HAS_BLOCKS(inode))
>   		err = f2fs_truncate(inode, true);
>
> @@ -374,6 +374,11 @@ no_delete:
>
>   	if (err && err != -ENOENT) {
>   		if (!exist_written_data(sbi, inode->i_ino, ORPHAN_INO)) {
> +			/* give more chances, if ENOMEM case */
> +			if (err == -ENOMEM) {
> +				err = 0;
> +				goto retry;
> +			}
>   			/*
>   			 * get here because we failed to release resource
>   			 * of inode previously, reminder our user to run fsck
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [f2fs-dev] [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case
  2016-05-05  2:00   ` [f2fs-dev] " Hou Pengyang
@ 2016-05-05  2:59     ` Jaegeuk Kim
  0 siblings, 0 replies; 14+ messages in thread
From: Jaegeuk Kim @ 2016-05-05  2:59 UTC (permalink / raw)
  To: Hou Pengyang
  Cc: linux-kernel, linux-fsdevel, linux-f2fs-devel, wangbintian 00221568

Hi,

On Thu, May 05, 2016 at 10:00:15AM +0800, Hou Pengyang wrote:
> On 2016/5/4 2:21, Jaegeuk Kim wrote:
> >This patch modifies to retry truncating node blocks in -ENOMEM case.
> >
> Hi, Kim. in this patch, I think there is NO chance to retry for -ENOMEM.
> 
> This is because if exist_written_data returns false, we can confirm that
> this inode has been released from orphan radix-tree:
> f2fs_evict_inode
>  ---> remove_inode_page
>     ---> truncate_node
>         ---> remove_orphan_inode
> On this condition, err is 0, So it won't enter:
> if (err && err != -ENOENT)
> {
>     ...
> }
> sequentially, there is no chance to truncate node blocks again.
> I miss something else?

When I initially tested fault injection, I could hit that before.
But, now I can't hit this again. :(
It seems it was gone while I updated the error flow before.
Agreed with you, and let me take your change.

BTW, I even suspect whether this leaking condition happens or not.
If f2fs_evict_inode deals with inode deletion, that inode should be an orphan
one. So, we don't need to consider that condition actually.

So, I wrote this patch as well.
I started stress tests again. :)

Thanks,

>From 8c1e4e5ca23410b8f55bbc75d64f75416d486739 Mon Sep 17 00:00:00 2001
From: Jaegeuk Kim <jaegeuk@kernel.org>
Date: Wed, 4 May 2016 19:48:53 -0700
Subject: [PATCH] f2fs: don't worry about inode leak in evict_inode

Even if an inode failed to release its blocks, it should be kept in an orphan
inode list, so it will be released later.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/inode.c | 16 ++--------------
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index baf3a2a..689d691 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -377,20 +377,8 @@ no_delete:
 		alloc_nid_failed(sbi, inode->i_ino);
 		clear_inode_flag(fi, FI_FREE_NID);
 	}
-
-	if (err && err != -ENOENT) {
-		if (!exist_written_data(sbi, inode->i_ino, ORPHAN_INO)) {
-			/*
-			 * get here because we failed to release resource
-			 * of inode previously, reminder our user to run fsck
-			 * for fixing.
-			 */
-			set_sbi_flag(sbi, SBI_NEED_FSCK);
-			f2fs_msg(sbi->sb, KERN_WARNING,
-				"inode (ino:%lu) resource leak, run fsck "
-				"to fix this issue!", inode->i_ino);
-		}
-	}
+	f2fs_bug_on(sbi, err &&
+		!exist_written_data(sbi, inode->i_ino, ORPHAN_INO));
 out_clear:
 	fscrypt_put_encryption_info(inode, NULL);
 	clear_inode(inode);
-- 
2.6.3

> 
> How about this patch?
> 
> --- a/fs/f2fs/inode.c
> +++ b/fs/f2fs/inode.c
> @@ -345,6 +345,7 @@ void f2fs_evict_inode(struct inode *inode)
>         set_inode_flag(fi, FI_NO_ALLOC);
>         i_size_write(inode, 0);
> 
> +retry:
>         if (F2FS_HAS_BLOCKS(inode))
>                 err = f2fs_truncate(inode, true);
> 
> @@ -354,6 +355,11 @@ void f2fs_evict_inode(struct inode *inode)
>                 f2fs_unlock_op(sbi);
>         }
> 
> +       if (err == -ENOMEM) {
> +               err = 0;
> +               goto retry;
> +       }
> +
>         sb_end_intwrite(inode->i_sb);
>  no_delete:
>         stat_dec_inline_xattr(inode);
> >Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> >---
> >  fs/f2fs/inode.c | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> >
> >diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
> >index f4ac851..5cccd7a 100644
> >--- a/fs/f2fs/inode.c
> >+++ b/fs/f2fs/inode.c
> >@@ -344,7 +344,7 @@ void f2fs_evict_inode(struct inode *inode)
> >  	sb_start_intwrite(inode->i_sb);
> >  	set_inode_flag(fi, FI_NO_ALLOC);
> >  	i_size_write(inode, 0);
> >-
> >+retry:
> >  	if (F2FS_HAS_BLOCKS(inode))
> >  		err = f2fs_truncate(inode, true);
> >
> >@@ -374,6 +374,11 @@ no_delete:
> >
> >  	if (err && err != -ENOENT) {
> >  		if (!exist_written_data(sbi, inode->i_ino, ORPHAN_INO)) {
> >+			/* give more chances, if ENOMEM case */
> >+			if (err == -ENOMEM) {
> >+				err = 0;
> >+				goto retry;
> >+			}
> >  			/*
> >  			 * get here because we failed to release resource
> >  			 * of inode previously, reminder our user to run fsck
> >
> 

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [f2fs-dev] [PATCH 05/11] f2fs: add mount option to select fault injection ratio
  2016-05-03 18:21 ` [PATCH 05/11] f2fs: add mount option to select fault injection ratio Jaegeuk Kim
@ 2016-05-09 12:00   ` Chao Yu
  0 siblings, 0 replies; 14+ messages in thread
From: Chao Yu @ 2016-05-09 12:00 UTC (permalink / raw)
  To: Jaegeuk Kim, linux-kernel, linux-fsdevel, linux-f2fs-devel

Hi Jaegeuk,

On 2016/5/4 2:21, Jaegeuk Kim wrote:
> This patch adds a mount option to select fault ratio.

It's better to add description in documentation for this new mount option.

Anyway, this patchset looks good to me, please add:

Acked-by: Chao Yu <yuchao0@huawei.com>

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2016-05-09 12:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-03 18:21 [PATCH 01/11] f2fs: introduce macros for proc entries Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 02/11] f2fs: add proc entry to show valid block bitmap Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 03/11] f2fs: introduce f2fs_kmalloc to wrap kmalloc Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 04/11] f2fs: use f2fs_grab_cache_page instead of grab_cache_page Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 05/11] f2fs: add mount option to select fault injection ratio Jaegeuk Kim
2016-05-09 12:00   ` [f2fs-dev] " Chao Yu
2016-05-03 18:21 ` [PATCH 06/11] f2fs: inject kmalloc failure Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 07/11] f2fs: inject page allocation failures Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 08/11] f2fs: inject ENOSPC failures Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 09/11] f2fs: revisit error handling flows Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 10/11] f2fs: fix leak of orphan inode objects Jaegeuk Kim
2016-05-03 18:21 ` [PATCH 11/11] f2fs: retry to truncate blocks in -ENOMEM case Jaegeuk Kim
2016-05-05  2:00   ` [f2fs-dev] " Hou Pengyang
2016-05-05  2:59     ` Jaegeuk Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).