diff options
author | Andreas Baumann <abaumann@yahoo.com> | 2013-04-17 15:58:04 +0200 |
---|---|---|
committer | Andreas Baumann <abaumann@yahoo.com> | 2013-04-17 15:58:04 +0200 |
commit | 36b1a442815ebe821aaaf6388fbd0d75b853a44a (patch) | |
tree | af19769c360c12fbbc17380adb68e68077de39ff | |
parent | b431181bd1830beed98aed6569fe399a3636c88b (diff) | |
download | pgfuse-36b1a442815ebe821aaaf6388fbd0d75b853a44a.tar.gz pgfuse-36b1a442815ebe821aaaf6388fbd0d75b853a44a.tar.bz2 |
improved statfs (symlink handling, handling of default PGDATA)
-rw-r--r-- | DEVELOPERS | 6 | ||||
-rw-r--r-- | TODO | 6 | ||||
-rw-r--r-- | pgfuse.c | 15 | ||||
-rw-r--r-- | pgsql.c | 55 |
4 files changed, 71 insertions, 11 deletions
@@ -140,7 +140,7 @@ Calculate the size of: a) virtual things like blocks and inodes (that's the way we went) b) get physical disk usage data from the database directly -b) Detect location of tables on disk +B) Detect location of tables on disk a) environment variable PGDATA Is only really set for the postgresql startup script and for the @@ -153,7 +153,9 @@ b) standard location (probed) /var/lib/postgres/data ERROR: must be superuser to examine "data_directory" Can't do this, as the db user must be underprivileged: -c) When the DBA create dedicated tablespaces, then there is no problem + ArchLinux: /var/lib/postgres + Centos/RHEL/Fedora: /var/lib/pgsql + Debian/Ubuntu: /var/lib/postgresql/9.1/main (/var/lib/postgresql should be fine) This is a rough sketch of the algorithm: @@ -1,8 +1,10 @@ TODO list (in order of priority) --------- -- integrate statfs patch: - - no Perl, Shell, Posix df dependency +- integrate statfs patch + - find alteratives way to determine PGDATA at runtime (by NOT + asking the Postgresql server) + - find a way to calculate PGDATA while compiling - handling of most file system metadata - ownership: how is this done depending on per-user or root mounts? think about security @@ -30,6 +30,7 @@ #include <inttypes.h> /* for PRIxxx macros */ #include <mntent.h> /* for iterating mount entries */ #include <sys/vfs.h> /* for statfs */ +#include <limits.h> #include <fuse.h> /* for user-land filesystem */ #include <fuse_opt.h> /* fuse command line parser */ @@ -968,6 +969,20 @@ static int pgfuse_statfs( const char *path, struct statvfs *buf ) return res; } + /* transform them and especially resolve symlinks */ + for( i = 0; i < nof_locations; i++ ) { + char *old_path = location[i]; + char *new_path = realpath( old_path, NULL ); + if( new_path == NULL ) { + /* do nothing, most likely a permission problem */ + syslog( LOG_ERR, "realpath for '%s' failed: %s, pgfuse mount point '%s', thread #%u", + old_path, strerror( errno ), data->mountpoint, THREAD_ID ); + } else { + location[i] = new_path; + free( old_path ); + } + } + blocks_free = INT64_MAX; blocks_avail = INT64_MAX; @@ -984,6 +984,48 @@ static int get_default_tablespace( PGconn *conn, int verbose ) return oid; } +static char *get_data_directory( PGconn *conn ) +{ + PGresult *res; + char *data; + + /* in the questionable case we have super user rights we + * can ask the server for the default path */ + res = PQexec( conn, "select setting from pg_settings where name = 'data_directory'" ); + + if( PQresultStatus( res ) != PGRES_TUPLES_OK ) { + syslog( LOG_ERR, "Error getting data_directory: %s", PQerrorMessage( conn ) ); + PQclear( res ); + return NULL; + } + + /* No permissions results in an empty result set */ + if( PQntuples( res ) == 0 ) { + PQclear( res ); + + /* No location, tablespace resides in PGDATA, + * usually it lies in /var/lib/postgres, + * /var/lib/postgresql, + * /var/lib/pgsql or /var/lib/postgresql/9.1/main + */ +#ifdef __linux__ + data = strdup( "/var/lib/postgres" ); +#else + /* TODO, but usually BSD stores it on /usr/local, MacOs + * would be different, but there a lot else is also different.. + */ + data = strdup( "/usr/local" ); +#endif + return data; + } + + data = strdup( PQgetvalue( res, 0, 0 ) ); + + PQclear( res ); + + return data; +} + static char *get_tablespace_location( PGconn *conn, const int oid, int verbose ) { PGresult *res; @@ -1012,6 +1054,12 @@ static char *get_tablespace_location( PGconn *conn, const int oid, int verbose ) data = strdup( PQgetvalue( res, 0, 0 ) ); PQclear( res ); + + /* no direct information in the catalog about the table space location, try + * other means */ + if( strcmp( data, "" ) == 0 ) { + data = get_data_directory( conn ); + } return data; } @@ -1078,13 +1126,6 @@ int psql_get_tablespace_locations( PGconn *conn, char **location, size_t *nof_oi location[i] = get_tablespace_location( conn, oid[i], verbose ); } - /* TODO: */ - for( i = 0; i < *nof_oids; i++ ) { - if( !location[i] ) { - /* No location, tablespace resides in PGDATA */ - } - } - for( i = 0; i < *nof_oids; i++ ) { if( verbose ) { syslog( LOG_DEBUG, "Free blocks calculation, seen tablespace OID %d, %s", |