From 7880ceedec55fbc3997d80e68670d03395225367 Mon Sep 17 00:00:00 2001
From: Huajun Li <huajun.li.lee@gmail.com>
Date: Mon, 31 Dec 2012 13:59:09 +0800
Subject: f2fs: update f2fs partition info about SIT/NAT layout

Update partition info output under debug FS to reflect segment layout correctly.

Signed-off-by: Huajun Li <huajun.li.lee@gmail.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
 fs/f2fs/debug.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'fs/f2fs/debug.c')

diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 0e0380a588a..b8ed7a72c6e 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -190,8 +190,8 @@ static int stat_show(struct seq_file *s, void *v)
 		update_general_status(si->sbi);
 
 		seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++);
-		seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
-			   si->nat_area_segs, si->sit_area_segs);
+		seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",
+			   si->sit_area_segs, si->nat_area_segs);
 		seq_printf(s, "[SSA: %d] [MAIN: %d",
 			   si->ssa_area_segs, si->main_area_segs);
 		seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
-- 
cgit v1.2.3-70-g09d2


From 66af62ce7588736ae65edfdb1c0df597775c4d21 Mon Sep 17 00:00:00 2001
From: majianpeng <majianpeng@gmail.com>
Date: Mon, 14 Jan 2013 20:08:16 +0800
Subject: f2fs: add global mutex_lock to protect f2fs_stat_list

There is an race condition between umounting f2fs and reading f2fs/status, which
results in oops.

Fox example:
Thread A			Thread B
umount f2fs 			cat f2fs/status

f2fs_destroy_stats() {		stat_show() {
				 list_for_each_entry_safe(&f2fs_stat_list)
 list_del(&si->stat_list);
 mutex_lock(&si->stat_lock);
 si->sbi = NULL;
 mutex_unlock(&si->stat_lock);
 kfree(sbi->stat_info);
} 				 mutex_lock(&si->stat_lock) <- si is gone.
				 ...
				}

Solution with a global lock: f2fs_stat_mutex:
Thread A			Thread B
umount f2fs 			cat f2fs/status

f2fs_destroy_stats() {		stat_show() {
 mutex_lock(&f2fs_stat_mutex);
 list_del(&si->stat_list);
 mutex_unlock(&f2fs_stat_mutex);
 kfree(sbi->stat_info);		 mutex_lock(&f2fs_stat_mutex);
}				 list_for_each_entry_safe(&f2fs_stat_list)
				 ...
				 mutex_unlock(&f2fs_stat_mutex);
				}

Signed-off-by: Jianpeng Ma <majianpeng@gmail.com>
[jaegeuk.kim@samsung.com: fix typos, description, and remove the existing lock]
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
 fs/f2fs/debug.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

(limited to 'fs/f2fs/debug.c')

diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index b8ed7a72c6e..73f034a9418 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -26,6 +26,7 @@
 
 static LIST_HEAD(f2fs_stat_list);
 static struct dentry *debugfs_root;
+static DEFINE_MUTEX(f2fs_stat_mutex);
 
 static void update_general_status(struct f2fs_sb_info *sbi)
 {
@@ -180,13 +181,9 @@ static int stat_show(struct seq_file *s, void *v)
 	int i = 0;
 	int j;
 
+	mutex_lock(&f2fs_stat_mutex);
 	list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) {
 
-		mutex_lock(&si->stat_lock);
-		if (!si->sbi) {
-			mutex_unlock(&si->stat_lock);
-			continue;
-		}
 		update_general_status(si->sbi);
 
 		seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++);
@@ -286,8 +283,8 @@ static int stat_show(struct seq_file *s, void *v)
 		seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n",
 				(si->base_mem + si->cache_mem) >> 10,
 				si->base_mem >> 10, si->cache_mem >> 10);
-		mutex_unlock(&si->stat_lock);
 	}
+	mutex_unlock(&f2fs_stat_mutex);
 	return 0;
 }
 
@@ -313,9 +310,6 @@ static int init_stats(struct f2fs_sb_info *sbi)
 		return -ENOMEM;
 
 	si = sbi->stat_info;
-	mutex_init(&si->stat_lock);
-	list_add_tail(&si->stat_list, &f2fs_stat_list);
-
 	si->all_area_segs = le32_to_cpu(raw_super->segment_count);
 	si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
 	si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
@@ -325,6 +319,11 @@ static int init_stats(struct f2fs_sb_info *sbi)
 	si->main_area_zones = si->main_area_sections /
 				le32_to_cpu(raw_super->secs_per_zone);
 	si->sbi = sbi;
