X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Freadahead%2Freadahead-collect.c;h=e2fd8dfd05f2dfd17c60a77e5520fca47cb41097;hp=8dacf6af5ca3c409c5017d779e823edc691529d9;hb=b0640287f784a320661f7206c9ade07b99003fd5;hpb=87ce22cc0d097d9cd0297d0141eadba6c573c299 diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c index 8dacf6af5..e2fd8dfd0 100644 --- a/src/readahead/readahead-collect.c +++ b/src/readahead/readahead-collect.c @@ -42,6 +42,11 @@ #include #include #include +#include + +#ifdef HAVE_FANOTIFY_INIT +#include +#endif #include @@ -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++; }