diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-09-05 10:09:03 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-09-05 10:09:03 +0300 |
commit | 3c7887a85f2ed628aee28bf586c2ed115fe47186 (patch) | |
tree | 96ad0509425d372e846bdb23b0a729792fc3cbd6 /plugin | |
parent | 84813c396afc93dffe91d3a246d3a21e05eec488 (diff) | |
parent | 244fdc435da364aea3b6e55835115cc04fe3297f (diff) | |
download | mariadb-git-3c7887a85f2ed628aee28bf586c2ed115fe47186.tar.gz |
Merge 10.5 into 10.6
Diffstat (limited to 'plugin')
-rw-r--r-- | plugin/disks/CMakeLists.txt | 21 | ||||
-rw-r--r-- | plugin/disks/information_schema_disks.cc | 230 | ||||
-rw-r--r-- | plugin/disks/mysql-test/disks/disks.result | 4 | ||||
-rw-r--r-- | plugin/disks/mysql-test/disks/disks.test | 1 |
4 files changed, 200 insertions, 56 deletions
diff --git a/plugin/disks/CMakeLists.txt b/plugin/disks/CMakeLists.txt index d0f34b04027..4e40842cad0 100644 --- a/plugin/disks/CMakeLists.txt +++ b/plugin/disks/CMakeLists.txt @@ -1,7 +1,24 @@ INCLUDE (CheckIncludeFiles) -CHECK_INCLUDE_FILES ("sys/statvfs.h;mntent.h" INFO_HEADERS LANGUAGE CXX) -IF (INFO_HEADERS) +CHECK_SYMBOL_EXISTS (getmntent "mntent.h" HAVE_GETMNTENT) +CHECK_SYMBOL_EXISTS (getmntent "sys/mnttab.h" HAVE_GETMNTENT_IN_SYS_MNTAB) +CHECK_SYMBOL_EXISTS (setmntent "mntent.h" HAVE_SETMNTENT) +CHECK_SYMBOL_EXISTS (getmntinfo "sys/types.h;sys/mount.h" HAVE_GETMNTINFO) +CHECK_SYMBOL_EXISTS (getmntinfo64 "sys/types.h;sys/mount.h" HAVE_GETMNTINFO64) + +IF (HAVE_GETMNTINFO) +CHECK_CXX_SOURCE_COMPILES(" +#include <sys/types.h> +#include <sys/statvfs.h> +int main() +{ + struct statvfs *s; + return getmntinfo(&s, ST_WAIT); +} + " HAVE_GETMNTINFO_TAKES_statvfs) +ENDIF() +IF (HAVE_GETMNTENT OR HAVE_GETMNTENT_IN_SYS_MNTAB OR + HAVE_GETMNTINFO OR HAVE_GETMNTINFO64) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) MYSQL_ADD_PLUGIN(DISKS information_schema_disks.cc MODULE_ONLY RECOMPILE_FOR_EMBEDDED) ENDIF() diff --git a/plugin/disks/information_schema_disks.cc b/plugin/disks/information_schema_disks.cc index 042cfaffaa4..174264c3269 100644 --- a/plugin/disks/information_schema_disks.cc +++ b/plugin/disks/information_schema_disks.cc @@ -17,11 +17,45 @@ #include <my_global.h> #include <sys/statvfs.h> #include <sys/types.h> +#if defined(HAVE_GETMNTENT) #include <mntent.h> +#elif !defined(HAVE_GETMNTINFO_TAKES_statvfs) +/* getmntinfo (the not NetBSD variants) */ +#include <sys/param.h> +#include <sys/ucred.h> +#include <sys/mount.h> +#endif +#if defined(HAVE_GETMNTENT_IN_SYS_MNTAB) +#include <sys/mnttab.h> +#define HAVE_GETMNTENT +#endif #include <sql_class.h> #include <sql_i_s.h> #include <sql_acl.h> /* check_global_access() */ +/* + This intends to support *BSD's, macOS, Solaris, AIX, HP-UX, and Linux. + + specificly: + FreeBSD/OpenBSD/DragonFly (statfs) NetBSD (statvfs) uses getmntinfo(). + macOS uses getmntinfo64(). + Linux can use getmntent_r(), but we've just used getmntent for simplification. + Linux/Solaris/AIX/HP-UX uses setmntent()/getmntent(). + Solaris uses getmntent() with a diffent prototype, return structure, and + no setmntent(fopen instead) +*/ +#if defined(HAVE_GETMNTINFO_TAKES_statvfs) || defined(HAVE_GETMNTENT) +typedef struct statvfs st_info; +#elif defined(HAVE_GETMNTINFO64) +typedef struct statfs64 st_info; +#else // GETMNTINFO +typedef struct statfs st_info; +#endif +#ifndef MOUNTED +/* HPUX - https://docstore.mik.ua/manuals/hp-ux/en/B2355-60130/getmntent.3X.html */ +#define MOUNTED MNT_MNTTAB +#endif + bool schema_table_store_record(THD *thd, TABLE *table); @@ -41,24 +75,40 @@ ST_FIELD_INFO disks_table_fields[]= }; - -int disks_table_add_row(THD* pThd, - TABLE* pTable, - const char* zDisk, - const char* zPath, - const struct statvfs& info) +static int disks_table_add_row_stat( + THD* pThd, + TABLE* pTable, + const char* zDisk, + const char* zPath, + const st_info &info) { // From: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html + // and same for statfs: + // From: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/statfs.2.html#//apple_ref/doc/man/2/statfs + // and: https://www.freebsd.org/cgi/man.cgi?query=statfs&sektion=2&apropos=0&manpath=FreeBSD+13.1-RELEASE+and+Ports // - // f_frsize Fundamental file system block size. + // f_bsize Fundamental file system block size. // f_blocks Total number of blocks on file system in units of f_frsize. // f_bfree Total number of free blocks. // f_bavail Number of free blocks available to non-privileged process. + ulong block_size= (ulong) info.f_bsize; - ulonglong total = ((ulonglong)info.f_frsize * info.f_blocks) / 1024; - ulonglong used = ((ulonglong)info.f_frsize * + ulonglong total = ((ulonglong) block_size * info.f_blocks) / 1024; + ulonglong used = ((ulonglong) block_size * (info.f_blocks - info.f_bfree)) / 1024; - ulonglong avail = ((ulonglong)info.f_frsize * info.f_bavail) / 1024; + ulonglong avail = ((ulonglong) block_size * info.f_bavail) / 1024; + + /* skip filesystems that don't have any space */ + if (!info.f_blocks) + return 0; + + /* skip RO mounted filesystems */ +#if defined(HAVE_GETMNTINFO_TAKES_statvfs) || defined(HAVE_GETMNTENT) + if (info.f_flag & ST_RDONLY) +#else + if (info.f_flags & MNT_RDONLY) +#endif + return 0; pTable->field[0]->store(zDisk, strlen(zDisk), system_charset_info); pTable->field[1]->store(zPath, strlen(zPath), system_charset_info); @@ -70,71 +120,147 @@ int disks_table_add_row(THD* pThd, return (schema_table_store_record(pThd, pTable) != 0) ? 1 : 0; } -int disks_table_add_row(THD* pThd, TABLE* pTable, const char* zDisk, const char* zPath) + +#ifdef HAVE_GETMNTENT +static int disks_table_add_row(THD* pThd, TABLE* pTable, const char* zDisk, const char* zPath) { int rv = 0; - struct statvfs info; + st_info info; if (statvfs(zPath, &info) == 0) // We ignore failures. { - rv = disks_table_add_row(pThd, pTable, zDisk, zPath, info); + rv = disks_table_add_row_stat(pThd, pTable, zDisk, zPath, info); } return rv; } +#endif + -int disks_fill_table(THD* pThd, TABLE_LIST* pTables, Item* pCond) +#ifdef HAVE_GETMNTINFO +static int disks_fill_table(THD* pThd, TABLE_LIST* pTables, Item* pCond) { - int rv = 1; - TABLE* pTable = pTables->table; + st_info *s; + int count, rv= 0; + TABLE* pTable= pTables->table; if (check_global_access(pThd, FILE_ACL, true)) - return 0; + return 0; + +#if defined(HAVE_GETMNTINFO_TAKES_statvfs) + count= getmntinfo(&s, ST_WAIT); +#elif defined(HAVE_GETMNTINFO64) + count= getmntinfo64(&s, MNT_WAIT); +#else + count= getmntinfo(&s, MNT_WAIT); +#endif + if (count == 0) + return 1; + + while (count && rv == 0) + { + rv= disks_table_add_row_stat(pThd, pTable, s->f_mntfromname, s->f_mntonname, *s); + count--; + s++; + } + return rv; +} +#else /* HAVE_GETMNTINFO */ + +static mysql_mutex_t m_getmntent; - FILE* pFile = setmntent("/etc/mtab", "r"); +/* HAVE_GETMNTENT */ +static int disks_fill_table(THD* pThd, TABLE_LIST* pTables, Item* pCond) +{ + int rv= 1; +#ifdef HAVE_SETMNTENT + struct mntent* pEnt; +#else + struct mnttab mnttabent, *pEnt= &mnttabent; +#endif + FILE* pFile; + TABLE* pTable= pTables->table; - if (pFile) + if (check_global_access(pThd, FILE_ACL, true)) + return 0; + +#ifdef HAVE_SETMNTENT + pFile= setmntent(MOUNTED, "r"); +#else + /* Solaris */ + pFile= fopen("/etc/mnttab", "r"); +#endif + + if (!pFile) + return 1; + + rv= 0; + + /* + We lock the outer loop rather than between getmntent so the multiple + infomation_schema.disks reads don't all start blocking each other and + no-one gets any answers. + */ + mysql_mutex_lock(&m_getmntent); + + while ((rv == 0) && +#if defined(HAVE_SETMNTENT) + (pEnt = getmntent(pFile)) + +#else + getmntent(pFile, pEnt) != 0 +#endif + ) { - const size_t BUFFER_SIZE = 4096; // 4K should be sufficient. - - char* pBuffer = new (std::nothrow) char [BUFFER_SIZE]; - - if (pBuffer) - { - rv = 0; - - struct mntent ent; - struct mntent* pEnt; - - while ((rv == 0) && (pEnt = getmntent_r(pFile, &ent, pBuffer, BUFFER_SIZE))) - { - // We only report the ones that refer to physical disks. - if (pEnt->mnt_fsname[0] == '/') - { - rv = disks_table_add_row(pThd, pTable, pEnt->mnt_fsname, pEnt->mnt_dir); - } - } - - delete [] pBuffer; - } - else - { - rv = 1; - } - - endmntent(pFile); + struct stat f; + const char *path, *point; +#ifdef HAVE_SETMNTENT + path= pEnt->mnt_dir; + point= pEnt->mnt_fsname; +#else + path= pEnt->mnt_mountp; + point= pEnt->mnt_special; +#endif + // Try to keep to real storage by excluding + // read only mounts, and mount points that aren't directories + if (hasmntopt(pEnt, MNTOPT_RO) != NULL) + continue; + if (stat(path, &f)) + continue; + if (!S_ISDIR(f.st_mode)) + continue; + rv= disks_table_add_row(pThd, pTable, point, path); } + mysql_mutex_unlock(&m_getmntent); + +#ifdef HAVE_SETMNTENT + endmntent(pFile); +#else + fclose(pFile); +#endif return rv; } +#endif /* HAVE_GETMNTINFO */ -int disks_table_init(void *ptr) +static int disks_table_init(void *ptr) { ST_SCHEMA_TABLE* pSchema_table = (ST_SCHEMA_TABLE*)ptr; pSchema_table->fields_info = disks_table_fields; pSchema_table->fill_table = disks_fill_table; +#ifndef HAVE_GETMNTINFO + mysql_mutex_init(0, &m_getmntent, MY_MUTEX_INIT_SLOW); +#endif + return 0; +} + +static int disks_table_deinit(void *ptr __attribute__((unused))) +{ +#ifndef HAVE_GETMNTINFO + mysql_mutex_destroy(&m_getmntent); +#endif return 0; } @@ -148,15 +274,15 @@ maria_declare_plugin(disks) MYSQL_INFORMATION_SCHEMA_PLUGIN, &disks_table_info, /* type-specific descriptor */ "DISKS", /* table name */ - "Johan Wikman", /* author */ + "Johan Wikman, Daniel Black", /* author */ "Disk space information", /* description */ PLUGIN_LICENSE_GPL, /* license type */ Show::disks_table_init, /* init function */ - NULL, /* deinit function */ - 0x0101, /* version = 1.1 */ + Show::disks_table_deinit, /* deinit function */ + 0x0102, /* version = 1.2 */ NULL, /* no status variables */ NULL, /* no system variables */ - "1.1", /* String version representation */ + "1.2", /* String version representation */ MariaDB_PLUGIN_MATURITY_STABLE /* Maturity (see include/mysql/plugin.h)*/ } mysql_declare_plugin_end; diff --git a/plugin/disks/mysql-test/disks/disks.result b/plugin/disks/mysql-test/disks/disks.result index eb78d4073df..38dfcf351a5 100644 --- a/plugin/disks/mysql-test/disks/disks.result +++ b/plugin/disks/mysql-test/disks/disks.result @@ -1,8 +1,8 @@ show create table information_schema.disks; Table Create Table DISKS CREATE TEMPORARY TABLE `DISKS` ( - `Disk` varchar(4096) NOT NULL, - `Path` varchar(4096) NOT NULL, + `Disk` varchar(pathlen) NOT NULL, + `Path` varchar(pathlen) NOT NULL, `Total` bigint(32) NOT NULL, `Used` bigint(32) NOT NULL, `Available` bigint(32) NOT NULL diff --git a/plugin/disks/mysql-test/disks/disks.test b/plugin/disks/mysql-test/disks/disks.test index 13a0762ae01..7189c548342 100644 --- a/plugin/disks/mysql-test/disks/disks.test +++ b/plugin/disks/mysql-test/disks/disks.test @@ -1,2 +1,3 @@ +--replace_regex /varchar\([0-9]+\)/varchar(pathlen)/ show create table information_schema.disks; select sum(Total) > sum(Available), sum(Total)>sum(Used) from information_schema.disks; |