From 4a3ea16925c56328f457720749375877d2eb086f Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 2 Dec 2015 15:43:40 +0100 Subject: [FUSE] Add virtual status file --- src/fuse/connection.c | 49 ++++++++++++++++++++++++++++++++++++++++ src/fuse/connection.h | 2 ++ src/fuse/main.c | 62 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 101 insertions(+), 12 deletions(-) (limited to 'src/fuse') diff --git a/src/fuse/connection.c b/src/fuse/connection.c index 43e2907..a90a53c 100644 --- a/src/fuse/connection.c +++ b/src/fuse/connection.c @@ -213,6 +213,55 @@ void connection_close() pthread_mutex_unlock( &connection.sendMutex ); } +int connection_printStats(char *buffer, const int len) +{ + int ret; + int remaining = len; + if ( remaining > 0 ) { + ret = snprintf( buffer, remaining, "Image: %s\nRevision: %d\n\nCurrent connection time: %ds\n\n", + image.name, (int)image.rid, (int)( (nowMilli() - connection.startupTime) / 1000 ) ); + if ( ret > 0 ) { + remaining -= ret; + buffer += ret; + } + } + int i = -1; + pthread_spin_lock( &altLock ); + while ( remaining > 3 && ++i < MAX_ALTS ) { + if ( altservers[i].host.type == 0 ) + continue; + if ( isSameAddressPort( &connection.currentServer, &altservers[i].host ) ) { + *buffer++ = '*'; + } else { + *buffer++ = ' '; + } + ret = sock_printHost( &altservers[i].host, buffer, remaining ); + remaining -= (ret + 1); // For space or * above + buffer += ret; + if ( remaining < 3 ) + break; + int width = MAX( 35 - ret, 0 ); + char *unit; + int value, failSpaces; + if ( altservers[i].rtt > 5000 ) { + unit = "ms"; + value = altservers[i].rtt / 1000; + failSpaces = 6; + } else { + unit = "µs"; + value = altservers[i].rtt; + width += 3; + failSpaces = 3; + } + ret = snprintf( buffer, remaining, "% *d %s Unreachable: % *d\n", + width, value, unit, failSpaces, altservers[i].consecutiveFails ); + remaining -= ret; + buffer += ret; + } + pthread_spin_unlock( &altLock ); + return len - remaining; +} + static void* connection_receiveThreadMain(void *sockPtr) { int sockFd = (int)(size_t)sockPtr; diff --git a/src/fuse/connection.h b/src/fuse/connection.h index 076704d..f59c876 100644 --- a/src/fuse/connection.h +++ b/src/fuse/connection.h @@ -24,4 +24,6 @@ bool connection_read(dnbd3_async_t *request); void connection_close(); +int connection_printStats(char *buffer, const int len); + #endif /* CONNECTION_H_ */ diff --git a/src/fuse/main.c b/src/fuse/main.c index d7f1dc8..38074dc 100644 --- a/src/fuse/main.c +++ b/src/fuse/main.c @@ -25,14 +25,19 @@ #define __STDC_FORMAT_MACROS #include #include +#include #define debugf(...) do { logadd( LOG_DEBUG1, __VA_ARGS__ ); } while (0) -static const char *imagePathName = "/img"; +static const char * const IMAGE_PATH = "/img"; +static const char * const STATS_PATH = "/status"; + static uint64_t imageSize; /* Debug/Benchmark variables */ static bool useDebug = false; static log_info logInfo; +static struct timespec startupTime; +static uid_t owner; void error(const char *msg) { @@ -44,13 +49,19 @@ static int image_getattr(const char *path, struct stat *stbuf) { int res = 0; memset( stbuf, 0, sizeof( struct stat ) ); + stbuf->st_ctim = stbuf->st_atim = stbuf->st_mtim = startupTime; + stbuf->st_uid = owner; if ( strcmp( path, "/" ) == 0 ) { - stbuf->st_mode = S_IFDIR | 0444; + stbuf->st_mode = S_IFDIR | 0550; stbuf->st_nlink = 2; - } else if ( strcmp( path, imagePathName ) == 0 ) { - stbuf->st_mode = S_IFREG | 0444; + } else if ( strcmp( path, IMAGE_PATH ) == 0 ) { + stbuf->st_mode = S_IFREG | 0440; stbuf->st_nlink = 1; stbuf->st_size = imageSize; + } else if ( strcmp( path, STATS_PATH ) == 0 ) { + stbuf->st_mode = S_IFREG | 0440; + stbuf->st_nlink = 1; + stbuf->st_size = 4096; } else { res = -ENOENT; } @@ -64,13 +75,14 @@ static int image_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of } filler( buf, ".", NULL, 0 ); filler( buf, "..", NULL, 0 ); - filler( buf, imagePathName + 1, NULL, 0 ); + filler( buf, IMAGE_PATH + 1, NULL, 0 ); + filler( buf, STATS_PATH + 1, NULL, 0 ); return 0; } static int image_open(const char *path, struct fuse_file_info *fi) { - if ( strcmp( path, imagePathName ) != 0 ) { + if ( strcmp( path, IMAGE_PATH ) != 0 && strcmp( path, STATS_PATH ) != 0 ) { return -ENOENT; } if ( ( fi->flags & 3 ) != O_RDONLY ) { @@ -79,14 +91,33 @@ static int image_open(const char *path, struct fuse_file_info *fi) return 0; } -static int image_read(const char *path UNUSED, char *buf, size_t size, off_t offset, struct fuse_file_info *fi UNUSED) +static int fillStatsFile(char *buf, size_t size, off_t offset) { + if ( offset == 0 ) { + return connection_printStats( buf, size ); + } + char buffer[4096]; + int ret = connection_printStats( buffer, sizeof buffer ); + int len = MIN( ret - (int)offset, (int)size ); + if ( len == 0 ) + return 0; + if ( len < 0 ) { + return -EOF; + } + memcpy( buf, buffer + offset, len ); + return len; +} + +static int image_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi UNUSED) { if ( (uint64_t)offset >= imageSize ) { return 0; } -// if ( strcmp( path, imagePathName ) != 0 ) { -// return -ENOENT; -// } + + if ( path[1] == STATS_PATH[1] ) { + return fillStatsFile(buf, size, offset); + } + //return -ENOENT; + if ( offset + size > imageSize ) { size = imageSize - offset; } @@ -210,6 +241,11 @@ int main(int argc, char *argv[]) case 'o': newArgv[newArgc++] = "-o"; newArgv[newArgc++] = optarg; + if ( strstr( optarg, "use_ino" ) != NULL ) { + printf( "************************\n" + "* WARNING: use_ino mount option is unsupported, use at your own risk!\n" + "************************\n" ); + } break; case 'H': printUsage( argv[0], 0 ); @@ -254,7 +290,7 @@ int main(int argc, char *argv[]) // Since dnbd3 is always read only and the remote image will not change newArgv[newArgc++] = "-o"; - newArgv[newArgc++] = "kernel_cache"; + newArgv[newArgc++] = "kernel_cache,default_permissions"; // Mount point goes last newArgv[newArgc++] = argv[optind]; @@ -274,10 +310,12 @@ int main(int argc, char *argv[]) logInfo.blockRequestCount = tmpShrt; - printf( "ImagePathName: %s\nFuseArgs:",imagePathName ); + printf( "ImagePathName: %s\nFuseArgs:",IMAGE_PATH ); for ( int i = 0; i < newArgc; ++i ) { printf( " '%s'", newArgv[i] ); } putchar('\n'); + clock_gettime( CLOCK_REALTIME, &startupTime ); + owner = getuid(); return fuse_main( newArgc, newArgv, &image_oper, NULL ); } -- cgit v1.2.3-55-g7522