chiark / gitweb /
11b2b2dc11819e385a9f323433c4ffb5015d82ec
[elogind.git] / src / readahead / readahead-analyze.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2012 Auke Kok <auke-jan.h.kok@intel.com>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdbool.h>
26 #include <unistd.h>
27 #include <inttypes.h>
28 #include <linux/limits.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <string.h>
32
33 #include "readahead-common.h"
34
35 int main_analyze(const char *pack_path) {
36         char line[LINE_MAX];
37         FILE *pack;
38         int a;
39         int missing = 0;
40         off_t tsize = 0;
41
42         if (!pack_path)
43                 pack_path = "/.readahead";
44
45         pack = fopen(pack_path, "re");
46         if (!pack) {
47                 log_error("Pack file missing.");
48                 goto fail;
49         }
50
51         if (!fgets(line, sizeof(line), pack)) {
52                 log_error("Pack file corrupt.");
53                 goto fail;
54         }
55
56         char_array_0(line);
57
58         if (!endswith(line, READAHEAD_PACK_FILE_VERSION)) {
59                 log_error("Pack file version incompatible with this parser.");
60                 goto fail;
61         }
62
63         if ((a = getc(pack)) == EOF) {
64                 log_error("Pack file corrupt.");
65                 goto fail;
66         }
67
68         fputs("   pct  sections     size: path\n"
69               "   ===  ========     ====: ====\n", stdout);
70
71         for (;;) {
72                 char path[PATH_MAX];
73                 struct stat st;
74                 uint64_t inode;
75                 int pages = 0;
76                 int sections = 0;
77
78                 if (!fgets(path, sizeof(path), pack))
79                         break; /* done */
80
81                 path[strlen(path)-1] = 0;
82
83                 if (fread(&inode, sizeof(inode), 1, pack) != 1) {
84                         log_error("Pack file corrupt.");
85                         goto fail;
86                 }
87
88                 for (;;) {
89                         uint32_t b, c;
90
91                         if (fread(&b, sizeof(b), 1, pack) != 1  ||
92                             fread(&c, sizeof(c), 1, pack) != 1) {
93                                 log_error("Pack file corrupt.");
94                                 goto fail;
95                         }
96                         if ((b == 0) && (c == 0))
97                                 break;
98
99                         /* Uncomment this to get all the chunks separately
100                            printf(" %d: %d %d\n", sections, b, c);
101                          */
102
103                         pages += (c - b);
104                         sections++;
105                 }
106
107                 if (stat(path, &st) == 0) {
108                         off_t size;
109
110                         if (sections == 0)
111                                 size = st.st_size;
112                         else
113                                 size = pages * page_size();
114
115                         tsize += size;
116
117                         printf("  %4d%% (%2d) %12ld: %s\n",
118                                 sections ? (int) (size * 100 / st.st_size) : 100,
119                                 sections ? sections : 1,
120                                 (unsigned long)size,
121                                 path);
122                 } else {
123                         printf("  %4dp (%2d) %12s: %s (MISSING)\n",
124                                 sections ? pages : -1,
125                                 sections ? sections : 1,
126                                 "???",
127                                 path);
128                         missing++;
129                 }
130
131         }
132
133         fclose(pack);
134
135         printf("\nHOST:    %s"
136                "TYPE:    %c\n"
137                "MISSING: %d\n"
138                "TOTAL:   %llu\n",
139                line,
140                a,
141                missing,
142                (unsigned long long) tsize);
143
144         return EXIT_SUCCESS;
145
146 fail:
147         fclose(pack);
148         return EXIT_FAILURE;
149 }