chiark / gitweb /
readahead: cleanups
[elogind.git] / src / readahead / readahead-collect.c
index 8dacf6af5ca3c409c5017d779e823edc691529d9..e2fd8dfd05f2dfd17c60a77e5520fca47cb41097 100644 (file)
 #include <sys/vfs.h>
 #include <getopt.h>
 #include <sys/inotify.h>
+#include <math.h>
+
+#ifdef HAVE_FANOTIFY_INIT
+#include <sys/fanotify.h>
+#endif
 
 #include <systemd/sd-daemon.h>
 
@@ -63,6 +68,7 @@
  */
 
 static ReadaheadShared *shared = NULL;
+static usec_t starttime;
 
 /* Avoid collisions with the NULL pointer */
 #define SECTOR_TO_PTR(s) ULONG_TO_PTR((s)+1)
@@ -201,6 +207,7 @@ static unsigned long fd_first_block(int fd) {
 struct item {
         const char *path;
         unsigned long block;
+        unsigned long bin;
 };
 
 static int qsort_compare(const void *a, const void *b) {
@@ -209,6 +216,13 @@ static int qsort_compare(const void *a, const void *b) {
         i = a;
         j = b;
 
+        /* sort by bin first */
+        if (i->bin < j->bin)
+                return -1;
+        if (i->bin > j->bin)
+                return 1;
+
+        /* then sort by sector */
         if (i->block < j->block)
                 return -1;
         if (i->block > j->block)
@@ -242,11 +256,12 @@ static int collect(const char *root) {
         assert(root);
 
         if (asprintf(&pack_fn, "%s/.readahead", root) < 0) {
-                log_error("Out of memory");
-                r = -ENOMEM;
+                r = log_oom();
                 goto finish;
         }
 
+        starttime = now(CLOCK_MONOTONIC);
+
         /* If there's no pack file yet we lower the kernel readahead
          * so that mincore() is accurate. If there is a pack file
          * already we assume it is accurate enough so that kernel
@@ -444,10 +459,29 @@ static int collect(const char *root) {
                                         free(p);
                                 else {
                                         unsigned long ul;
+                                        usec_t entrytime;
+                                        struct item *entry;
+
+                                        entry = new0(struct item, 1);
+                                        if (!entry) {
+                                                r = log_oom();
+                                                goto finish;
+                                        }
 
                                         ul = fd_first_block(m->fd);
 
-                                        if ((k = hashmap_put(files, p, SECTOR_TO_PTR(ul))) < 0) {
+                                        entrytime = now(CLOCK_MONOTONIC);
+
+                                        entry->block = ul;
+                                        entry->path = strdup(p);
+                                        if (!entry->path) {
+                                                free(entry);
+                                                r = log_oom();
+                                                goto finish;
+                                        }
+                                        entry->bin = (entrytime - starttime) / 2000000;
+
+                                        if ((k = hashmap_put(files, p, entry)) < 0) {
                                                 log_warning("set_put() failed: %s", strerror(-k));
                                                 free(p);
                                         }
@@ -457,7 +491,7 @@ static int collect(const char *root) {
                                 log_warning("readlink(%s) failed: %s", fn, strerror(-k));
 
                 next_iteration:
-                        if (m->fd)
+                        if (m->fd >= 0)
                                 close_nointr_nofail(m->fd);
                 }
         }
@@ -477,8 +511,7 @@ done:
         log_debug("On btrfs: %s", yes_no(on_btrfs));
 
         if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) {
-                log_error("Out of memory");
-                r = -ENOMEM;
+                r = log_oom();
                 goto finish;
         }
 
@@ -510,15 +543,13 @@ done:
 
                 n = hashmap_size(files);
                 if (!(ordered = new(struct item, n))) {
-                        log_error("Out of memory");
-                        r = -ENOMEM;
+                        r = log_oom();
                         goto finish;
                 }
 
                 j = ordered;
                 HASHMAP_FOREACH_KEY(q, p, files, i) {
-                        j->path = p;
-                        j->block = PTR_TO_SECTOR(q);
+                        memcpy(j, q, sizeof(struct item));
                         j++;
                 }