My favorites | Sign in
Project Logo
                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
Boot tracing and prefetching support, uses prefetch core.

Signed-off-by: Krzysztof Lichota <krzysiek@lichota.net>


---

init/Kconfig | 8 +
mm/Makefile | 1
mm/prefetch_boot.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 399 insertions(+), 0 deletions(-)
create mode 100644 mm/prefetch_boot.c

e11c0867f81dd458a8d178e999b184e1f79faa57
diff --git a/init/Kconfig b/init/Kconfig
index 9ba6032..0f7f777 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -114,6 +114,14 @@ config PREFETCH_CORE
The core provides functions used by real prefetching modules,
so you have to enable one of them also.

+config PREFETCH_BOOT
+ tristate "Boot prefetching support"
+ default n
+ depends on PREFETCH_CORE && PROC_FS
+ help
+ This option enables facility for tracing and prefetching during system boot.
+ In order to use it you have to install appropriate prefetch init scripts.
+
config SYSVIPC
bool "System V IPC"
---help---
diff --git a/mm/Makefile b/mm/Makefile
index dee5c46..2c4e30c 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -32,4 +32,5 @@ obj-$(CONFIG_MIGRATION) += migrate.o
obj-$(CONFIG_SMP) += allocpercpu.o
obj-$(CONFIG_QUICKLIST) += quicklist.o
obj-$(CONFIG_PREFETCH_CORE) += prefetch_core.o
+obj-$(CONFIG_PREFETCH_BOOT) += prefetch_boot.o

