chiark / gitweb /
76db3cb7e4b8dc0be437e291d9bf8e3d0c0797cb
[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         _cleanup_fclose_ FILE *pack = NULL;
38         int a;
39         int missing = 0;
40         size_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("  %4jd%% (%2d) %12jd: %s\n",
118                                (intmax_t) (sections && st.st_size ? size * 100 / st.st_size : 100),
119                                sections ? sections : 1,
120                                (intmax_t) 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         printf("\nHOST:    %s"
134                "TYPE:    %c\n"
135                "MISSING: %d\n"
136                "TOTAL:   %zu\n",
137                line,
138                a,
139                missing,
140                tsize);
141
142         return EXIT_SUCCESS;
143
144 fail:
145         return EXIT_FAILURE;
146 }