[libvirt] [PATCH v2 1/6] Introduce virFileFindHugeTLBFS

Michal Privoznik mprivozn at redhat.com
Wed Jul 23 15:37:17 UTC 2014


This should iterate over mount tab and search for hugetlbfs among with
looking for the default value of huge pages.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/libvirt_private.syms |   2 +
 src/util/virfile.c       | 151 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/util/virfile.h       |  12 ++++
 3 files changed, 163 insertions(+), 2 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 51504d1..c928564 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1276,9 +1276,11 @@ virFileDirectFdFlag;
 virFileExists;
 virFileFclose;
 virFileFdopen;
+virFileFindHugeTLBFS;
 virFileFindMountPoint;
 virFileFindResource;
 virFileFindResourceFull;
+virFileGetHugepageSize;
 virFileGetMountReverseSubtree;
 virFileGetMountSubtree;
 virFileHasSuffix;
diff --git a/src/util/virfile.c b/src/util/virfile.c
index 463064c..f18a0f5 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -2837,6 +2837,9 @@ int virFilePrintf(FILE *fp, const char *msg, ...)
 # ifndef CIFS_SUPER_MAGIC
 #  define CIFS_SUPER_MAGIC 0xFF534D42
 # endif
+# ifndef HUGETLBFS_MAGIC
+#  define HUGETLBFS_MAGIC 0x958458f6
+# endif
 
 int
 virFileIsSharedFSType(const char *path,
@@ -2909,14 +2912,158 @@ virFileIsSharedFSType(const char *path,
 
     return 0;
 }
-#else
+
+int
+virFileGetHugepageSize(const char *path,
+                       unsigned long long *size)
+{
+    int ret = -1;
+    struct statfs fs;
+
+    if (statfs(path, &fs) < 0) {
+        virReportSystemError(errno,
+                             _("cannot determine filesystem for '%s'"),
+                             path);
+        goto cleanup;
+    }
+
+    if (fs.f_type != HUGETLBFS_MAGIC) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("not a hugetlbfs mount: '%s'"),
+                       path);
+        goto cleanup;
+    }
+
+    *size = fs.f_bsize / 1024; /* we are storing size in KiB */
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+# define PROC_MEMINFO "/proc/meminfo"
+# define HUGEPAGESIZE_STR "Hugepagesize:"
+
+static int
+virFileGetDefaultHugepageSize(unsigned long long *size)
+{
+    int ret = -1;
+    char *meminfo, *c, *n, *unit;
+
+    if (virFileReadAll(PROC_MEMINFO, 4096, &meminfo) < 0)
+        goto cleanup;
+
+    if (!(c = strstr(meminfo, HUGEPAGESIZE_STR))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Unable to parse %s"),
+                       PROC_MEMINFO);
+        goto cleanup;
+    }
+    c += strlen(HUGEPAGESIZE_STR);
+
+    if ((n = strchr(c, '\n'))) {
+        /* Cut off the rest of the meminfo file */
+        *n = '\0';
+    }
+
+    if (virStrToLong_ull(c, &unit, 10, size) < 0 || STRNEQ(unit, " kB")) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Unable to parse %s %s"),
+                       HUGEPAGESIZE_STR, c);
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(meminfo);
+    return ret;
+}
+
+# define PROC_MOUNTS "/proc/mounts"
+
+int
+virFileFindHugeTLBFS(virHugeTLBFSPtr *ret_fs,
+                     size_t *ret_nfs)
+{
+    int ret = -1;
+    FILE *f = NULL;
+    struct mntent mb;
+    char mntbuf[1024];
+    virHugeTLBFSPtr fs = NULL;
+    size_t nfs = 0;
+    unsigned long long default_hugepagesz;
+
+    if (virFileGetDefaultHugepageSize(&default_hugepagesz) < 0)
+        goto cleanup;
+
+    if (!(f = setmntent(PROC_MOUNTS, "r"))) {
+        virReportSystemError(errno,
+                             _("Unable to open %s"),
+                             PROC_MOUNTS);
+        goto cleanup;
+    }
+
+    while (getmntent_r(f, &mb, mntbuf, sizeof(mntbuf))) {
+        virHugeTLBFSPtr tmp;
+
+        if (STRNEQ(mb.mnt_type, "hugetlbfs"))
+            continue;
+
+        if (VIR_REALLOC_N(fs, nfs + 1) < 0)
+            goto cleanup;
+
+        tmp = &fs[nfs];
+        nfs++;
+
+        if (VIR_STRDUP(tmp->mnt_dir, mb.mnt_dir) < 0)
+            goto cleanup;
+
+        if (virFileGetHugepageSize(tmp->mnt_dir, &tmp->size) < 0)
+            goto cleanup;
+
+        tmp->deflt = tmp->size == default_hugepagesz;
+    }
+
+    *ret_fs = fs;
+    *ret_nfs = nfs;
+    fs = NULL;
+    nfs = 0;
+    ret = 0;
+
+ cleanup:
+    endmntent(f);
+    while (nfs)
+        VIR_FREE(fs[--nfs].mnt_dir);
+    VIR_FREE(fs);
+    return ret;
+}
+
+#else /* defined __linux__ */
+
 int virFileIsSharedFSType(const char *path ATTRIBUTE_UNUSED,
                           int fstypes ATTRIBUTE_UNUSED)
 {
     /* XXX implement me :-) */
     return 0;
 }
-#endif
+
+int
+virFileGetHugepageSize(const char *path ATTRIBUTE_UNUSED,
+                       unsigned long long *size ATTRIBUTE_UNUSED)
+{
+    /* XXX implement me :-) */
+    virReportUnsupportedError();
+    return -1;
+}
+
+int
+virFileFindHugeTLBFS(virHugeTLBFSPtr *ret_fs ATTRIBUTE_UNUSED,
+                     size_t *ret_nfs ATTRIBUTE_UNUSED)
+{
+    /* XXX implement me :-) */
+    virReportUnsupportedError();
+    return -1;
+}
+#endif /* defined __linux__ */
 
 int virFileIsSharedFS(const char *path)
 {
diff --git a/src/util/virfile.h b/src/util/virfile.h
index 36d3fe7..403d0ba 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -283,4 +283,16 @@ int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL;
 int virFilePrintf(FILE *fp, const char *msg, ...)
     ATTRIBUTE_FMT_PRINTF(2, 3);
 
+typedef struct _virHugeTLBFS virHugeTLBFS;
+typedef virHugeTLBFS *virHugeTLBFSPtr;
+struct _virHugeTLBFS {
+    char *mnt_dir;                  /* Where the FS is mount to */
+    unsigned long long size;        /* page size in kibibytes */
+    bool deflt;                     /* is this the default huge page size */
+};
+
+int virFileGetHugepageSize(const char *path,
+                           unsigned long long *size);
+int virFileFindHugeTLBFS(virHugeTLBFSPtr *ret_fs,
+                         size_t *ret_nfs);
 #endif /* __VIR_FILE_H */
-- 
1.8.5.5




More information about the libvir-list mailing list