diff --git a/mm/prefetch_boot.c b/mm/prefetch_boot.c
new file mode 100644
index 0000000..94cf994
--- /dev/null
+++ b/mm/prefetch_boot.c
@@ -0,0 +1,390 @@
+/*
+ * linux/mm/prefetch_core.c
+ *
+ * Copyright (C) 2007 Krzysztof Lichota <lichota@mimuw.edu.pl>
+ *
+ * This is boot prefetch support implementation.
+ * It consists mainly of proc interface, the rest is done by init scripts using proc interface.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/prefetch_core.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/limits.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <asm/current.h>
+
+
+/*************** Boot tracing **************/
+#define DEFAULT_BOOT_TRACE_FILENAME_TEMPLATE "/.prefetch-boot-trace.%s"
+char *filename_template = DEFAULT_BOOT_TRACE_FILENAME_TEMPLATE;
+module_param(filename_template, charp, 0);
+MODULE_PARM_DESC(filename_template, "Template for boot trace name, where trace will be saved and read from. %s will be replaced with name of phase. The default is: " DEFAULT_BOOT_TRACE_FILENAME_TEMPLATE);
+
+///maximum size of phase name, not including trailing NULL
+#define PHASE_NAME_MAX 10
+///maximum size as string, keep in sync with PHASE_NAME_MAX
+#define PHASE_NAME_MAX_S "10"
+
+///maximum size of command name, not including trailing NULL
+#define CMD_NAME_MAX 10
+///maximum size as string, keep in sync with CMD_NAME_MAX
+#define CMD_NAME_MAX_S "10"
+
+///Enables/disables whole functionality of the module
+static int enabled = 1;
+module_param(enabled, bool, 0);
+MODULE_PARM_DESC(enabled, "Enables or disables whole boot prefetching module functionality (tracing and prefetching)");
+
+///Controls whether prefetching should be done along with tracing.
+static int prefetch_enabled = 1;
+module_param(prefetch_enabled, bool, 0);
+MODULE_PARM_DESC(prefetch_enabled, "Enables or disables prefetching during boot. If disabled, only tracing will be done");
+
+static struct mutex boot_prefetch_mutex;
+/**
+ * Phase start marker, protected by boot_prefetch_mutex.
+*/
+static trace_marker_t boot_start_marker;
+static char boot_tracing_phase[PHASE_NAME_MAX + 1] = "init";
+static int boot_tracing_running = 0;
+
+/**
+ Saves boot trace fragment for phase @phase_name which
+ starts at boot_start_marker and ends at @end_phase_marker.
+
+ boot_prefetch_mutex must be held while calling this function.
+*/
+static int prefetch_save_boot_trace(
+ char *phase_name,
+ trace_marker_t end_phase_marker
+ )
+{
+ char *boot_trace_filename = NULL;
+ int ret = 0;
+
+ boot_trace_filename = kasprintf(GFP_KERNEL, filename_template,
+ phase_name
+ );
+
+ if (boot_trace_filename == NULL) {
+ printk(KERN_WARNING "Cannot allocate memory for trace filename in phase %s\n", phase_name);
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = prefetch_save_trace_fragment(
+ boot_start_marker,
+ end_phase_marker,
+ boot_trace_filename
+ );
+out:
+ if (boot_trace_filename != NULL)
+ kfree(boot_trace_filename);
+ return ret;
+}
+
+/**
+ Starts tracing for given boot phase.
+ boot_prefetch_mutex is taken by this function.
+*/
+int prefetch_start_boot_tracing_phase(char *phase_name)
+{
+ int r;
+ int ret = 0;
+ trace_marker_t marker;
+
+ mutex_lock(&boot_prefetch_mutex);
+
+ if (boot_tracing_running) {
+ //boot tracing was already running
+ ret = prefetch_continue_trace(&marker);
+ if (ret < 0) {
+ printk(KERN_WARNING "Cannot continue tracing, error=%d\n", ret);
+ goto out_unlock;
+ }
+
+ r = prefetch_save_boot_trace(boot_tracing_phase, marker);
+ if (r < 0)
+ //NOTE: just warn and continue, prefetching might still succeed and phase has been started
+ printk(KERN_WARNING "Saving boot trace failed, phase %s, error=%d\n", boot_tracing_phase, r);
+
+ boot_start_marker = marker;
+ } else {
+ //first phase of tracing
+ ret = prefetch_start_trace(&boot_start_marker);
+ if (ret < 0) {
+ printk(KERN_WARNING "Cannot start tracing, error=%d\n", ret);
+ goto out_unlock;
+ }
+ }
+
+ strncpy(boot_tracing_phase, phase_name, PHASE_NAME_MAX);
+ boot_tracing_phase[PHASE_NAME_MAX] = 0;
+
+ boot_tracing_running = 1;
+
+#ifdef PREFETCH_DEBUG
+ printk(KERN_INFO "Boot command %s, phase %s marker: ", cmd_name, phase_name);
+ print_marker("Marker: ", boot_start_marker);
+#endif
+out_unlock:
+ mutex_unlock(&boot_prefetch_mutex);
+ return ret;
+}
+
+int prefetch_start_boot_prefetching_phase(char *phase_name)
+{
+ char *boot_trace_filename = NULL;
+ int ret = 0;
+ if (!prefetch_enabled) {
+ printk(KERN_INFO "Prefetching disabled, not starting prefetching for boot phase: %s\n", phase_name);
+ return 0;
+ }
+
+ boot_trace_filename = kasprintf(GFP_KERNEL, filename_template,
+ phase_name
+ );
+
+ if (boot_trace_filename == NULL) {
+ printk(KERN_WARNING "Cannot allocate memory for trace filename\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ printk(KERN_INFO "Starting prefetching for boot phase: %s\n", phase_name);
+ ret = do_prefetch_from_file(boot_trace_filename);
+
+ if (ret < 0)
+ printk("Failed to prefetch trace from file %s, error=%d\n", boot_trace_filename, ret);
+
+out:
+ if (boot_trace_filename != NULL)
+ kfree(boot_trace_filename);
+
+ return ret;
+}
+
+
+
+/**
+ Starts next phase of boot.
+ Starts tracing. Then, if trace is available, loads it and starts
+ prefetch.
+ @cmd_name is the name of action, if you want to keep its contents,
+ copy it somewhere, as it will be deallocated.
+ @phase_name is the name of new phase, if you want to keep its contents,
+ copy it somewhere, as it will be deallocated.
+*/
+static int prefetch_start_boot_phase(char *cmd_name, char *phase_name)
+{
+ int ret = 0;
+ int start_prefetching = 0;
+ int start_tracing = 0;
+
+ if (strcmp(cmd_name, "prefetch") == 0)
+ start_prefetching = 1;
+ else if (strcmp(cmd_name, "trace") == 0)
+ start_tracing = 1;
+ else if (strcmp(cmd_name, "both") == 0) {
+ start_prefetching = 1;
+ start_tracing = 1;
+ } else {
+ printk(KERN_WARNING "Boot prefetch: unknown command: %s for phase %s\n",
+ cmd_name,
+ phase_name
+ );
+ return -EINVAL;
+ }
+ if (start_tracing)
+ prefetch_start_boot_tracing_phase(phase_name);
+
+ if (start_prefetching)
+ ret = prefetch_start_boot_prefetching_phase(phase_name);
+
+ return ret;
+}
+
+static int prefetch_stop_boot_tracing(void)
+{
+ trace_marker_t marker;
+ int ret = 0;
+ printk(KERN_INFO "Stopping boot tracing and prefetching\n");
+
+ mutex_lock(&boot_prefetch_mutex);
+
+ if (!boot_tracing_running) {
+ printk("Trying to stop boot tracing although tracing is not running\n");
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ ret = prefetch_stop_trace(&marker);
+ if (ret < 0)
+ printk(KERN_WARNING "Stopping tracing for boot tracing returned error, error=%d\n", ret);
+
+ boot_tracing_running = 0;
+
+#ifdef PREFETCH_DEBUG
+ print_marker("Boot stop marker: ", marker);
+#endif
+
+ ret = prefetch_save_boot_trace(boot_tracing_phase, marker);
+ if (ret < 0) {
+ printk(KERN_WARNING "Saving final boot trace failed, phase %s, error=%d\n", boot_tracing_phase, ret);
+ goto out_unlock_release;
+ }
+
+out_unlock_release:
+ ret = prefetch_release_trace(marker);
+ if (ret < 0)
+ printk(KERN_WARNING "Releasing trace for boot tracing returned error, error=%d\n", ret);
+
+out_unlock:
+ mutex_unlock(&boot_prefetch_mutex);
+ return ret;
+}
+
+int param_match_prefix(char *line, char *param_name)
+{
+ unsigned param_len = strlen(param_name);
+ if (strncmp(line, param_name, param_len) == 0)
+ return 1;
+
+ return 0;
+}
+
+ssize_t boot_prefetch_proc_write(struct file *proc_file, const char __user * buffer,
+ size_t count, loff_t *ppos)
+{
+ char *name;
+ int e = 0;
+ int r;
+ char *phase_name;
+ char *cmd_name;
+
+ if (count >= PATH_MAX)
+ return -ENAMETOOLONG;
+
+ name = kmalloc(count+1, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ if (copy_from_user(name, buffer, count)) {
+ e = -EFAULT;
+ goto out;
+ }
+
+ /* strip the optional newline */
+ if (count && name[count-1] == '\n')
+ name[count-1] = '\0';
+ else
+ name[count] = '\0';
+
+ if (param_match(name, "prefetch enable")) {
+ printk(KERN_INFO "Prefetching enabled\n");
+ prefetch_enabled = 1;
+ goto out;
+ }
+
+ if (param_match(name, "prefetch disable")) {
+ printk(KERN_INFO "Prefetching disabled\n");
+ prefetch_enabled = 0;
+ goto out;
+ }
+
+ if (param_match_prefix(name, "start ")) {
+ phase_name = kzalloc(PHASE_NAME_MAX + 1, GFP_KERNEL); //1 for terminating NULL
+ if (phase_name == NULL) {
+ printk(KERN_WARNING "Cannot allocate memory for phase name\n");
+ goto out;
+ }
+ cmd_name = kzalloc(CMD_NAME_MAX + 1, GFP_KERNEL); //1 for terminating NULL
+ if (cmd_name == NULL) {
+ printk(KERN_WARNING "Cannot allocate memory for command name\n");
+ goto out;
+ }
+ r = sscanf(name,
+ "start %" CMD_NAME_MAX_S "s phase %" PHASE_NAME_MAX_S "s",
+ cmd_name,
+ phase_name
+ );
+ if (r != 2) {
+ e = -EINVAL;
+ printk(KERN_WARNING "Wrong parameter to start command, command was: %s\n",
+ name
+ );
+ kfree(phase_name);
+ kfree(cmd_name);
+ goto out;
+ }
+ e = prefetch_start_boot_phase(cmd_name, phase_name);
+ kfree(phase_name);
+ kfree(cmd_name);
+ goto out;
+ }
+
+ if (param_match(name, "boot tracing stop")) {
+ e = prefetch_stop_boot_tracing();
+ goto out;
+ }
+out:
+ kfree(name);
+
+ return e ? e : count;
+}
+
+static int boot_prefetch_proc_open(struct inode *inode, struct file *proc_file)
+{
+ return 0;
+}
+
+static int boot_prefetch_proc_release(struct inode *inode, struct file *proc_file)
+{
+ return 0;
+}
+
+static struct file_operations proc_boot_prefetch_fops = {
+ .owner = THIS_MODULE,
+ .open = boot_prefetch_proc_open,
+ .release = boot_prefetch_proc_release,
+ .write = boot_prefetch_proc_write,
+};
+
+static __init int boot_prefetch_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ mutex_init(&boot_prefetch_mutex);
+
+ if (prefetch_proc_dir == NULL) {
+ printk(KERN_WARNING "Prefetch proc directory not present, proc interface for boot prefetching will not be available\n");
+ } else {
+ //create proc entry
+ entry = create_proc_entry("boot", 0600, prefetch_proc_dir);
+ if (entry)
+ entry->proc_fops = &proc_boot_prefetch_fops;
+ }
+ printk(KERN_INFO "Boot prefetching module started, enabled=%d, prefetching=%d\n",
+ enabled,
+ prefetch_enabled
+ );
+
+ return 0;
+}
+
+static void boot_prefetch_exit(void)
+{
+ remove_proc_entry("boot", prefetch_proc_dir);
+}
+
+MODULE_AUTHOR("Krzysztof Lichota <lichota@mimuw.edu.pl>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Boot prefetching - support for tracing and prefetching during system boot");
+
+module_init(boot_prefetch_init);
+module_exit(boot_prefetch_exit);
--
1.1.3
Show details Hide details

Change log

r366 by krzysztof.lichota on Aug 20, 2007   Diff
Added end of Summer of Code tag contents.
Go to: 
Project members, sign in to write a code review

Older revisions

r269 by krzysztof.lichota on Aug 10, 2007   Diff
Patches submitted to Ubuntu kernel
team for review.
All revisions of this file

File info

Size: 12151 bytes, 441 lines
Hosted by Google Code