aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-fs-f2fs6
-rw-r--r--fs/f2fs/checkpoint.c11
-rw-r--r--fs/f2fs/f2fs.h11
-rw-r--r--fs/f2fs/super.c39
-rw-r--r--include/linux/f2fs_fs.h14
5 files changed, 78 insertions, 3 deletions
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 523cb9d4e272..a809f6005f14 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -106,3 +106,9 @@ Description:
106 Controls dirty nat entries ratio threshold, if current 106 Controls dirty nat entries ratio threshold, if current
107 ratio exceeds configured threshold, checkpoint will 107 ratio exceeds configured threshold, checkpoint will
108 be triggered for flushing dirty nat entries. 108 be triggered for flushing dirty nat entries.
109
110What: /sys/fs/f2fs/<disk>/lifetime_write_kbytes
111Date: January 2016
112Contact: "Shuoran Liu" <liushuoran@huawei.com>
113Description:
114 Shows total written kbytes issued to disk.
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 4b6f9c08f6fa..112e19fdbe08 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -921,6 +921,9 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
921 int cp_payload_blks = __cp_payload(sbi); 921 int cp_payload_blks = __cp_payload(sbi);
922 block_t discard_blk = NEXT_FREE_BLKADDR(sbi, curseg); 922 block_t discard_blk = NEXT_FREE_BLKADDR(sbi, curseg);
923 bool invalidate = false; 923 bool invalidate = false;
924 struct super_block *sb = sbi->sb;
925 struct curseg_info *seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE);
926 u64 kbytes_written;
924 927
925 /* 928 /*
926 * This avoids to conduct wrong roll-forward operations and uses 929 * This avoids to conduct wrong roll-forward operations and uses
@@ -1034,6 +1037,14 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
1034 1037
1035 write_data_summaries(sbi, start_blk); 1038 write_data_summaries(sbi, start_blk);
1036 start_blk += data_sum_blocks; 1039 start_blk += data_sum_blocks;
1040
1041 /* Record write statistics in the hot node summary */
1042 kbytes_written = sbi->kbytes_written;
1043 if (sb->s_bdev->bd_part)
1044 kbytes_written += BD_PART_WRITTEN(sbi);
1045
1046 seg_i->sum_blk->info.kbytes_written = cpu_to_le64(kbytes_written);
1047
1037 if (__remain_node_summaries(cpc->reason)) { 1048 if (__remain_node_summaries(cpc->reason)) {
1038 write_node_summaries(sbi, start_blk); 1049 write_node_summaries(sbi, start_blk);
1039 start_blk += NR_CURSEG_NODE_TYPE; 1050 start_blk += NR_CURSEG_NODE_TYPE;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 4e7eab9f3f5a..5b6fd541551c 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -846,8 +846,19 @@ struct f2fs_sb_info {
846 struct list_head s_list; 846 struct list_head s_list;
847 struct mutex umount_mutex; 847 struct mutex umount_mutex;
848 unsigned int shrinker_run_no; 848 unsigned int shrinker_run_no;
849
850 /* For write statistics */
851 u64 sectors_written_start;
852 u64 kbytes_written;
849}; 853};
850 854
855/* For write statistics. Suppose sector size is 512 bytes,
856 * and the return value is in kbytes. s is of struct f2fs_sb_info.
857 */
858#define BD_PART_WRITTEN(s) \
859(((u64)part_stat_read(s->sb->s_bdev->bd_part, sectors[1]) - \
860 s->sectors_written_start) >> 1)
861
851static inline void f2fs_update_time(struct f2fs_sb_info *sbi, int type) 862static inline void f2fs_update_time(struct f2fs_sb_info *sbi, int type)
852{ 863{
853 sbi->last_time[type] = jiffies; 864 sbi->last_time[type] = jiffies;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 0ea5bcccab6d..58d9a5574bb0 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -126,6 +126,19 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
126 return NULL; 126 return NULL;
127} 127}
128 128
129static ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a,
130 struct f2fs_sb_info *sbi, char *buf)
131{
132 struct super_block *sb = sbi->sb;
133
134 if (!sb->s_bdev->bd_part)
135 return snprintf(buf, PAGE_SIZE, "0\n");
136
137 return snprintf(buf, PAGE_SIZE, "%llu\n",
138 (unsigned long long)(sbi->kbytes_written +
139 BD_PART_WRITTEN(sbi)));
140}
141
129static ssize_t f2fs_sbi_show(struct f2fs_attr *a, 142static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
130 struct f2fs_sb_info *sbi, char *buf) 143 struct f2fs_sb_info *sbi, char *buf)
131{ 144{
@@ -204,6 +217,9 @@ static struct f2fs_attr f2fs_attr_##_name = { \
204 f2fs_sbi_show, f2fs_sbi_store, \ 217 f2fs_sbi_show, f2fs_sbi_store, \
205 offsetof(struct struct_name, elname)) 218 offsetof(struct struct_name, elname))
206 219
220#define F2FS_GENERAL_RO_ATTR(name) \
221static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL)
222
207F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time); 223F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
208F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time); 224F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
209F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time); 225F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
@@ -221,6 +237,7 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
221F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); 237F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
222F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); 238F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]);
223F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); 239F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
240F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
224 241
225#define ATTR_LIST(name) (&f2fs_attr_##name.attr) 242#define ATTR_LIST(name) (&f2fs_attr_##name.attr)
226static struct attribute *f2fs_attrs[] = { 243static struct attribute *f2fs_attrs[] = {
@@ -241,6 +258,7 @@ static struct attribute *f2fs_attrs[] = {
241 ATTR_LIST(dirty_nats_ratio), 258 ATTR_LIST(dirty_nats_ratio),
242 ATTR_LIST(cp_interval), 259 ATTR_LIST(cp_interval),
243 ATTR_LIST(idle_interval), 260 ATTR_LIST(idle_interval),
261 ATTR_LIST(lifetime_write_kbytes),
244 NULL, 262 NULL,
245}; 263};
246 264
@@ -768,8 +786,6 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
768 bool need_stop_gc = false; 786 bool need_stop_gc = false;
769 bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE); 787 bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE);
770 788
771 sync_filesystem(sb);
772
773 /* 789 /*
774 * Save the old mount options in case we 790 * Save the old mount options in case we
775 * need to restore them. 791 * need to restore them.
@@ -777,6 +793,13 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
777 org_mount_opt = sbi->mount_opt; 793 org_mount_opt = sbi->mount_opt;
778 active_logs = sbi->active_logs; 794 active_logs = sbi->active_logs;
779 795
796 if (*flags & MS_RDONLY) {
797 set_opt(sbi, FASTBOOT);
798 set_sbi_flag(sbi, SBI_IS_DIRTY);
799 }
800
801 sync_filesystem(sb);
802
780 sbi->mount_opt.opt = 0; 803 sbi->mount_opt.opt = 0;
781 default_options(sbi); 804 default_options(sbi);
782 805
@@ -1244,6 +1267,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
1244 bool retry = true, need_fsck = false; 1267 bool retry = true, need_fsck = false;
1245 char *options = NULL; 1268 char *options = NULL;
1246 int recovery, i, valid_super_block; 1269 int recovery, i, valid_super_block;
1270 struct curseg_info *seg_i;
1247 1271
1248try_onemore: 1272try_onemore:
1249 err = -EINVAL; 1273 err = -EINVAL;
@@ -1374,6 +1398,17 @@ try_onemore:
1374 goto free_nm; 1398 goto free_nm;
1375 } 1399 }
1376 1400
1401 /* For write statistics */
1402 if (sb->s_bdev->bd_part)
1403 sbi->sectors_written_start =
1404 (u64)part_stat_read(sb->s_bdev->bd_part, sectors[1]);
1405
1406 /* Read accumulated write IO statistics if exists */
1407 seg_i = CURSEG_I(sbi, CURSEG_HOT_NODE);
1408 if (__exist_node_summaries(sbi))
1409 sbi->kbytes_written =
1410 le64_to_cpu(seg_i->sum_blk->info.kbytes_written);
1411
1377 build_gc_manager(sbi); 1412 build_gc_manager(sbi);
1378 1413
1379 /* get an inode for node space */ 1414 /* get an inode for node space */
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index e59c3be92106..67aa01df777d 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -358,6 +358,12 @@ struct summary_footer {
358 sizeof(struct sit_journal_entry)) 358 sizeof(struct sit_journal_entry))
359#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\ 359#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
360 sizeof(struct sit_journal_entry)) 360 sizeof(struct sit_journal_entry))
361
362/* Reserved area should make size of f2fs_extra_info equals to
363 * that of nat_journal and sit_journal.
364 */
365#define EXTRA_INFO_RESERVED (SUM_JOURNAL_SIZE - 2 - 8)
366
361/* 367/*
362 * frequently updated NAT/SIT entries can be stored in the spare area in 368 * frequently updated NAT/SIT entries can be stored in the spare area in
363 * summary blocks 369 * summary blocks
@@ -387,6 +393,11 @@ struct sit_journal {
387 __u8 reserved[SIT_JOURNAL_RESERVED]; 393 __u8 reserved[SIT_JOURNAL_RESERVED];
388} __packed; 394} __packed;
389 395
396struct f2fs_extra_info {
397 __le64 kbytes_written;
398 __u8 reserved[EXTRA_INFO_RESERVED];
399} __packed;
400
390/* 4KB-sized summary block structure */ 401/* 4KB-sized summary block structure */
391struct f2fs_summary_block { 402struct f2fs_summary_block {
392 struct f2fs_summary entries[ENTRIES_IN_SUM]; 403 struct f2fs_summary entries[ENTRIES_IN_SUM];
@@ -394,10 +405,11 @@ struct f2fs_summary_block {
394 __le16 n_nats; 405 __le16 n_nats;
395 __le16 n_sits; 406 __le16 n_sits;
396 }; 407 };
397 /* spare area is used by NAT or SIT journals */ 408 /* spare area is used by NAT or SIT journals or extra info */
398 union { 409 union {
399 struct nat_journal nat_j; 410 struct nat_journal nat_j;
400 struct sit_journal sit_j; 411 struct sit_journal sit_j;
412 struct f2fs_extra_info info;
401 }; 413 };
402 struct summary_footer footer; 414 struct summary_footer footer;
403} __packed; 415} __packed;