diff options
Diffstat (limited to 'kernel/trace/trace_stat.c')
-rw-r--r-- | kernel/trace/trace_stat.c | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c index 39310e3434ee..acdebd771a93 100644 --- a/kernel/trace/trace_stat.c +++ b/kernel/trace/trace_stat.c | |||
@@ -75,7 +75,7 @@ static int stat_seq_init(struct tracer_stat_session *session) | |||
75 | { | 75 | { |
76 | struct trace_stat_list *iter_entry, *new_entry; | 76 | struct trace_stat_list *iter_entry, *new_entry; |
77 | struct tracer_stat *ts = session->ts; | 77 | struct tracer_stat *ts = session->ts; |
78 | void *prev_stat; | 78 | void *stat; |
79 | int ret = 0; | 79 | int ret = 0; |
80 | int i; | 80 | int i; |
81 | 81 | ||
@@ -85,6 +85,10 @@ static int stat_seq_init(struct tracer_stat_session *session) | |||
85 | if (!ts->stat_cmp) | 85 | if (!ts->stat_cmp) |
86 | ts->stat_cmp = dummy_cmp; | 86 | ts->stat_cmp = dummy_cmp; |
87 | 87 | ||
88 | stat = ts->stat_start(); | ||
89 | if (!stat) | ||
90 | goto exit; | ||
91 | |||
88 | /* | 92 | /* |
89 | * The first entry. Actually this is the second, but the first | 93 | * The first entry. Actually this is the second, but the first |
90 | * one (the stat_list head) is pointless. | 94 | * one (the stat_list head) is pointless. |
@@ -99,14 +103,19 @@ static int stat_seq_init(struct tracer_stat_session *session) | |||
99 | 103 | ||
100 | list_add(&new_entry->list, &session->stat_list); | 104 | list_add(&new_entry->list, &session->stat_list); |
101 | 105 | ||
102 | new_entry->stat = ts->stat_start(); | 106 | new_entry->stat = stat; |
103 | prev_stat = new_entry->stat; | ||
104 | 107 | ||
105 | /* | 108 | /* |
106 | * Iterate over the tracer stat entries and store them in a sorted | 109 | * Iterate over the tracer stat entries and store them in a sorted |
107 | * list. | 110 | * list. |
108 | */ | 111 | */ |
109 | for (i = 1; ; i++) { | 112 | for (i = 1; ; i++) { |
113 | stat = ts->stat_next(stat, i); | ||
114 | |||
115 | /* End of insertion */ | ||
116 | if (!stat) | ||
117 | break; | ||
118 | |||
110 | new_entry = kmalloc(sizeof(struct trace_stat_list), GFP_KERNEL); | 119 | new_entry = kmalloc(sizeof(struct trace_stat_list), GFP_KERNEL); |
111 | if (!new_entry) { | 120 | if (!new_entry) { |
112 | ret = -ENOMEM; | 121 | ret = -ENOMEM; |
@@ -114,31 +123,23 @@ static int stat_seq_init(struct tracer_stat_session *session) | |||
114 | } | 123 | } |
115 | 124 | ||
116 | INIT_LIST_HEAD(&new_entry->list); | 125 | INIT_LIST_HEAD(&new_entry->list); |
117 | new_entry->stat = ts->stat_next(prev_stat, i); | 126 | new_entry->stat = stat; |
118 | 127 | ||
119 | /* End of insertion */ | 128 | list_for_each_entry_reverse(iter_entry, &session->stat_list, |
120 | if (!new_entry->stat) | 129 | list) { |
121 | break; | ||
122 | |||
123 | list_for_each_entry(iter_entry, &session->stat_list, list) { | ||
124 | 130 | ||
125 | /* Insertion with a descendent sorting */ | 131 | /* Insertion with a descendent sorting */ |
126 | if (ts->stat_cmp(new_entry->stat, | 132 | if (ts->stat_cmp(iter_entry->stat, |
127 | iter_entry->stat) > 0) { | 133 | new_entry->stat) >= 0) { |
128 | |||
129 | list_add_tail(&new_entry->list, | ||
130 | &iter_entry->list); | ||
131 | break; | ||
132 | 134 | ||
133 | /* The current smaller value */ | ||
134 | } else if (list_is_last(&iter_entry->list, | ||
135 | &session->stat_list)) { | ||
136 | list_add(&new_entry->list, &iter_entry->list); | 135 | list_add(&new_entry->list, &iter_entry->list); |
137 | break; | 136 | break; |
138 | } | 137 | } |
139 | } | 138 | } |
140 | 139 | ||
141 | prev_stat = new_entry->stat; | 140 | /* The current larger value */ |
141 | if (list_empty(&new_entry->list)) | ||
142 | list_add(&new_entry->list, &session->stat_list); | ||
142 | } | 143 | } |
143 | exit: | 144 | exit: |
144 | mutex_unlock(&session->stat_mutex); | 145 | mutex_unlock(&session->stat_mutex); |
@@ -160,7 +161,7 @@ static void *stat_seq_start(struct seq_file *s, loff_t *pos) | |||
160 | 161 | ||
161 | /* If we are in the beginning of the file, print the headers */ | 162 | /* If we are in the beginning of the file, print the headers */ |
162 | if (!*pos && session->ts->stat_headers) | 163 | if (!*pos && session->ts->stat_headers) |
163 | session->ts->stat_headers(s); | 164 | return SEQ_START_TOKEN; |
164 | 165 | ||
165 | return seq_list_start(&session->stat_list, *pos); | 166 | return seq_list_start(&session->stat_list, *pos); |
166 | } | 167 | } |
@@ -169,6 +170,9 @@ static void *stat_seq_next(struct seq_file *s, void *p, loff_t *pos) | |||
169 | { | 170 | { |
170 | struct tracer_stat_session *session = s->private; | 171 | struct tracer_stat_session *session = s->private; |
171 | 172 | ||
173 | if (p == SEQ_START_TOKEN) | ||
174 | return seq_list_start(&session->stat_list, *pos); | ||
175 | |||
172 | return seq_list_next(p, &session->stat_list, pos); | 176 | return seq_list_next(p, &session->stat_list, pos); |
173 | } | 177 | } |
174 | 178 | ||
@@ -183,6 +187,9 @@ static int stat_seq_show(struct seq_file *s, void *v) | |||
183 | struct tracer_stat_session *session = s->private; | 187 | struct tracer_stat_session *session = s->private; |
184 | struct trace_stat_list *l = list_entry(v, struct trace_stat_list, list); | 188 | struct trace_stat_list *l = list_entry(v, struct trace_stat_list, list); |
185 | 189 | ||
190 | if (v == SEQ_START_TOKEN) | ||
191 | return session->ts->stat_headers(s); | ||
192 | |||
186 | return session->ts->stat_show(s, l->stat); | 193 | return session->ts->stat_show(s, l->stat); |
187 | } | 194 | } |
188 | 195 | ||