]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
file: speed up loading non-gzipped modules when zlib is enabled.
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>
Sat, 24 Dec 2011 02:09:31 +0000 (00:09 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Sat, 24 Dec 2011 03:15:25 +0000 (01:15 -0200)
Just now realized that my distro (Gentoo) enables support for gzip but
does not compress modules by default.

In this case it's better to have a special case that uses mmap()
instead of a loop of realloc() + gzread().

libkmod/libkmod-file.c

index 13add1286b7622e3f357aa05c470f95603553db4..99ff3f2abe9c10e428de60bfb09c5ea9e46c3aab 100644 (file)
 struct kmod_file {
 #ifdef ENABLE_ZLIB
        gzFile gzf;
-#else
-       int fd;
 #endif
+       int fd;
        off_t size;
        void *memory;
 };
 
 #ifdef ENABLE_ZLIB
 #define READ_STEP (4 * 1024 * 1024)
-static int zlip_file_open(struct kmod_file *file, const char *filename)
+
+static bool check_zlib(struct kmod_file *file)
+{
+       uint8_t magic[2] = {0, 0}, zlibmagic[2] = {0x1f, 0x8b};
+       size_t done = 0, todo = 2;
+       while (todo > 0) {
+               ssize_t r = read(file->fd, magic + done, todo);
+               if (r > 0){
+                       todo -= r;
+                       done += r;
+               } else if (r == 0)
+                       goto error;
+               else if (errno == EAGAIN || errno == EINTR)
+                       continue;
+               else
+                       goto error;
+       }
+       lseek(file->fd, 0, SEEK_SET);
+       return memcmp(magic, zlibmagic, 2) == 0;
+error:
+       lseek(file->fd, 0, SEEK_SET);
+       return false;
+}
+
+static int zlib_file_open(struct kmod_file *file)
 {
        int err = 0;
        off_t did = 0, total = 0;
        unsigned char *p = NULL;
 
        errno = 0;
-       file->gzf = gzopen(filename, "rbe");
-       if (file->gzf == NULL)
+       file->gzf = gzdopen(file->fd, "rb");
+       if (file->gzf == NULL) {
+               close(file->fd);
                return -errno;
+       }
 
        for (;;) {
                int r;
@@ -88,16 +113,13 @@ error:
        gzclose(file->gzf);
        return err;
 }
-#else
-static int reg_file_open(struct kmod_file *file, const char *filename)
+#endif
+
+static int reg_file_open(struct kmod_file *file)
 {
        struct stat st;
        int err = 0;
 
-       file->fd = open(filename, O_RDONLY|O_CLOEXEC);
-       if (file->fd < 0)
-               return -errno;
-
        if (fstat(file->fd, &st) < 0) {
                err = -errno;
                goto error;
@@ -115,7 +137,6 @@ error:
        close(file->fd);
        return err;
 }
-#endif
 
 struct kmod_file *kmod_file_open(const char *filename)
 {
@@ -125,12 +146,20 @@ struct kmod_file *kmod_file_open(const char *filename)
        if (file == NULL)
                return NULL;
 
+       file->fd = open(filename, O_RDONLY|O_CLOEXEC);
+       if (file->fd < 0) {
+               err = -errno;
+               goto error;
+       }
+
 #ifdef ENABLE_ZLIB
-       err = zlip_file_open(file, filename);
-#else
-       err = reg_file_open(file, filename);
+       if (check_zlib(file))
+               err = zlib_file_open(file);
+       else
 #endif
+               err = reg_file_open(file);
 
+error:
        if (err < 0) {
                free(file);
                errno = -err;
@@ -153,11 +182,15 @@ off_t kmod_file_get_size(const struct kmod_file *file)
 void kmod_file_unref(struct kmod_file *file)
 {
 #ifdef ENABLE_ZLIB
-       free(file->memory);
-       gzclose(file->gzf);
-#else
-       munmap(file->memory, file->size);
-       close(file->fd);
+       if (file->gzf != NULL) {
+               free(file->memory);
+               gzclose(file->gzf);
+       } else {
+#endif
+               munmap(file->memory, file->size);
+               close(file->fd);
+#ifdef ENABLE_ZLIB
+       }
 #endif
        free(file);
 }