summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2013-04-17 15:58:04 +0200
committerAndreas Baumann <abaumann@yahoo.com>2013-04-17 15:58:04 +0200
commit36b1a442815ebe821aaaf6388fbd0d75b853a44a (patch)
treeaf19769c360c12fbbc17380adb68e68077de39ff
parentb431181bd1830beed98aed6569fe399a3636c88b (diff)
downloadpgfuse-36b1a442815ebe821aaaf6388fbd0d75b853a44a.tar.gz
pgfuse-36b1a442815ebe821aaaf6388fbd0d75b853a44a.tar.bz2
improved statfs (symlink handling, handling of default PGDATA)
-rw-r--r--DEVELOPERS6
-rw-r--r--TODO6
-rw-r--r--pgfuse.c15
-rw-r--r--pgsql.c55
4 files changed, 71 insertions, 11 deletions
diff --git a/DEVELOPERS b/DEVELOPERS
index fc329ea..d146bb5 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -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:
diff --git a/TODO b/TODO
index bff7c24..45de361 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/pgfuse.c b/pgfuse.c
index b74af59..5593839 100644
--- a/pgfuse.c
+++ b/pgfuse.c
@@ -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;
diff --git a/pgsql.c b/pgsql.c
index 4a2e776..0022603 100644
--- a/pgsql.c
+++ b/pgsql.c
@@ -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",