From: Oliver Kurth Date: Mon, 23 Oct 2017 21:21:22 +0000 (-0700) Subject: Make disk free space reporting consistent with Linux 'df' command. X-Git-Tag: stable-10.3.0~237 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7643a1eddcc2cdc0b8a42af821ae92ca076ee37a;p=thirdparty%2Fopen-vm-tools.git Make disk free space reporting consistent with Linux 'df' command. On Linux, statfs syscall reports free space in two fields. From http://man7.org/linux/man-pages/man2/statfs.2.html: 1. f_bfree => Free blocks in filesystem 2. f_bavail => Free blocks available to unprivileged user For file systems that maintain reserved space for system activities f_bfree > f_bavail because f_bfree includes the reserved space in the file system. The reserved space is typically 5% for 'ext4' file systems. Newer distros like RHEL 7.x use 'xfs' by default and report same value for both the fields. The Linux 'df' command uses f_bavail in its reporting. Tools reports, conditionally, f_bfree for root and f_bavail for non-root. However, since vmtoolsd runs as root, Tools always reports f_bfree, which is more free space than 'df' would report (depending on amount of reserved space). In order to be consistent with Linux 'df' command, report f_bavail as the disk free space by default. This does change the behavior a little bit in that Tools will report less disk free space than before, the difference being the same as the reserved space on the file system, typically 5%. This should be OK in general because it makes the space reporting a bit conservative. If this change in behavior is not desired for some use cases, the old behavior can be restored by setting the following newly added configuration in this change: [guestinfo] diskinfo-include-reserved=true The existing callers that are outside the guestInfo plugin will continue to include reserved space in their space accounting as before. Also fixed a few minor stuff/touchups in vmtoolsConfig.c. --- diff --git a/open-vm-tools/lib/hgfsServer/hgfsServer.c b/open-vm-tools/lib/hgfsServer/hgfsServer.c index 88c533cfc..b942653e3 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServer.c +++ b/open-vm-tools/lib/hgfsServer/hgfsServer.c @@ -5417,7 +5417,7 @@ HgfsServerStatFs(const char *pathName, // IN: Path we're interested in /* Now call the wiper lib to get space information. */ Str_Strcpy(p.mountPoint, pathName, sizeof p.mountPoint); - wiperError = WiperSinglePartition_GetSpace(&p, freeBytes, totalBytes); + wiperError = WiperSinglePartition_GetSpace(&p, NULL, freeBytes, totalBytes); if (strlen(wiperError) > 0) { LOG(4, ("%s: error using wiper lib: %s\n", __FUNCTION__, wiperError)); diff --git a/open-vm-tools/lib/include/conf.h b/open-vm-tools/lib/include/conf.h index d6da7e339..5f3f701a7 100644 --- a/open-vm-tools/lib/include/conf.h +++ b/open-vm-tools/lib/include/conf.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2002-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2002-2017 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -16,7 +16,6 @@ * *********************************************************/ - /* * conf.h -- * @@ -67,12 +66,12 @@ #define CONFGROUPNAME_GUESTINFO "guestinfo" /** - * Lets users disable just the perf monitor. + * Lets user disable just the perf monitor. */ #define CONFNAME_GUESTINFO_DISABLEPERFMON "disable-perf-mon" /** - * Lets users disable just DiskInfo. + * Lets user disable just DiskInfo. * * If thinking of deprecating this, please read bug 535343 first. */ @@ -113,6 +112,13 @@ #define CONFNAME_GUESTINFO_EXCLUDENICS "exclude-nics" +/** + * Lets user include reserved space in diskInfo space metrics on Linux. + * + * @param boolean Set to true to include reserved space. + */ +#define CONFNAME_DISKINFO_INCLUDERESERVED "diskinfo-include-reserved" + /* * END GuestInfo goodies. ****************************************************************************** diff --git a/open-vm-tools/lib/include/vmware/tools/utils.h b/open-vm-tools/lib/include/vmware/tools/utils.h index b5968a432..c0bfd3e21 100644 --- a/open-vm-tools/lib/include/vmware/tools/utils.h +++ b/open-vm-tools/lib/include/vmware/tools/utils.h @@ -129,19 +129,19 @@ gboolean VMTools_ConfigGetBoolean(GKeyFile *config, const gchar *section, const gchar *key, - gboolean defValue); + const gboolean defValue); gint VMTools_ConfigGetInteger(GKeyFile *config, const gchar *section, const gchar *key, - gint defValue); + const gint defValue); gchar * VMTools_ConfigGetString(GKeyFile *config, const gchar *section, const gchar *key, - gchar *defValue); + const gchar *defValue); #if defined(G_PLATFORM_WIN32) diff --git a/open-vm-tools/lib/include/wiper.h b/open-vm-tools/lib/include/wiper.h index 6eafb69cd..d16972d6d 100644 --- a/open-vm-tools/lib/include/wiper.h +++ b/open-vm-tools/lib/include/wiper.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2004-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2004-2017 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -105,8 +105,9 @@ void WiperSinglePartition_Close(WiperPartition *); Bool Wiper_IsWipeSupported(const WiperPartition *); unsigned char *WiperSinglePartition_GetSpace(const WiperPartition *p, - uint64 *free, - uint64 *total); + uint64 *avail, + uint64 *free, + uint64 *total); /* External definition of the wiper state */ struct Wiper_State; diff --git a/open-vm-tools/lib/wiper/wiperPosix.c b/open-vm-tools/lib/wiper/wiperPosix.c index 8300dba0a..9dcc38733 100644 --- a/open-vm-tools/lib/wiper/wiperPosix.c +++ b/open-vm-tools/lib/wiper/wiperPosix.c @@ -568,9 +568,10 @@ WiperSinglePartition_Open(const char *mountPoint) // IN */ unsigned char * -WiperSinglePartition_GetSpace(const WiperPartition *p, // IN - uint64 *free, // OUT - uint64 *total) // OUT +WiperSinglePartition_GetSpace(const WiperPartition *p, // IN + uint64 *avail, // OUT/OPT + uint64 *free, // OUT/OPT + uint64 *total) // OUT { #ifdef sun struct statvfs statfsbuf; @@ -595,11 +596,32 @@ WiperSinglePartition_GetSpace(const WiperPartition *p, // IN blockSize = statfsbuf.f_bsize; #endif - if (geteuid()== 0) { - *free = (uint64)statfsbuf.f_bfree * blockSize; - } else { - *free = (uint64)statfsbuf.f_bavail * blockSize; + if (avail) { + /* + * Free blocks available to non-superuser users. + * This excludes reserved blocks. Mostly applicable + * to 'ext' file systems. Newer file systems like + * 'xfs' report same value for f_bavail and f_bfree. + */ + *avail = (uint64)statfsbuf.f_bavail * blockSize; + } + + if (free) { + if (geteuid()== 0) { + /* + * Free blocks in the file system. This includes + * the reserved blocks too. + */ + *free = (uint64)statfsbuf.f_bfree * blockSize; + } else { + /* + * Free blocks available to non-superuser users. + * This excludes reserved blocks. + */ + *free = (uint64)statfsbuf.f_bavail * blockSize; + } } + *total = (uint64)statfsbuf.f_blocks * blockSize; return ""; @@ -757,7 +779,7 @@ WiperGetSpace(WiperState *state, // IN uint64 *total) // OUT { ASSERT(state); - return WiperSinglePartition_GetSpace(state->p, free, total); + return WiperSinglePartition_GetSpace(state->p, NULL, free, total); } diff --git a/open-vm-tools/libvmtools/vmtoolsConfig.c b/open-vm-tools/libvmtools/vmtoolsConfig.c index 874580703..c41e3dc75 100644 --- a/open-vm-tools/libvmtools/vmtoolsConfig.c +++ b/open-vm-tools/libvmtools/vmtoolsConfig.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2008-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2008-2017 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -538,6 +538,7 @@ exit: * * @param[in] config Config file to read the key from. * @param[in] section Section to look for in the config file. + * @param[in] key Key to look for in the section. * @param[in] defValue Default value if the key is not found or error. * * @return value of the key if value was read successfully, else defValue. @@ -547,7 +548,7 @@ gboolean VMTools_ConfigGetBoolean(GKeyFile *config, const gchar *section, const gchar *key, - gboolean defValue) + const gboolean defValue) { GError *err = NULL; gboolean value; @@ -580,6 +581,7 @@ VMTools_ConfigGetBoolean(GKeyFile *config, * * @param[in] config Config file to read the key from. * @param[in] section Section to look for in the config file. + * @param[in] key Key to look for in the section. * @param[in] defValue Default value if the key is not found or error. * * @return value of the key if value was read successfully, else defValue. @@ -589,7 +591,7 @@ gint VMTools_ConfigGetInteger(GKeyFile *config, const gchar *section, const gchar *key, - gint defValue) + const gint defValue) { GError *err = NULL; gint value; @@ -619,6 +621,7 @@ VMTools_ConfigGetInteger(GKeyFile *config, * * @param[in] config Config file to read the key from. * @param[in] section Section to look for in the config file. + * @param[in] key Key to look for in the section. * @param[in] defValue Default value if the key is not found or error. * * @return value of the key if value was read successfully, else a copy @@ -630,7 +633,7 @@ gchar * VMTools_ConfigGetString(GKeyFile *config, const gchar *section, const gchar *key, - gchar *defValue) + const gchar *defValue) { GError *err = NULL; gchar *value; diff --git a/open-vm-tools/services/plugins/guestInfo/diskInfo.c b/open-vm-tools/services/plugins/guestInfo/diskInfo.c index 35dd682fa..7b236881e 100644 --- a/open-vm-tools/services/plugins/guestInfo/diskInfo.c +++ b/open-vm-tools/services/plugins/guestInfo/diskInfo.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2014-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2014-2017 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -78,7 +78,7 @@ GuestInfo_FreeDiskInfo(GuestDiskInfo *di) */ GuestDiskInfo * -GuestInfoGetDiskInfoWiper(void) +GuestInfoGetDiskInfoWiper(Bool includeReserved) // IN { WiperPartition_List pl; DblLnkLst_Links *curr; @@ -105,11 +105,16 @@ GuestInfoGetDiskInfoWiper(void) PPartitionEntry newPartitionList; PPartitionEntry partEntry; unsigned char *error; - - error = WiperSinglePartition_GetSpace(part, &freeBytes, &totalBytes); + if (includeReserved) { + error = WiperSinglePartition_GetSpace(part, NULL, + &freeBytes, &totalBytes); + } else { + error = WiperSinglePartition_GetSpace(part, &freeBytes, + NULL, &totalBytes); + } if (strlen(error)) { - g_warning("GetDiskInfo: ERROR: could not get space for partition %s: %s\n", - part->mountPoint, error); + g_warning("GetDiskInfo: ERROR: could not get space info for " + "partition %s: %s\n", part->mountPoint, error); goto out; } diff --git a/open-vm-tools/services/plugins/guestInfo/diskInfoPosix.c b/open-vm-tools/services/plugins/guestInfo/diskInfoPosix.c index dc23e6bf9..625c98830 100644 --- a/open-vm-tools/services/plugins/guestInfo/diskInfoPosix.c +++ b/open-vm-tools/services/plugins/guestInfo/diskInfoPosix.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2014-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2014-2017 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -22,6 +22,7 @@ * Contains POSIX-specific bits of gettting disk information. */ +#include "conf.h" #include "util.h" #include "vmware.h" #include "guestInfoInt.h" @@ -40,7 +41,24 @@ */ GuestDiskInfo * -GuestInfo_GetDiskInfo(void) +GuestInfo_GetDiskInfo(const ToolsAppCtx *ctx) { - return GuestInfoGetDiskInfoWiper(); + gboolean includeReserved; + + /* + * In order to be consistent with the way 'df' reports + * disk free space, we don't include the reserved space + * while reporting the disk free space by default. + */ + includeReserved = VMTools_ConfigGetBoolean(ctx->config, + CONFGROUPNAME_GUESTINFO, + CONFNAME_DISKINFO_INCLUDERESERVED, + FALSE); + if (includeReserved) { + g_debug("Including reserved space in diskInfo stats.\n"); + } else { + g_debug("Excluding reserved space from diskInfo stats.\n"); + } + + return GuestInfoGetDiskInfoWiper(includeReserved); } diff --git a/open-vm-tools/services/plugins/guestInfo/guestInfoInt.h b/open-vm-tools/services/plugins/guestInfo/guestInfoInt.h index 87443e297..ad51119eb 100644 --- a/open-vm-tools/services/plugins/guestInfo/guestInfoInt.h +++ b/open-vm-tools/services/plugins/guestInfo/guestInfoInt.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2008-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2008-2017 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -42,10 +42,10 @@ gboolean GuestInfo_StatProviderPoll(gpointer data); GuestDiskInfo * -GuestInfoGetDiskInfoWiper(void); +GuestInfoGetDiskInfoWiper(Bool includeReserved); GuestDiskInfo * -GuestInfo_GetDiskInfo(void); +GuestInfo_GetDiskInfo(const ToolsAppCtx *ctx); void GuestInfo_FreeDiskInfo(GuestDiskInfo *di); diff --git a/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c b/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c index 49cab26df..9b421fd50 100644 --- a/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c +++ b/open-vm-tools/services/plugins/guestInfo/guestInfoServer.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 1998-2016 VMware, Inc. All rights reserved. + * Copyright (C) 1998-2017 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -418,7 +418,7 @@ GuestInfoGather(gpointer data) g_key_file_get_boolean(ctx->config, CONFGROUPNAME_GUESTINFO, CONFNAME_GUESTINFO_DISABLEQUERYDISKINFO, NULL); if (!disableQueryDiskInfo) { - if ((diskInfo = GuestInfo_GetDiskInfo()) == NULL) { + if ((diskInfo = GuestInfo_GetDiskInfo(ctx)) == NULL) { g_warning("Failed to get disk info.\n"); } else { if (GuestInfoUpdateVmdb(ctx, INFO_DISK_FREE_SPACE, diskInfo, 0)) {