[libvirt] [PATCH v1 2/7] Introduce virFileFindHugeTLBFS

Michal Privoznik mprivozn at redhat.com
Thu Jul 17 16:12:43 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 |   1 +
 src/util/virfile.c       | 155 +++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virfile.h       |  12 ++++
 3 files changed, 168 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 8d3671c..44403fd 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1297,6 +1297,7 @@ virFileDirectFdFlag;
 virFileExists;
 virFileFclose;
 virFileFdopen;
+virFileFindHugeTLBFS;
 virFileFindMountPoint;
 virFileFindResource;
 virFileFindResourceFull;
diff --git a/src/util/virfile.c b/src/util/virfile.c
index 699b9f8..e1034b7 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -2841,6 +2841,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,
@@ -2914,6 +2917,33 @@ virFileIsSharedFSType(const char *path,
     return 0;
 }
 
+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;
+}
+
 #else /* ! HAVE_STATFS */
 
 int virFileIsSharedFSType(const char *path ATTRIBUTE_UNUSED,
@@ -2923,6 +2953,17 @@ int virFileIsSharedFSType(const char *path ATTRIBUTE_UNUSED,
     return 0;
 }
 
+int
+virFileGetHugepageSize(const char *path,
+                       unsigned long long *size)
+{
+    /* XXX implement me :-) */
+    VIR_WARN("Trying to get huge page size on %s is not implemented yet.",
+             path);
+    *size = 2048; /* Pure guess */
+    return 0;
+}
+
 #endif /* HAVE_STATFS */
 
 int virFileIsSharedFS(const char *path)
@@ -2935,3 +2976,117 @@ int virFileIsSharedFS(const char *path)
                                  VIR_FILE_SHFS_SMB |
                                  VIR_FILE_SHFS_CIFS);
 }
+
+
+#if defined __linux__ && defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
+
+# 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
+
+int
+virFileFindHugeTLBFS(virHugeTLBFSPtr *ret_fs,
+                     size_t *ret_nfs)
+{
+    /* XXX implement me :-) */
+    *ret_fs = NULL;
+    *ret_nfs = 0;
+    return 0;
+}
+#endif /* ! defined __linux__ && defined HAVE_MNTENT_H &&
+          defined HAVE_GETMNTENT_R */
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