summaryrefslogtreecommitdiffstats
path: root/src/fuse/main.c
diff options
context:
space:
mode:
authorSimon Rettberg2015-04-24 17:13:31 +0200
committerSimon Rettberg2015-04-24 17:13:31 +0200
commitee62ca14800eb27e51038a78a0dab4f71b6be31f (patch)
tree11bc7d301dafd884dfdfe52bf91d75dc84a83dfb /src/fuse/main.c
parentFuse (diff)
downloaddnbd3-ee62ca14800eb27e51038a78a0dab4f71b6be31f.tar.gz
dnbd3-ee62ca14800eb27e51038a78a0dab4f71b6be31f.tar.xz
dnbd3-ee62ca14800eb27e51038a78a0dab4f71b6be31f.zip
[FUSE] Integrate into cmake build process
Diffstat (limited to 'src/fuse/main.c')
-rw-r--r--src/fuse/main.c348
1 files changed, 348 insertions, 0 deletions
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 <miklos@szeredi.hu>
+ * 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 <fuse.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+/* for socket */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+/* for printing uint */
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+/* 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 <mountpoint> -s <serverAdress> -p <port> -i <imageName>\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 );
+}
+