[systemd-devel] [PATCH] readahead: read /usr files last for rotational media, skip /var

Paolo Bonzini bonzini at gnu.org
Fri Sep 30 02:54:45 PDT 2011


When enabling readahead on my system (which has a 5400rpm hard drive)
"systemd-analyze blame" output is like this:

    19507ms udev.service
    18336ms fedora-storage-init.service
    13254ms var-lock.mount
    12960ms var-run.mount
    12871ms media.mount

This matches visual feedback from systemd's boot log (the
"Starting..." and "Started..." messages on the console appeared quite
slowly).  "systemd-analyze plot" shows that the serialization point
is udev.

Basically, readahead-replay is starving udev and everything else running
early in the boot process.  udev cannot simply load the modules and
programs it needs; rather, it has to wait for readahead to fetch them.
The pack file shows things such as libX11, libgio and libglib very close
to the beginning of the file, while kernel modules are more towards
the end.  The problem is that updated kernel modules are often installed
months after the root partition was formatted, while large files might
be installed at the beginning of the drive and stay there forever.

The attached file adds a simple heuristic to readahead-collect: break the
files in two groups, reading first the files that are not in /usr, and
then those that are in /usr.  This is all but perfect, as it may delay
some files and still load others too early.  It may delay some files
because systemd will read from /usr/lib/binfmt.d early at startup (this
sounds clearly wrong, since /usr may not even be mounted at that point!).
Similarly, it will not delay loading GLib (which has to be in /lib because
some programs in /sbin use it) even though in my case it is not needed.

Still, it was enough to save 5 more seconds, bringing the total to 20.
"systemd-analyze blame" was also more satisfying:

    8154ms fedora-storage-init.service
    7067ms udev.service
    6064ms var-lock.mount
    6057ms var-run.mount
    6043ms media.mount

A better heuristic, perhaps involving some kind of topological sort
would likely duplicate the size of readahead-collect, so I went for the
low-hanging fruit.

Signed-off-by: Paolo Bonzini <bonzini at gnu.org>
---
	This fixes bug 41336, reported by yours truly.  In the patch
	I attached there I also dropped readahead of /var, which
	is pretty much useless.  The pack file for those files usually
	marks the last page as used, but the last page tracked by collect
	won't be anymore the last page at the next reboot.  However,
	this change can be made separately.

 src/readahead-collect.c |    7 ++++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/src/readahead-collect.c b/src/readahead-collect.c
index eac11e7..ffa1dae 100644
--- a/src/readahead-collect.c
+++ b/src/readahead-collect.c
@@ -197,6 +197,7 @@ static unsigned long fd_first_block(int fd) {
 struct item {
         const char *path;
         unsigned long block;
+        int group;
 };
 
 static int qsort_compare(const void *a, const void *b) {
@@ -205,6 +206,11 @@ static int qsort_compare(const void *a, const void *b) {
         i = a;
         j = b;
 
+        if (i->group < j->group)
+                return -1;
+        if (i->group > j->group)
+                return 1;
+
         if (i->block < j->block)
                 return -1;
         if (i->block > j->block)
@@ -502,6 +508,7 @@ done:
                 HASHMAP_FOREACH_KEY(q, p, files, i) {
                         j->path = p;
                         j->block = PTR_TO_SECTOR(q);
+                        j->group = startswith(p, "/usr") ? 1 : 0;
                         j++;
                 }
 
-- 
1.7.6



More information about the systemd-devel mailing list