module: support reading coresize from /sys if supported
Linux 3.3 introduced the coresize attribute in /sys/module/*. When
available, use this instead of parsing some portion of /proc/modules.
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
index fb3a64e..1271c70 100644
--- a/libkmod/libkmod-module.c
+++ b/libkmod/libkmod-module.c
@@ -1679,22 +1679,43 @@
* kmod_module_get_size:
* @mod: kmod module
*
- * Get the size of this kmod module as returned by Linux kernel. It reads the
- * file /proc/modules to search for this module and get its size.
+ * Get the size of this kmod module as returned by Linux kernel. If supported,
+ * the size is read from the coresize attribute in /sys/module. For older
+ * kernels, this falls back on /proc/modules and searches for the specified
+ * module to get its size.
*
* Returns: the size of this kmod module.
*/
KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod)
{
- // FIXME TODO: this should be available from /sys/module/foo
FILE *fp;
char line[4096];
int lineno = 0;
long size = -ENOENT;
+ int dfd, cfd;
if (mod == NULL)
return -ENOENT;
+ /* try to open the module dir in /sys. If this fails, don't
+ * bother trying to find the size as we know the module isn't
+ * loaded.
+ */
+ snprintf(line, sizeof(line), "/sys/module/%s", mod->name);
+ dfd = open(line, O_RDONLY);
+ if (dfd < 0)
+ return -errno;
+
+ /* available as of linux 3.3.x */
+ cfd = openat(dfd, "coresize", O_RDONLY|O_CLOEXEC);
+ if (cfd >= 0) {
+ if (read_str_long(cfd, &size, 10) < 0)
+ ERR(mod->ctx, "failed to read coresize from %s\n", line);
+ close(cfd);
+ goto done;
+ }
+
+ /* fall back on parsing /proc/modules */
fp = fopen("/proc/modules", "re");
if (fp == NULL) {
int err = -errno;
@@ -1729,6 +1750,9 @@
break;
}
fclose(fp);
+
+done:
+ close(dfd);
return size;
}