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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list