diff options
author | Andreas Baumann <abaumann@yahoo.com> | 2013-04-15 18:52:51 +0200 |
---|---|---|
committer | Andreas Baumann <abaumann@yahoo.com> | 2013-04-15 18:52:51 +0200 |
commit | 906665d02eefdc98b93edab645e8f0c08c5dfdf3 (patch) | |
tree | 0256d5dee7a609da5f179c772cb78a8258663d61 | |
parent | 75d12c2bd82cccec8847703e95ceec4fef9588f2 (diff) | |
download | pgfuse-906665d02eefdc98b93edab645e8f0c08c5dfdf3.tar.gz pgfuse-906665d02eefdc98b93edab645e8f0c08c5dfdf3.tar.bz2 |
started to rewrite, removed dependecy on shell/Perl
resulting a fictive number for free files and free blocks for now
added test cases
removed function.sql
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | function.sql | 21 | ||||
-rw-r--r-- | pgfuse.c | 89 | ||||
-rw-r--r-- | pgsql.c | 60 | ||||
-rw-r--r-- | pgsql.h | 8 | ||||
-rw-r--r-- | tests/Makefile | 7 |
6 files changed, 104 insertions, 86 deletions
@@ -1,6 +1,11 @@ TODO list (in order of priority) --------- +- integrate statfs patch: + - Can't do this, as the db user must be underprivileged: + show data_directory; + ERROR: must be superuser to examine "data_directory" + - no Perl, Shell, Posix df dependency - handling of most file system metadata - ownership: how is this done depending on per-user or root mounts? think about security diff --git a/function.sql b/function.sql deleted file mode 100644 index 59746a1..0000000 --- a/function.sql +++ /dev/null @@ -1,21 +0,0 @@ -CREATE LANGUAGE plperlu; -CREATE OR REPLACE FUNCTION db_disk_free() - RETURNS bigint AS -$BODY$ -# Get size of data_directory partition -# this uses UNIX df(1) command - -# reported by df(1) -my $df=`df -B1 -a -P \$(psql -c "show data_directory;" -t)`; -my @df=split(/[\n\r]+/,$df); -shift @df; -for my $l (@df) { - my @a=split(/\s+/,$l); - return $a[3]; -} - -return undef; -$BODY$ - LANGUAGE 'plperlu' VOLATILE - COST 1000; -COMMENT ON FUNCTION db_disk_free() IS 'Get free disck space of data_directory partition'; @@ -938,61 +938,80 @@ static int pgfuse_statfs( const char *path, struct statvfs *buf ) PGconn *conn; - int64_t fs_size, fs_used, fs_free, fs_avail; + int64_t blocks_total, blocks_used, blocks_free, blocks_avail; + int64_t files_total, files_used, files_free, files_avail; if( data->verbose ) { syslog( LOG_INFO, "Statfs called on '%s', thread #%u", data->mountpoint, THREAD_ID ); } - - /* Note: f_frsize, f_favail, f_fsid and f_flag are currently ignored by FUSE */ - + memset( buf, 0, sizeof( struct statvfs ) ); - buf->f_bsize = data->block_size; - buf->f_frsize = data->block_size; - ACQUIRE( conn ); PSQL_BEGIN( conn ); - fs_free = psql_get_fs_free( conn ); - - if( fs_free < 0 ) { - fs_free = INT_MAX; - } else { - fs_free = fs_free / data->block_size; + /* blocks */ + + blocks_free = psql_get_fs_blocks_free( conn ); + if( blocks_free < 0 ) { + PSQL_ROLLBACK( conn ); RELEASE( conn ); + return -blocks_free; + } - }; + blocks_used = psql_get_fs_blocks_used( conn ); + if( blocks_used < 0 ) { + PSQL_ROLLBACK( conn ); RELEASE( conn ); + return -blocks_used; + } + + blocks_total = blocks_free + blocks_used; + blocks_avail = blocks_free; + + /* inodes */ - fs_used = psql_get_fs_used( conn ); + files_free = psql_get_fs_blocks_free( conn ); + if( files_free < 0 ) { + PSQL_ROLLBACK( conn ); RELEASE( conn ); + return -files_free; + } - if( fs_used < 0 ) { + files_used = psql_get_fs_files_used( conn ); + if( files_used < 0 ) { PSQL_ROLLBACK( conn ); RELEASE( conn ); - fs_used = INT_MAX; - fs_size = INT_MAX; - fs_free = INT_MAX; - fs_avail = INT_MAX; - } else { - fs_used = fs_used / data->block_size; - fs_size = fs_free + fs_used; - fs_avail = fs_free; - }; + return -files_used; + } - PSQL_COMMIT( conn ); RELEASE( conn ); + files_total = files_free + files_used; + files_avail = files_free; - /* Note: it's hard to tell how much space is left in the database - * and how big it is - */ - buf->f_blocks = fs_size; - buf->f_bfree = fs_free; - buf->f_bavail = fs_avail; - buf->f_files = INT_MAX; - buf->f_ffree = INT_MAX; - buf->f_favail = INT_MAX; + if( data->verbose ) { + syslog( LOG_ERR, "Stats for '%s' are (%jd blocks total, %jd used, %jd free, " + "%jd files total, %jd files used, %jd files free, thread #%u", + data->mountpoint, + blocks_total, blocks_used, blocks_free, + files_total, files_used, files_free, + THREAD_ID ); + } + + /* fill statfs structure */ + + /* Note: f_frsize, f_favail, f_fsid and f_flag are currently ignored by FUSE */ + buf->f_bsize = data->block_size; + buf->f_frsize = data->block_size; + buf->f_blocks = blocks_total; + buf->f_bfree = blocks_free; + buf->f_bavail = blocks_avail; + buf->f_files = files_total; + buf->f_ffree = files_free; + buf->f_favail = files_avail; + buf->f_fsid = 0x4FE3A364; if( data->read_only ) { buf->f_flag |= ST_RDONLY; } buf->f_namemax = MAX_FILENAME_LENGTH; + + PSQL_COMMIT( conn ); RELEASE( conn ); return 0; } @@ -25,6 +25,7 @@ #include <arpa/inet.h> /* for htonl, ntohl */ #include <stdint.h> /* for uint64_t */ #include <inttypes.h> /* for PRIxxx macros */ +#include <values.h> /* for INT_MAX */ #include "endian.h" /* for be64toh and htobe64 */ @@ -928,54 +929,61 @@ size_t psql_get_block_size( PGconn *conn, const size_t block_size ) return db_block_size; } -size_t psql_get_fs_used( PGconn *conn ) +size_t psql_get_fs_blocks_used( PGconn *conn ) { PGresult *res; char *data; - size_t fs_used; - res = PQexec( conn, "SELECT SUM(size) FROM dir;" ); + size_t used; + + res = PQexec( conn, "SELECT (SELECT COUNT(*) FROM data) + (SELECT COUNT(*) FROM dir)" ); if( PQresultStatus( res ) != PGRES_TUPLES_OK ) { - syslog( LOG_ERR, "Error in psql_get_fs_used: %s", PQerrorMessage( conn ) ); + syslog( LOG_ERR, "Error in psql_get_fs_blocks_used: %s", PQerrorMessage( conn ) ); PQclear( res ); return -EIO; } - /* empty, this is ok, any blocksize acceptable after initialization */ - if( PQntuples( res ) == 0 ) { - PQclear( res ); - return 0; - } - + /* we calculate the number of blocks occupied by all data entries + * plus all "indoes" (in our case entries in dir), + * more like a filesystem would do it. Returning blocks as this is + * harder to overflow a size_t (in case it's 32-bit, modern + * systems shouldn't care). It's slower though + */ data = PQgetvalue( res, 0, 0 ); - fs_used = atol( data ); + used = atoi( data ); PQclear( res ); - return fs_used; + return used; } -size_t psql_get_fs_free( PGconn *conn ) +size_t psql_get_fs_blocks_free( PGconn *conn ) { - PGresult *res; - char *data; - size_t fs_free; - res = PQexec( conn, "SELECT db_disk_free();" ); - if( PQresultStatus( res ) != PGRES_TUPLES_OK ) { - syslog( LOG_ERR, "Error in psql_get_fs_free: %s", PQerrorMessage( conn ) ); - PQclear( res ); - return -EIO; - } + return 9999; +} - /* empty, this is ok, any blocksize acceptable after initialization */ - if( PQntuples( res ) == 0 ) { +size_t psql_get_fs_files_used( PGconn *conn ) +{ + PGresult *res; + char *data; + size_t used; + + res = PQexec( conn, "SELECT COUNT(*) FROM dir" ); + if( PQresultStatus( res ) != PGRES_TUPLES_OK ) { + syslog( LOG_ERR, "Error in psql_get_fs_files_used: %s", PQerrorMessage( conn ) ); PQclear( res ); return -EIO; } data = PQgetvalue( res, 0, 0 ); - fs_free = atol( data ); + used = atoi( data ); PQclear( res ); - return fs_free; + return used; } + +size_t psql_get_fs_files_free( PGconn *conn ) +{ + return 9999; +} + @@ -98,8 +98,12 @@ int psql_rename( PGconn *conn, const int64_t from_id, const int64_t from_parent_ size_t psql_get_block_size( PGconn *conn, const size_t block_size ); -size_t psql_get_fs_used( PGconn *conn ); +size_t psql_get_fs_blocks_used( PGconn *conn ); -size_t psql_get_fs_free( PGconn *conn ); +size_t psql_get_fs_blocks_free( PGconn *conn ); + +size_t psql_get_fs_files_used( PGconn *conn ); + +size_t psql_get_fs_files_free( PGconn *conn ); #endif diff --git a/tests/Makefile b/tests/Makefile index b8dd4e3..f44570f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -48,8 +48,6 @@ test: testfsync testpgsql testtypes testbigfile -stat mnt/dir/dir4/bfile -stat mnt/dir/dir4 -stat mnt/dir/dir4/dlink - # show filesystem stats (statvfs) - -stat -f mnt # expect success, truncate a file (grow and shrink) -touch mnt/trunc -ls -al mnt/trunc @@ -61,6 +59,11 @@ test: testfsync testpgsql testtypes testbigfile # expect success, write a sparse big file -./testbigfile -ls -al mnt/testbigfile.data + # show filesystem stats (statvfs) + -stat -f mnt + # the more human readable output of statvfs + -df -h mnt + -df -i mnt # END: unmount FUSE file system fusermount -u mnt |