diff options
author | Michael Scherle | 2022-04-12 18:30:57 +0200 |
---|---|---|
committer | Michael Scherle | 2022-04-12 18:30:57 +0200 |
commit | c5ba8d71817e285337dafcb3ae6f47982abfb1e3 (patch) | |
tree | 95576c5f9773a9ed7bef47e11ef32c367b5c3513 | |
parent | multible bugfixes, test can verify existing file (diff) | |
download | dnbd3-c5ba8d71817e285337dafcb3ae6f47982abfb1e3.tar.gz dnbd3-c5ba8d71817e285337dafcb3ae6f47982abfb1e3.tar.xz dnbd3-c5ba8d71817e285337dafcb3ae6f47982abfb1e3.zip |
changed to use container_of and callbacks
-rw-r--r-- | src/fuse/connection.c | 14 | ||||
-rw-r--r-- | src/fuse/connection.h | 9 | ||||
-rw-r--r-- | src/fuse/cowfile.c | 132 | ||||
-rw-r--r-- | src/fuse/cowfile.h | 23 | ||||
-rw-r--r-- | src/fuse/main.c | 13 | ||||
-rw-r--r-- | src/fuse/main.h | 5 |
6 files changed, 103 insertions, 93 deletions
diff --git a/src/fuse/connection.c b/src/fuse/connection.c index ff77794..20c57ae 100644 --- a/src/fuse/connection.c +++ b/src/fuse/connection.c @@ -6,6 +6,8 @@ #include <dnbd3/shared/sockhelper.h> #include <dnbd3/shared/log.h> +#include "main.h" +#include "cowfile.h" #include <stdlib.h> #include <pthread.h> #include <string.h> @@ -406,10 +408,8 @@ static void* connection_receiveThreadMain( void *sockPtr ) } unlock_rw( &altLock ); } - if( request->cow_write != NULL ) { - cowfile_writePaddedBlock(request ); - } else if( request->cow != NULL ) { - cowFile_readRemoteData( request ); + if(useCow){ + cowFile_handleCallback( request ); } else { fuse_reply_buf( request->fuse_req, request->buffer, request->length ); @@ -714,10 +714,8 @@ static void probeAltServers() goto fail; } // Success, reply to fuse - if( request->cow_write != NULL ) { - cowfile_writePaddedBlock(request ); - } else if( request->cow != NULL ) { - cowFile_readRemoteData( request ); + if(useCow){ + cowFile_handleCallback(request); } else { fuse_reply_buf( request->fuse_req, request->buffer, request->length ); diff --git a/src/fuse/connection.h b/src/fuse/connection.h index 51173ad..e5fe89b 100644 --- a/src/fuse/connection.h +++ b/src/fuse/connection.h @@ -12,23 +12,20 @@ #include <fuse_lowlevel.h> + extern atomic_bool keepRunning; struct _dnbd3_async; -typedef struct cow_request cow_request_t; -typedef struct cow_write_request cow_write_request_t; - typedef struct _dnbd3_async { struct _dnbd3_async *next; // Next in this linked list (provate field, not set by caller) ticks time; // When request was put on wire, 0 if not measuring uint64_t offset; uint32_t length; fuse_req_t fuse_req; - cow_request_t *cow; - cow_write_request_t *cow_write; - char* buffer; + char buffer[]; // Must be last member! } dnbd3_async_t; + bool connection_init( const char *hosts, const char *image, const uint16_t rid, const bool learnNewServers ); bool connection_initThreads(); diff --git a/src/fuse/cowfile.c b/src/fuse/cowfile.c index d020aec..ae6f095 100644 --- a/src/fuse/cowfile.c +++ b/src/fuse/cowfile.c @@ -388,75 +388,87 @@ static void finishWriteRequest( fuse_req_t req, cow_request_t *cowRequest ) free( cowRequest ); } +static void writePaddedBlock( cow_sub_request_t *sRequest ) +{ + //copy write Data + memcpy( ( sRequest->dRequest.buffer + ( sRequest->inBlockOffset % DNBD3_BLOCK_SIZE ) ), sRequest->buffer, + sRequest->size ); + writeData( sRequest->dRequest.buffer, DNBD3_BLOCK_SIZE, (ssize_t)sRequest->size, sRequest->cowRequest, + sRequest->block, ( sRequest->inBlockOffset - ( sRequest->inBlockOffset % DNBD3_BLOCK_SIZE ) ) ); + + + if ( atomic_fetch_sub( &sRequest->cowRequest->workCounter, 1 ) == 1 ) { + finishWriteRequest( sRequest->dRequest.fuse_req, sRequest->cowRequest ); + } + free( sRequest ); +} // TODO if > remote pad 0 /** * @brief * */ -static void padBlockFromRemote( - fuse_req_t req, off_t offset, cow_request_t *cowRequest, cow_write_request_t *cowWriteRequest ) +static void padBlockFromRemote( fuse_req_t req, off_t offset, cow_request_t *cowRequest, char *buffer, size_t size, + cow_block_metadata_t *block, off_t inBlockOffset ) { if ( offset > (off_t)metadata->originalImageSize ) { //pad 0 and done char buffer[DNBD3_BLOCK_SIZE] = { 0 }; - memcpy( buffer, cowWriteRequest->buffer, cowWriteRequest->size ); + memcpy( buffer, buffer, size ); - writeData( buffer, DNBD3_BLOCK_SIZE, (ssize_t)cowWriteRequest->size, cowRequest, cowWriteRequest->block, - cowWriteRequest->inBlockOffset ); - free( cowWriteRequest ); + writeData( buffer, DNBD3_BLOCK_SIZE, (ssize_t)size, cowRequest, block, inBlockOffset ); return; } - + cow_sub_request_t *sRequest = malloc( sizeof( cow_sub_request_t ) + DNBD3_BLOCK_SIZE ); + sRequest->callback = writePaddedBlock; + sRequest->inBlockOffset = inBlockOffset; + sRequest->block = block; + sRequest->size = size; + sRequest->buffer = buffer; + sRequest->cowRequest = cowRequest; off_t start = offset - ( offset % DNBD3_BLOCK_SIZE ); - dnbd3_async_t *request = malloc( sizeof( dnbd3_async_t ) ); - request->buffer = calloc( DNBD3_BLOCK_SIZE, sizeof( char ) ); - request->length = DNBD3_BLOCK_SIZE; - request->offset = start; - request->fuse_req = req; - request->cow = cowRequest; - request->cow_write = cowWriteRequest; + sRequest->dRequest.length = DNBD3_BLOCK_SIZE; + sRequest->dRequest.offset = start; + sRequest->dRequest.fuse_req = req; + sRequest->cowRequest = cowRequest; + if ( ( (size_t)( offset + DNBD3_BLOCK_SIZE ) ) > metadata->originalImageSize ) { - request->length = (uint32_t)MIN( DNBD3_BLOCK_SIZE, offset + DNBD3_BLOCK_SIZE - metadata->originalImageSize ); + sRequest->dRequest.length = + (uint32_t)MIN( DNBD3_BLOCK_SIZE, offset + DNBD3_BLOCK_SIZE - metadata->originalImageSize ); } atomic_fetch_add( &cowRequest->workCounter, 1 ); - if ( !connection_read( request ) ) { + if ( !connection_read( &sRequest->dRequest ) ) { atomic_fetch_sub( &cowRequest->workCounter, 1 ); // todo check if not now cowRequest->errorCode = EIO; - free( request ); + free( sRequest ); return; } } -void cowfile_writePaddedBlock( dnbd3_async_t *request ) + +void cowFile_handleCallback( dnbd3_async_t *request ) { - //copy write Data - memcpy( ( request->buffer + ( request->cow_write->inBlockOffset % DNBD3_BLOCK_SIZE ) ), request->cow_write->buffer, - request->cow_write->size ); - writeData( request->buffer, DNBD3_BLOCK_SIZE, (ssize_t)request->cow_write->size, request->cow, - request->cow_write->block, - ( request->cow_write->inBlockOffset - ( request->cow_write->inBlockOffset % DNBD3_BLOCK_SIZE ) ) ); - - free( request->cow_write ); - if ( atomic_fetch_sub( &request->cow->workCounter, 1 ) == 1 ) { - finishWriteRequest( request->fuse_req, request->cow ); - } - free( request->buffer ); - free( request ); + cow_sub_request_t *sRequest = container_of( request, cow_sub_request_t, dRequest ); + sRequest->callback( sRequest ); } - -void cowFile_readRemoteData( dnbd3_async_t *request ) +static void readRemoteData( cow_sub_request_t *sRequest ) { - atomic_fetch_add( &request->cow->bytesWorkedOn, request->length ); - if ( atomic_fetch_sub( &request->cow->workCounter, 1 ) == 1 ) { - fuse_reply_buf( request->fuse_req, request->cow->readBuffer, request->cow->bytesWorkedOn ); - free( request->cow->readBuffer ); - free( request->cow ); + memcpy( sRequest->cowRequest->readBuffer + ( sRequest->dRequest.offset - sRequest->cowRequest->fuseRequestOffset ), + sRequest->dRequest.buffer, sRequest->dRequest.length ); + + + atomic_fetch_add( &sRequest->cowRequest->bytesWorkedOn, sRequest->dRequest.length ); + + if ( atomic_fetch_sub( &sRequest->cowRequest->workCounter, 1 ) == 1 ) { + fuse_reply_buf( + sRequest->dRequest.fuse_req, sRequest->cowRequest->readBuffer, sRequest->cowRequest->bytesWorkedOn ); + free( sRequest->cowRequest->readBuffer ); + free( sRequest->cowRequest ); } - free( request ); + free( sRequest ); } @@ -506,12 +518,8 @@ void cowfile_write( fuse_req_t req, cow_request_t *cowRequest, off_t offset, siz && !checkBit( metaBlock->bitfield, (int)( inBlockOffset / DNBD3_BLOCK_SIZE ) ) ) { // write remote size_t padSize = MIN( sizeToWriteToBlock, DNBD3_BLOCK_SIZE - ( (size_t)currentOffset % DNBD3_BLOCK_SIZE ) ); - cow_write_request_t *cowWriteRequest = malloc( sizeof( cow_write_request_t ) ); - cowWriteRequest->inBlockOffset = (off_t)inBlockOffset; - cowWriteRequest->block = metaBlock; - cowWriteRequest->size = padSize; - cowWriteRequest->buffer = cowRequest->writeBuffer + ( ( currentOffset - offset ) * !cowRequest->replyAttr ); - padBlockFromRemote( req, offset, cowRequest, cowWriteRequest ); + char *sbuf = cowRequest->writeBuffer + ( ( currentOffset - offset ) * !cowRequest->replyAttr ); + padBlockFromRemote( req, offset, cowRequest, sbuf, padSize, metaBlock, (off_t)inBlockOffset ); currentOffset += padSize; continue; } @@ -522,13 +530,9 @@ void cowfile_write( fuse_req_t req, cow_request_t *cowRequest, off_t offset, siz off_t padStartOffset = currentEndOffset - ( currentEndOffset % 4096 ); off_t inBlockPadStartOffset = padStartOffset - metaBlockStartOffset; if ( !checkBit( metaBlock->bitfield, (int)( inBlockPadStartOffset / DNBD3_BLOCK_SIZE ) ) ) { - cow_write_request_t *cowWriteRequest = malloc( sizeof( cow_write_request_t ) ); - cowWriteRequest->inBlockOffset = inBlockPadStartOffset; - cowWriteRequest->block = metaBlock; - cowWriteRequest->size = (currentEndOffset)-padStartOffset; - cowWriteRequest->buffer = - cowRequest->writeBuffer + ( ( padStartOffset - offset ) * !cowRequest->replyAttr ); - padBlockFromRemote( req, padStartOffset, cowRequest, cowWriteRequest ); + char *sbuf = cowRequest->writeBuffer + ( ( padStartOffset - offset ) * !cowRequest->replyAttr ); + padBlockFromRemote( req, padStartOffset, cowRequest, sbuf, (currentEndOffset)-padStartOffset, metaBlock, + inBlockPadStartOffset ); sizeToWriteToBlock -= (currentEndOffset)-padStartOffset; @@ -567,21 +571,22 @@ void cowfile_write( fuse_req_t req, cow_request_t *cowRequest, off_t offset, siz * @param buffer into which the data is to be written * @param workCounter workCounter is increased by one and later reduced by one again when the request is completed. */ -static void readRemote( fuse_req_t req, off_t offset, ssize_t size, char *buffer, cow_request_t *cowRequest ) +static void readRemote( fuse_req_t req, off_t offset, ssize_t size, cow_request_t *cowRequest ) { - dnbd3_async_t *request = malloc( sizeof( dnbd3_async_t ) ); - request->buffer = buffer; - request->length = (uint32_t)size; - request->offset = offset; - request->fuse_req = req; - request->cow = cowRequest; - request->cow_write = NULL; + cow_sub_request_t *sRequest = malloc( sizeof( cow_sub_request_t ) + size ); + sRequest->callback = readRemoteData; + sRequest->dRequest.length = (uint32_t)size; + sRequest->dRequest.offset = offset; + sRequest->dRequest.fuse_req = req; + sRequest->cowRequest = cowRequest; + + atomic_fetch_add( &cowRequest->workCounter, 1 ); - if ( !connection_read( request ) ) { + if ( !connection_read( &sRequest->dRequest ) ) { atomic_fetch_sub( &cowRequest->workCounter, 1 ); //TODO ChECK IF NOT 0 Now cowRequest->errorCode = EIO; - free( request ); + free( sRequest ); return; } } @@ -661,8 +666,7 @@ void cowfile_read( fuse_req_t req, size_t size, off_t offset ) if ( doRead || searchOffset >= endOffset ) { ssize_t sizeToRead = MIN( searchOffset, endOffset ) - lastReadOffset; if ( !isLocal ) { - readRemote( - req, lastReadOffset, sizeToRead, cowRequest->readBuffer + ( lastReadOffset - offset ), cowRequest ); + readRemote( req, lastReadOffset, sizeToRead, cowRequest ); } else { // Compute the offset in the .data file where the read starts off_t localRead = diff --git a/src/fuse/cowfile.h b/src/fuse/cowfile.h index 43101e2..d28158c 100644 --- a/src/fuse/cowfile.h +++ b/src/fuse/cowfile.h @@ -1,6 +1,9 @@ #ifndef _COWFILE_H_ #define _COWFILE_H_ + +#include "connection.h" +#include "main.h" #include <stdint.h> #include <stdlib.h> #include <stdatomic.h> @@ -9,12 +12,12 @@ #include <string.h> #include <pthread.h> #include <errno.h> -#include "main.h" + #define COW_METADAT_STORAGE_CAPACITY ( COW_BITFIELD_SIZE * DNBD3_BLOCK_SIZE ) #define COW_L2_SIZE 1024 #define COW_L2_STORAGE_CAPACITY ( COW_L2_SIZE * COW_METADAT_STORAGE_CAPACITY ) - +#define container_of( ptr, type, member ) ( (type *)( (char *)( ptr ) - (char *)&( ( (type *)NULL )->member ) ) ) #define COW_METADATA_HEADER_SIZE 280 typedef struct __attribute__( ( packed ) ) cowfile_metadata_header @@ -59,14 +62,21 @@ typedef struct cow_request struct fuse_file_info *fi; } cow_request_t; -typedef struct cow_write_request +typedef struct cow_sub_request cow_sub_request_t; +typedef void ( *cow_callback )( cow_sub_request_t *sRequest ); + + +typedef struct cow_sub_request { - const char *buffer; size_t size; off_t inBlockOffset; + const char *buffer; cow_block_metadata_t *block; + cow_callback callback; + cow_request_t *cowRequest; + dnbd3_async_t dRequest; -} cow_write_request_t; +} cow_sub_request_t; typedef int32_t l1; @@ -77,6 +87,7 @@ bool cowfile_load( char *path, size_t **imageSizePtr ); void cowfile_read( fuse_req_t req, size_t size, off_t offset ); void cowfile_write( fuse_req_t req, cow_request_t *cowRequest, off_t offset, size_t size ); -size_t cowfile_append( char *buffer, uint64_t offset, uint64_t size ); +void cowFile_handleCallback( dnbd3_async_t *request ); + #endif /* COWFILE_H_ */
\ No newline at end of file diff --git a/src/fuse/main.c b/src/fuse/main.c index b7a4a9b..5d37813 100644 --- a/src/fuse/main.c +++ b/src/fuse/main.c @@ -16,7 +16,7 @@ static const char *IMAGE_NAME = "img"; static const char *STATS_NAME = "status"; static struct fuse_session *_fuseSession = NULL; - +bool useCow = false; static uint64_t imageSize; static uint64_t *imageSizePtr =&imageSize; @@ -25,7 +25,6 @@ static bool useDebug = false; static log_info logInfo; static struct timespec startupTime; static uid_t owner; -static bool useCow = false; static int reply_buf_limited( fuse_req_t req, const char *buf, size_t bufsize, off_t off, size_t maxsize ); static void fillStatsFile( fuse_req_t req, size_t size, off_t offset ); static void image_destroy( void *private_data ); @@ -214,15 +213,11 @@ static void image_ll_read( fuse_req_t req, fuse_ino_t ino, size_t size, off_t of } - dnbd3_async_t *request = malloc( sizeof(dnbd3_async_t) ); - request->buffer = malloc(size); + dnbd3_async_t *request = malloc( sizeof(dnbd3_async_t) + size ); request->length = (uint32_t)size; request->offset = offset; request->fuse_req = req; - request->cow = NULL; - request->cow_write = NULL; - if ( !connection_read( request ) ) { fuse_reply_err( req, EIO ); free( request ); @@ -361,6 +356,7 @@ static void printUsage( char *argv0, int exitCode ) printf( " -S --sticky Use only servers from command line (no learning from servers)\n" ); printf( " -s Single threaded mode\n" ); printf( " -c <path> Enables cow, creates the cow files at given path\n" ); + printf( " -L <path> Loads the cow files from a given path\n" ); exit( exitCode ); } @@ -375,7 +371,8 @@ static const struct option longOpts[] = { { "rid", required_argument, NULL, 'r' }, { "sticky", no_argument, NULL, 'S' }, { "version", no_argument, NULL, 'v' }, - { "cow", required_argument, NULL, 'v' }, + { "cow", required_argument, NULL, 'c' }, + { "loadcow", required_argument, NULL, 'L' }, { 0, 0, 0, 0 } }; diff --git a/src/fuse/main.h b/src/fuse/main.h index 117b31f..d444cea 100644 --- a/src/fuse/main.h +++ b/src/fuse/main.h @@ -1,12 +1,14 @@ #ifndef _MAIN_H_ #define _MAIN_H_ + +#include "cowfile.h" #include "connection.h" #include "helper.h" #include <dnbd3/version.h> #include <dnbd3/build.h> #include <dnbd3/shared/protocol.h> #include <dnbd3/shared/log.h> -#include "cowfile.h" + #define FUSE_USE_VERSION 30 #include <dnbd3/config.h> @@ -31,6 +33,7 @@ #define INO_STATS (2) #define INO_IMAGE (3) +extern bool useCow; void image_ll_getattr( fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi ); #endif /* main_H_ */
\ No newline at end of file |