+
+	mutex_lock(&f2fs_stat_mutex);
+	list_add_tail(&si->stat_list, &f2fs_stat_list);
+	mutex_unlock(&f2fs_stat_mutex);
+
 	return 0;
 }
 
@@ -347,10 +346,10 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_stat_info *si = sbi->stat_info;
 
+	mutex_lock(&f2fs_stat_mutex);
 	list_del(&si->stat_list);
-	mutex_lock(&si->stat_lock);
-	si->sbi = NULL;
-	mutex_unlock(&si->stat_lock);
+	mutex_unlock(&f2fs_stat_mutex);
+
 	kfree(sbi->stat_info);
 }
 
-- 
cgit v1.2.3-70-g09d2


From 4589d25d015c2d02bb5f7075d0cbf6dcf23a33c0 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <linkinjeon@gmail.com>
Date: Tue, 15 Jan 2013 19:58:47 +0900
Subject: f2fs: fix the debugfs entry creation path

As the "status" debugfs entry will be maintained for entire F2FS filesystem
irrespective of the number of partitions.
So, we can move the initialization to the init part of the f2fs and destroy will
be done from exit part. After making changes, for individual partition mount -
entry creation code will not be executed.

Signed-off-by: Jianpeng Ma <majianpeng@gmail.com>
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Amit Sahrawat <a.sahrawat@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
---
 fs/f2fs/debug.c | 27 ++++++++++-----------------
 fs/f2fs/f2fs.h  |  6 ++++--
 fs/f2fs/super.c |  7 +++++--
 3 files changed, 19 insertions(+), 21 deletions(-)

(limited to 'fs/f2fs/debug.c')

diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 73f034a9418..c8c37307b32 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -300,7 +300,7 @@ static const struct file_operations stat_fops = {
 	.release = single_release,
 };
 
-static int init_stats(struct f2fs_sb_info *sbi)
+int f2fs_build_stats(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
 	struct f2fs_stat_info *si;
@@ -327,21 +327,6 @@ static int init_stats(struct f2fs_sb_info *sbi)
 	return 0;
 }
 
-int f2fs_build_stats(struct f2fs_sb_info *sbi)
-{
-	int retval;
-
-	retval = init_stats(sbi);
-	if (retval)
-		return retval;
-
-	if (!debugfs_root)
-		debugfs_root = debugfs_create_dir("f2fs", NULL);
-
-	debugfs_create_file("status", S_IRUGO, debugfs_root, NULL, &stat_fops);
-	return 0;
-}
-
 void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_stat_info *si = sbi->stat_info;
@@ -353,7 +338,15 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
 	kfree(sbi->stat_info);
 }
 
-void destroy_root_stats(void)
+void __init f2fs_create_root_stats(void)
+{
+	debugfs_root = debugfs_create_dir("f2fs", NULL);
+	if (debugfs_root)
+		debugfs_create_file("status", S_IRUGO, debugfs_root,
+					 NULL, &stat_fops);
+}
+
+void f2fs_destroy_root_stats(void)
 {
 	debugfs_remove_recursive(debugfs_root);
 	debugfs_root = NULL;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 285e43d602f..976325d51e3 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1060,7 +1060,8 @@ struct f2fs_stat_info {
 
 int f2fs_build_stats(struct f2fs_sb_info *);
 void f2fs_destroy_stats(struct f2fs_sb_info *);
-void destroy_root_stats(void);
+void f2fs_create_root_stats(void);
+void f2fs_destroy_root_stats(void);
 #else
 #define stat_inc_call_count(si)
 #define stat_inc_seg_count(si, type)
@@ -1070,7 +1071,8 @@ void destroy_root_stats(void);
 
 static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; }
 static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { }
-static inline void destroy_root_stats(void) { }
+static inline void f2fs_create_root_stats(void) { }
+static inline void f2fs_destroy_root_stats(void) { }
 #endif
 
 extern const struct file_operations f2fs_dir_operations;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index ac127fde8e1..d551a724b73 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -675,14 +675,17 @@ static int __init init_f2fs_fs(void)
 	err = create_checkpoint_caches();
 	if (err)
 		goto fail;
-	return register_filesystem(&f2fs_fs_type);
+	err = register_filesystem(&f2fs_fs_type);
+	if (err)
+		goto fail;
+	f2fs_create_root_stats();
 fail:
 	return err;
 }
 
 static void __exit exit_f2fs_fs(void)
 {
-	destroy_root_stats();
+	f2fs_destroy_root_stats();
 	unregister_filesystem(&f2fs_fs_type);
 	destroy_checkpoint_caches();
 	destroy_gc_caches();
-- 
cgit v1.2.3-70-g09d2