aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2
diff options
context:
space:
mode:
authorHitoshi Mitake <mitake.hitoshi@lab.ntt.co.jp>2015-11-06 19:31:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-06 20:50:42 -0500
commit58497703837048ac501ce56056eb74b4361108fc (patch)
tree57165f47606930e10f15d475e999ccdf9a273e7f /fs/nilfs2
parentd0c14a9ee79467cd6a04b281577e1e6f74806ab2 (diff)
nilfs2: add a tracepoint for tracking stage transition of segment construction
This patch adds a tracepoint for tracking stage transition of block collection in segment construction. With the tracepoint, we can analysis the behavior of segment construction in depth. It would be useful for bottleneck detection and debugging, etc. The tracepoint is created with the standard trace API of linux (like ext3, ext4, f2fs and btrfs). So we can analysis with existing tools easily. Of course, more detailed analysis will be possible if we can create nilfs specific analysis tools. Below is an example of event dump with Brendan Gregg's perf-tools (https://github.com/brendangregg/perf-tools). Time consumption between each stage can be obtained. $ sudo bin/tpoint nilfs2:nilfs2_collection_stage_transition Tracing nilfs2:nilfs2_collection_stage_transition. Ctrl-C to end. segctord-14875 [003] ...1 28311.067794: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_INIT segctord-14875 [003] ...1 28311.068139: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_GC segctord-14875 [003] ...1 28311.068139: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_FILE segctord-14875 [003] ...1 28311.068486: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_IFILE segctord-14875 [003] ...1 28311.068540: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_CPFILE segctord-14875 [003] ...1 28311.068561: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_SUFILE segctord-14875 [003] ...1 28311.068565: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_DAT segctord-14875 [003] ...1 28311.068573: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_SR segctord-14875 [003] ...1 28311.068574: nilfs2_collection_stage_transition: sci = ffff8800ce6de000 stage = ST_DONE For capturing transition correctly, this patch adds wrappers for the member scnt of nilfs_cstage. With this change, every transition of the stage can produce trace event in a correct manner. Signed-off-by: Hitoshi Mitake <mitake.hitoshi@lab.ntt.co.jp> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Cc: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nilfs2')
-rw-r--r--fs/nilfs2/segment.c71
-rw-r--r--fs/nilfs2/segment.h3
2 files changed, 53 insertions, 21 deletions
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index c6abbad9b8e3..ef354043b87c 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -77,6 +77,36 @@ enum {
77 NILFS_ST_DONE, 77 NILFS_ST_DONE,
78}; 78};
79 79
80#define CREATE_TRACE_POINTS
81#include <trace/events/nilfs2.h>
82
83/*
84 * nilfs_sc_cstage_inc(), nilfs_sc_cstage_set(), nilfs_sc_cstage_get() are
85 * wrapper functions of stage count (nilfs_sc_info->sc_stage.scnt). Users of
86 * the variable must use them because transition of stage count must involve
87 * trace events (trace_nilfs2_collection_stage_transition).
88 *
89 * nilfs_sc_cstage_get() isn't required for the above purpose because it doesn't
90 * produce tracepoint events. It is provided just for making the intention
91 * clear.
92 */
93static inline void nilfs_sc_cstage_inc(struct nilfs_sc_info *sci)
94{
95 sci->sc_stage.scnt++;
96 trace_nilfs2_collection_stage_transition(sci);
97}
98
99static inline void nilfs_sc_cstage_set(struct nilfs_sc_info *sci, int next_scnt)
100{
101 sci->sc_stage.scnt = next_scnt;
102 trace_nilfs2_collection_stage_transition(sci);
103}
104
105static inline int nilfs_sc_cstage_get(struct nilfs_sc_info *sci)
106{
107 return sci->sc_stage.scnt;
108}
109
80/* State flags of collection */ 110/* State flags of collection */
81#define NILFS_CF_NODE 0x0001 /* Collecting node blocks */ 111#define NILFS_CF_NODE 0x0001 /* Collecting node blocks */
82#define NILFS_CF_IFILE_STARTED 0x0002 /* IFILE stage has started */ 112#define NILFS_CF_IFILE_STARTED 0x0002 /* IFILE stage has started */
@@ -1062,7 +1092,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1062 size_t ndone; 1092 size_t ndone;
1063 int err = 0; 1093 int err = 0;
1064 1094
1065 switch (sci->sc_stage.scnt) { 1095 switch (nilfs_sc_cstage_get(sci)) {
1066 case NILFS_ST_INIT: 1096 case NILFS_ST_INIT:
1067 /* Pre-processes */ 1097 /* Pre-processes */
1068 sci->sc_stage.flags = 0; 1098 sci->sc_stage.flags = 0;
@@ -1071,7 +1101,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1071 sci->sc_nblk_inc = 0; 1101 sci->sc_nblk_inc = 0;
1072 sci->sc_curseg->sb_sum.flags = NILFS_SS_LOGBGN; 1102 sci->sc_curseg->sb_sum.flags = NILFS_SS_LOGBGN;
1073 if (mode == SC_LSEG_DSYNC) { 1103 if (mode == SC_LSEG_DSYNC) {
1074 sci->sc_stage.scnt = NILFS_ST_DSYNC; 1104 nilfs_sc_cstage_set(sci, NILFS_ST_DSYNC);
1075 goto dsync_mode; 1105 goto dsync_mode;
1076 } 1106 }
1077 } 1107 }
@@ -1079,10 +1109,10 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1079 sci->sc_stage.dirty_file_ptr = NULL; 1109 sci->sc_stage.dirty_file_ptr = NULL;
1080 sci->sc_stage.gc_inode_ptr = NULL; 1110 sci->sc_stage.gc_inode_ptr = NULL;
1081 if (mode == SC_FLUSH_DAT) { 1111 if (mode == SC_FLUSH_DAT) {
1082 sci->sc_stage.scnt = NILFS_ST_DAT; 1112 nilfs_sc_cstage_set(sci, NILFS_ST_DAT);
1083 goto dat_stage; 1113 goto dat_stage;
1084 } 1114 }
1085 sci->sc_stage.scnt++; /* Fall through */ 1115 nilfs_sc_cstage_inc(sci); /* Fall through */
1086 case NILFS_ST_GC: 1116 case NILFS_ST_GC:
1087 if (nilfs_doing_gc()) { 1117 if (nilfs_doing_gc()) {
1088 head = &sci->sc_gc_inodes; 1118 head = &sci->sc_gc_inodes;
@@ -1103,7 +1133,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1103 } 1133 }
1104 sci->sc_stage.gc_inode_ptr = NULL; 1134 sci->sc_stage.gc_inode_ptr = NULL;
1105 } 1135 }
1106 sci->sc_stage.scnt++; /* Fall through */ 1136 nilfs_sc_cstage_inc(sci); /* Fall through */
1107 case NILFS_ST_FILE: 1137 case NILFS_ST_FILE:
1108 head = &sci->sc_dirty_files; 1138 head = &sci->sc_dirty_files;
1109 ii = list_prepare_entry(sci->sc_stage.dirty_file_ptr, head, 1139 ii = list_prepare_entry(sci->sc_stage.dirty_file_ptr, head,
@@ -1125,10 +1155,10 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1125 } 1155 }
1126 sci->sc_stage.dirty_file_ptr = NULL; 1156 sci->sc_stage.dirty_file_ptr = NULL;
1127 if (mode == SC_FLUSH_FILE) { 1157 if (mode == SC_FLUSH_FILE) {
1128 sci->sc_stage.scnt = NILFS_ST_DONE; 1158 nilfs_sc_cstage_set(sci, NILFS_ST_DONE);
1129 return 0; 1159 return 0;
1130 } 1160 }
1131 sci->sc_stage.scnt++; 1161 nilfs_sc_cstage_inc(sci);
1132 sci->sc_stage.flags |= NILFS_CF_IFILE_STARTED; 1162 sci->sc_stage.flags |= NILFS_CF_IFILE_STARTED;
1133 /* Fall through */ 1163 /* Fall through */
1134 case NILFS_ST_IFILE: 1164 case NILFS_ST_IFILE:
@@ -1136,7 +1166,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1136 &nilfs_sc_file_ops); 1166 &nilfs_sc_file_ops);
1137 if (unlikely(err)) 1167 if (unlikely(err))
1138 break; 1168 break;
1139 sci->sc_stage.scnt++; 1169 nilfs_sc_cstage_inc(sci);
1140 /* Creating a checkpoint */ 1170 /* Creating a checkpoint */
1141 err = nilfs_segctor_create_checkpoint(sci); 1171 err = nilfs_segctor_create_checkpoint(sci);
1142 if (unlikely(err)) 1172 if (unlikely(err))
@@ -1147,7 +1177,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1147 &nilfs_sc_file_ops); 1177 &nilfs_sc_file_ops);
1148 if (unlikely(err)) 1178 if (unlikely(err))
1149 break; 1179 break;
1150 sci->sc_stage.scnt++; /* Fall through */ 1180 nilfs_sc_cstage_inc(sci); /* Fall through */
1151 case NILFS_ST_SUFILE: 1181 case NILFS_ST_SUFILE:
1152 err = nilfs_sufile_freev(nilfs->ns_sufile, sci->sc_freesegs, 1182 err = nilfs_sufile_freev(nilfs->ns_sufile, sci->sc_freesegs,
1153 sci->sc_nfreesegs, &ndone); 1183 sci->sc_nfreesegs, &ndone);
@@ -1163,7 +1193,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1163 &nilfs_sc_file_ops); 1193 &nilfs_sc_file_ops);
1164 if (unlikely(err)) 1194 if (unlikely(err))
1165 break; 1195 break;
1166 sci->sc_stage.scnt++; /* Fall through */ 1196 nilfs_sc_cstage_inc(sci); /* Fall through */
1167 case NILFS_ST_DAT: 1197 case NILFS_ST_DAT:
1168 dat_stage: 1198 dat_stage:
1169 err = nilfs_segctor_scan_file(sci, nilfs->ns_dat, 1199 err = nilfs_segctor_scan_file(sci, nilfs->ns_dat,
@@ -1171,10 +1201,10 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1171 if (unlikely(err)) 1201 if (unlikely(err))
1172 break; 1202 break;
1173 if (mode == SC_FLUSH_DAT) { 1203 if (mode == SC_FLUSH_DAT) {
1174 sci->sc_stage.scnt = NILFS_ST_DONE; 1204 nilfs_sc_cstage_set(sci, NILFS_ST_DONE);
1175 return 0; 1205 return 0;
1176 } 1206 }
1177 sci->sc_stage.scnt++; /* Fall through */ 1207 nilfs_sc_cstage_inc(sci); /* Fall through */
1178 case NILFS_ST_SR: 1208 case NILFS_ST_SR:
1179 if (mode == SC_LSEG_SR) { 1209 if (mode == SC_LSEG_SR) {
1180 /* Appending a super root */ 1210 /* Appending a super root */
@@ -1184,7 +1214,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1184 } 1214 }
1185 /* End of a logical segment */ 1215 /* End of a logical segment */
1186 sci->sc_curseg->sb_sum.flags |= NILFS_SS_LOGEND; 1216 sci->sc_curseg->sb_sum.flags |= NILFS_SS_LOGEND;
1187 sci->sc_stage.scnt = NILFS_ST_DONE; 1217 nilfs_sc_cstage_set(sci, NILFS_ST_DONE);
1188 return 0; 1218 return 0;
1189 case NILFS_ST_DSYNC: 1219 case NILFS_ST_DSYNC:
1190 dsync_mode: 1220 dsync_mode:
@@ -1197,7 +1227,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1197 if (unlikely(err)) 1227 if (unlikely(err))
1198 break; 1228 break;
1199 sci->sc_curseg->sb_sum.flags |= NILFS_SS_LOGEND; 1229 sci->sc_curseg->sb_sum.flags |= NILFS_SS_LOGEND;
1200 sci->sc_stage.scnt = NILFS_ST_DONE; 1230 nilfs_sc_cstage_set(sci, NILFS_ST_DONE);
1201 return 0; 1231 return 0;
1202 case NILFS_ST_DONE: 1232 case NILFS_ST_DONE:
1203 return 0; 1233 return 0;
@@ -1442,7 +1472,8 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
1442 goto failed; 1472 goto failed;
1443 1473
1444 /* The current segment is filled up */ 1474 /* The current segment is filled up */
1445 if (mode != SC_LSEG_SR || sci->sc_stage.scnt < NILFS_ST_CPFILE) 1475 if (mode != SC_LSEG_SR ||
1476 nilfs_sc_cstage_get(sci) < NILFS_ST_CPFILE)
1446 break; 1477 break;
1447 1478
1448 nilfs_clear_logs(&sci->sc_segbufs); 1479 nilfs_clear_logs(&sci->sc_segbufs);
@@ -1946,7 +1977,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
1946 struct the_nilfs *nilfs = sci->sc_super->s_fs_info; 1977 struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
1947 int err; 1978 int err;
1948 1979
1949 sci->sc_stage.scnt = NILFS_ST_INIT; 1980 nilfs_sc_cstage_set(sci, NILFS_ST_INIT);
1950 sci->sc_cno = nilfs->ns_cno; 1981 sci->sc_cno = nilfs->ns_cno;
1951 1982
1952 err = nilfs_segctor_collect_dirty_files(sci, nilfs); 1983 err = nilfs_segctor_collect_dirty_files(sci, nilfs);
@@ -1974,7 +2005,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
1974 goto failed; 2005 goto failed;
1975 2006
1976 /* Avoid empty segment */ 2007 /* Avoid empty segment */
1977 if (sci->sc_stage.scnt == NILFS_ST_DONE && 2008 if (nilfs_sc_cstage_get(sci) == NILFS_ST_DONE &&
1978 nilfs_segbuf_empty(sci->sc_curseg)) { 2009 nilfs_segbuf_empty(sci->sc_curseg)) {
1979 nilfs_segctor_abort_construction(sci, nilfs, 1); 2010 nilfs_segctor_abort_construction(sci, nilfs, 1);
1980 goto out; 2011 goto out;
@@ -1988,7 +2019,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
1988 nilfs_segctor_fill_in_file_bmap(sci); 2019 nilfs_segctor_fill_in_file_bmap(sci);
1989 2020
1990 if (mode == SC_LSEG_SR && 2021 if (mode == SC_LSEG_SR &&
1991 sci->sc_stage.scnt >= NILFS_ST_CPFILE) { 2022 nilfs_sc_cstage_get(sci) >= NILFS_ST_CPFILE) {
1992 err = nilfs_segctor_fill_in_checkpoint(sci); 2023 err = nilfs_segctor_fill_in_checkpoint(sci);
1993 if (unlikely(err)) 2024 if (unlikely(err))
1994 goto failed_to_write; 2025 goto failed_to_write;
@@ -2007,7 +2038,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
2007 if (unlikely(err)) 2038 if (unlikely(err))
2008 goto failed_to_write; 2039 goto failed_to_write;
2009 2040
2010 if (sci->sc_stage.scnt == NILFS_ST_DONE || 2041 if (nilfs_sc_cstage_get(sci) == NILFS_ST_DONE ||
2011 nilfs->ns_blocksize_bits != PAGE_CACHE_SHIFT) { 2042 nilfs->ns_blocksize_bits != PAGE_CACHE_SHIFT) {
2012 /* 2043 /*
2013 * At this point, we avoid double buffering 2044 * At this point, we avoid double buffering
@@ -2020,7 +2051,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
2020 if (err) 2051 if (err)
2021 goto failed_to_write; 2052 goto failed_to_write;
2022 } 2053 }
2023 } while (sci->sc_stage.scnt != NILFS_ST_DONE); 2054 } while (nilfs_sc_cstage_get(sci) != NILFS_ST_DONE);
2024 2055
2025 out: 2056 out:
2026 nilfs_segctor_drop_written_files(sci, nilfs); 2057 nilfs_segctor_drop_written_files(sci, nilfs);
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index a48d6de1e02c..0408b9b2814b 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -67,7 +67,8 @@ struct nilfs_recovery_info {
67 67
68/** 68/**
69 * struct nilfs_cstage - Context of collection stage 69 * struct nilfs_cstage - Context of collection stage
70 * @scnt: Stage count 70 * @scnt: Stage count, must be accessed via wrappers:
71 * nilfs_sc_cstage_inc(), nilfs_sc_cstage_set(), nilfs_sc_cstage_get()
71 * @flags: State flags 72 * @flags: State flags
72 * @dirty_file_ptr: Pointer on dirty_files list, or inode of a target file 73 * @dirty_file_ptr: Pointer on dirty_files list, or inode of a target file
73 * @gc_inode_ptr: Pointer on the list of gc-inodes 74 * @gc_inode_ptr: Pointer on the list of gc-inodes