From ee62ca14800eb27e51038a78a0dab4f71b6be31f Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 24 Apr 2015 17:13:31 +0200 Subject: [FUSE] Integrate into cmake build process --- src/fuse/main.c | 348 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 src/fuse/main.c (limited to 'src/fuse/main.c') diff --git a/src/fuse/main.c b/src/fuse/main.c new file mode 100644 index 0000000..79f17e8 --- /dev/null +++ b/src/fuse/main.c @@ -0,0 +1,348 @@ +/* + * FUSE: Filesystem in Userspace + * Copyright (C) 2001-2007 Miklos Szeredi + * This program can be distributed under the terms of the GNU GPL. + * See the file COPYING. + * + * Changed by Stephan Schwaer + * */ + +#include "../protocol.h" +#include "../serialize.h" +#include "helper.h" + +#define FUSE_USE_VERSION 30 +#include +#include +#include +#include +#include +#include +#include +/* for socket */ +#include +#include +#include +#include +/* for printing uint */ +#define __STDC_FORMAT_MACROS +#include + +/* variables for socket */ +int sock = -1; +int n; + +char *server_address = NULL; +int portno = -1; +char *image_Name = NULL; +const char *imagePathName = "/image"; +uint16_t rid; +static uint64_t imageSize; +/* Debug/Benchmark variables */ +bool useDebug = false; +bool useLog = false; +log_info logInfo; +uint8_t printCount = 0; + +void error(const char *msg) +{ + perror( msg ); + exit( 0 ); +} + +static void dnbd3_connect() +{ + while ( true ) { + if ( sock != -1 ) { + close( sock ); + } + sock = connect_to_server( server_address, portno ); + + if ( sock == -1 ) { + printf( "[ERROR] Connection Error!\n" ); + goto fail; + } + + printf( "Selecting image " ); + + serialized_buffer_t sbuffer; + uint16_t protocol_version; + char *name; + uint16_t rrid; + + if ( dnbd3_select_image( sock, image_Name, rid, 0 ) != 1 ) { + printf( "- Error\n" ); + goto fail; + } + printf( "- Success\n" ); + + if ( !dnbd3_select_image_reply( &sbuffer, sock, &protocol_version, &name, &rrid, &imageSize ) ) { + printf( "Error reading reply\n" ); + goto fail; + } + printf( "Reply successful\n" ); + + if ( rid != 0 && rid != rrid ) { + printf( "Got unexpected rid %d, wanted %d\n", (int)rrid, (int)rid ); + sleep( 10 ); + goto fail; + } + rid = rrid; + + printf( "Protocol version: %i, Image: %s, RevisionID: %i, Size: %i MiB\n", (int)protocol_version, name, (int) rrid, (int)( imageSize/ ( 1024*1024 ) ) ); + return; + +fail: ; + sleep( 2 ); + } +} + +static int image_getattr(const char *path, struct stat *stbuf) +{ + int res = 0; + memset( stbuf, 0, sizeof( struct stat ) ); + if ( strcmp( path, "/" ) == 0 ) { + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + } else if ( strcmp( path, imagePathName ) == 0 ) { + stbuf->st_mode = S_IFREG | 0755; + stbuf->st_nlink = 1; + stbuf->st_size = imageSize; + } else { + res = -ENOENT; + } + return res; +} + +static int image_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset UNUSED, struct fuse_file_info *fi UNUSED) +{ + if ( strcmp( path, "/" ) != 0 ) { + return -ENOENT; + } + filler( buf, ".", NULL, 0 ); + filler( buf, "..", NULL, 0 ); + filler( buf, imagePathName + 1, NULL, 0 ); + return 0; +} + +static int image_open(const char *path, struct fuse_file_info *fi) +{ + if ( strcmp( path, imagePathName ) != 0 ) { + return -ENOENT; + } + if ( ( fi->flags & 3 ) != O_RDONLY ) { + return -EACCES; + } + return 0; +} + +static int image_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi UNUSED) +{ + /* buffer for throwing away unwanted messages. */ + char tBuf[100]; + + if ( strcmp( path, imagePathName ) != 0 ) { + return -ENOENT; + } + if ( offset >= imageSize ) { + return 0; + } + if ( offset + size > imageSize ) { + size = imageSize - offset; + } + + if ( sock == -1 ) { +retry: ; + dnbd3_connect(); + } + + /* seek inside the image */ + if ( !dnbd3_get_block( sock, offset, size, offset ) ) { + printf( "[ERROR] Get block error!\n" ); + goto retry; + } + + /* count the requested blocks */ + uint64_t startBlock = offset / ( 4096 ); + uint64_t endBlock = ( offset + size - 1 ) / ( 4096 ); + + printf( "StartBlockRequest: %"PRIu64"\n", startBlock ); + printf( "EndBlockRequest: %"PRIu64"\n", endBlock ); + + if ( useDebug ) { + for ( ; startBlock <= endBlock; startBlock++ ) { + logInfo.blockRequestCount[startBlock] += 1; + } + } + + dnbd3_reply_t reply; + + /*see if the received package is a requested block, throw away if not */ + while ( true ) { + if ( !dnbd3_get_reply( sock, &reply ) ) { + printf( "[ERROR] Reply error\n" ); + goto retry; + } + printf( "Reply success\n" ); + + if ( reply.cmd == CMD_ERROR ) { + printf( "Got a CMD_ERROR!\n" ); + goto retry; + } + if ( reply.cmd != CMD_GET_BLOCK ) { + printf( "Received block isn't a wanted block, throwing it away...\n" ); + int tDone = 0; + int todo; + while ( tDone < reply.size ) { + todo = reply.size - tDone > 100 ? 100: reply.size - tDone; + + n = read( sock, tBuf, todo ); + if ( n <= 0 ) { + if ( n < 0 && ( errno == EAGAIN || errno == EINTR ) ) { + continue; + } + printf( "[ERROR] Errno %i and %i\n",errno, n ); + goto retry; + } + tDone += n; + } + continue; + } + break; + } + + printf( "Payloadsize: %i\n", ( int ) reply.size ); + printf( "Offset: %"PRIu64"\n", reply.handle ); + + if ( size != reply.size || offset != reply.handle ) { + printf( "Size: %i, reply.size: %i!\n", ( int ) size, ( int ) reply.size ); + printf( "Handle: %" PRIu64 ", reply.handle: %" PRIu64 "!\n", offset, reply.handle ); + goto retry; + } + /* read the data block data from received package */ + int done = 0; + while ( done < size ) { + n = read( sock, buf + done, size - done ); + if ( n <= 0 ) { + if ( n < 0 && ( errno == EAGAIN || errno == EINTR ) ) { + continue; + } + printf( "[ERROR] Error: %i and %i\n",errno, n ); + goto retry; + } + done += n; + /* for benchmarking */ + logInfo.receivedBytes += n; + } + printf( "Received bytes: %i MiB\n", ( int )( logInfo.receivedBytes/ ( 1024*1024 ) ) ); + + /* logfile stuff */ + if ( useLog ) { + if ( printCount == 0 ) { + printLog( &logInfo ); + } + printCount++; + } + return size; +} + +/* close the connection */ +void image_destroy(void *private_data) +{ + if ( useLog ) { + printLog( &logInfo ); + } + if ( sock != -1 ) { + close( sock ); + sock = -1; + } + return; +} + +/* map the implemented fuse operations */ +static struct fuse_operations image_oper = { + .getattr = image_getattr, + .readdir = image_readdir, + .open = image_open, + .read = image_read, + .destroy = image_destroy, +}; + +int main(int argc, char *argv[]) +{ + char *mountPoint = NULL; + int opt; + bool testOpt = false; + + if ( argc == 1 || strcmp( argv[1], "--help" ) == 0 || strcmp( argv[1], "--usage" ) == 0 ) { +exit_usage: + printf( "Usage: %s [-l] [-d] [-t] -m -s -p -i \n", argv[0] ); + printf( " -l: creates a logfile log.txt at program path\n" ); + printf( " -d: fuse debug mode\n" ); + printf( " -t: use hardcoded server, port and image for testing\n" ); + exit( EXIT_FAILURE ); + } + + while ( ( opt = getopt( argc,argv,"m:s:p:i:tdl" ) ) != -1 ) { + switch ( opt ) { + case 'm': + mountPoint = optarg; + break; + case 's': + server_address = optarg; + break; + case 'p': + portno = atoi( optarg ); + break; + case 'i': + image_Name = optarg; + break; + case 't': + testOpt = true; + break; + case 'd': + useDebug = true; + break; + case 'l': + useLog = true; + useDebug = true; + break; + default: + goto exit_usage; + } + } + + if ( testOpt ) { + /* values for testing. */ + server_address = "132.230.4.1"; + portno = 5003; + image_Name = "windows7-umwelt.vmdk"; + useLog = true; + } + + if ( server_address == NULL || portno == -1 || image_Name == NULL || mountPoint == NULL ) { + goto exit_usage; + } + + int arg_count = 5; + if ( useDebug ) { + arg_count++; + } + char *args[6] = {"foo", "-o", "ro,allow_other", "-s", mountPoint, "-d"}; + + dnbd3_connect(); + + /* initialize benchmark variables */ + logInfo.receivedBytes = 0; + logInfo.imageSize = imageSize; + logInfo.imageBlockCount = ( imageSize + 4095 ) / 4096; + + uint8_t tmpShrt[logInfo.imageBlockCount]; + memset( tmpShrt, 0, sizeof tmpShrt ); + + logInfo.blockRequestCount = tmpShrt; + + printf( "ImagePathName: %s\n",imagePathName ); + return fuse_main( arg_count, args, &image_oper, NULL ); +} + -- cgit v1.2.3-55-g7522