chiark / gitweb /
readahead: take file system root on command line
[elogind.git] / src / readahead-collect.c
index 93a04521f3fb82a7dd9d3385f36ff18fe14f1525..937231ca4282d46355b01b738c51c6cbccf896ef 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/fs.h>
 #include <linux/fiemap.h>
 #include <sys/ioctl.h>
+#include <sys/vfs.h>
 
 #include "missing.h"
 #include "util.h"
 #include "ioprio.h"
 #include "readahead-common.h"
 
-/*
-   fixme:
+#define MINCORE_VEC_SIZE (READAHEAD_FILE_SIZE_MAX/PAGE_SIZE)
 
-     - BTRFS_IOC_DEFRAG
-*/
+static int btrfs_defrag(int fd) {
+        struct btrfs_ioctl_vol_args data;
 
-#define MINCORE_VEC_SIZE (READAHEAD_FILE_SIZE_MAX/PAGE_SIZE)
+        zero(data);
+        data.fd = fd;
 
-static int pack_file(FILE *pack, const char *fn) {
+        return ioctl(fd, BTRFS_IOC_DEFRAG, &data);
+}
+
+static int pack_file(FILE *pack, const char *fn, bool on_btrfs) {
         struct stat st;
         void *start = MAP_FAILED;
         uint8_t vec[MINCORE_VEC_SIZE];
@@ -78,6 +82,9 @@ static int pack_file(FILE *pack, const char *fn) {
                 goto finish;
         }
 
+        if (on_btrfs)
+                btrfs_defrag(fd);
+
         l = PAGE_ALIGN(st.st_size);
         if ((start = mmap(NULL, l, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
                 log_warning("mmap(%s) failed: %m", fn);
@@ -190,7 +197,8 @@ static int collect(const char *root) {
         sigset_t mask;
         FILE *pack = NULL;
         char *pack_fn_new = NULL, *pack_fn = NULL;
-        bool on_ssd;
+        bool on_ssd, on_btrfs;
+        struct statfs sfs;
 
         assert(root);
 
@@ -247,6 +255,9 @@ static int collect(const char *root) {
                 ssize_t n;
                 struct fanotify_event_metadata *m;
 
+                if (hashmap_size(files) > READAHEAD_FILES_MAX)
+                        break;
+
                 if (poll(pollfd, _FD_MAX, -1) < 0) {
 
                         if (errno == EINTR)
@@ -308,7 +319,6 @@ static int collect(const char *root) {
 
                         m = FAN_EVENT_NEXT(m, n);
                 }
-
         }
 
         if (fanotify_fd >= 0) {
@@ -321,6 +331,9 @@ static int collect(const char *root) {
         on_ssd = fs_on_ssd(root);
         log_debug("On SSD: %s", yes_no(on_ssd));
 
+        on_btrfs = statfs(root, &sfs) >= 0 && sfs.f_type == BTRFS_SUPER_MAGIC;
+        log_debug("On btrfs: %s", yes_no(on_btrfs));
+
         asprintf(&pack_fn, "%s/.readahead", root);
         asprintf(&pack_fn_new, "%s/.readahead.new", root);
 
@@ -339,13 +352,13 @@ static int collect(const char *root) {
         fputs(CANONICAL_HOST "\n", pack);
         putc(on_ssd ? 'S' : 'R', pack);
 
-        if (on_ssd) {
+        if (on_ssd || on_btrfs) {
 
-                /* On SSD, just write things out in the order the
-                 * files where accessed */
+                /* On SSD or on btrfs, just write things out in the
+                 * order the files where accessed. */
 
                 HASHMAP_FOREACH_KEY(q, p, files, i)
-                        pack_file(pack, p);
+                        pack_file(pack, p, on_btrfs);
         } else {
                 struct item *ordered, *j;
                 unsigned k, n;
@@ -374,7 +387,7 @@ static int collect(const char *root) {
                 qsort(ordered, n, sizeof(struct item), qsort_compare);
 
                 for (k = 0; k < n; k++)
-                        pack_file(pack, ordered[k].path);
+                        pack_file(pack, ordered[k].path, on_btrfs);
 
                 free(ordered);
         }
@@ -424,13 +437,12 @@ finish:
 }
 
 int main(int argc, char *argv[]) {
-        /* log_set_target(LOG_TARGET_SYSLOG_OR_KMSG); */
+
+        log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
         log_parse_environment();
         log_open();
 
-        log_set_max_level(LOG_DEBUG);
-
-        if (collect("/") < 0)
+        if (collect(argc >= 2 ? argv[1] : "/") < 0)
                 return 1;
 
         return 0;