diff options
| author | Michael Scherle | 2022-06-30 12:59:28 +0200 |
|---|---|---|
| committer | Michael Scherle | 2022-06-30 12:59:28 +0200 |
| commit | 331d71dd99e5918228e2afdf6833aa5368e39264 (patch) | |
| tree | d58d3df9e6e3de85babc5a324a7eb941c20f94ae /src | |
| parent | created sperate paramter for stats (diff) | |
| download | dnbd3-331d71dd99e5918228e2afdf6833aa5368e39264.tar.gz dnbd3-331d71dd99e5918228e2afdf6833aa5368e39264.tar.xz dnbd3-331d71dd99e5918228e2afdf6833aa5368e39264.zip | |
removed timeUploaded and use cmpxchg
Diffstat (limited to 'src')
| -rw-r--r-- | src/cowtest/main.c | 12 | ||||
| -rw-r--r-- | src/fuse/cowDoc/readme.md | 26 | ||||
| -rw-r--r-- | src/fuse/cowfile.c | 63 | ||||
| -rw-r--r-- | src/fuse/cowfile.h | 5 |
4 files changed, 55 insertions, 51 deletions
diff --git a/src/cowtest/main.c b/src/cowtest/main.c index 7c27f0f..06686f0 100644 --- a/src/cowtest/main.c +++ b/src/cowtest/main.c @@ -610,16 +610,18 @@ int main( int argc, char *argv[] ) printUsage(); return 0; } - while ( 1 ) + int opt; + while ((opt = getopt(argc, argv, "d:c:t:v:")) != -1) { - int result = getopt( argc, argv, "d:c:t:v:" ); - if ( result == -1 ) break; /* end of list */ + + printf( "res: %i", opt ); char * pEnd; - switch (result) + + switch ( opt ) { case 'd': - delay =(int) strtol (optarg, &pEnd, 10); + delay =(int) strtol ( optarg, &pEnd, 10 ); printf("Delay set to %i\n", delay); break; case 'c': diff --git a/src/fuse/cowDoc/readme.md b/src/fuse/cowDoc/readme.md index fcf5b2d..858255a 100644 --- a/src/fuse/cowDoc/readme.md +++ b/src/fuse/cowDoc/readme.md @@ -27,7 +27,7 @@ This extension to the fuse dnbd3 client allows it to mount images writable. The Example parameters for creating a new cow session: ``` -./dnbd3-fuse "/home/user/VMs/mount" -f -h localhost -i imagename -c "/home/user/temp" -C "192.168.178.20:5000" +./dnbd3-fuse "/home/user/VMs/mount" -f -h localhost -i imagename -c "/home/user/temp" -C "192.168.178.20:5000" --cowStatStdout -m ``` @@ -37,13 +37,9 @@ Example parameters for creating a new cow session: -## Data strucure -<!--- -Split into metadata and data +## Data structure -!--> - -The datastructe is split in two main parts. The actual data from the write on the image and its corresponding metadata. Its also important to distinguish between a dnbd3 block which is 4096byte and and cow block which groups 320 dnbd3 blocks together. An cow block has an `cow_block_metadata_t` struct which holds the corresponding meta data. The metadata is used to determine if and block has bin written on, where this block is stored in the data file, when it was last modified and when it was uploaded. But more later. +The data structure is split in two main parts. The actual data from the write on the image and its corresponding metadata. Its also important to distinguish between a dnbd3 block which is 4096byte and and cow block which groups 320 dnbd3 blocks together. An cow block has an `cow_block_metadata_t` struct which holds the corresponding meta data. The metadata is used to determine if and block has bin written on, where this block is stored in the data file, when it was last modified and when it was uploaded. But more later. ### Blockmetadata @@ -93,7 +89,7 @@ COW_METADATA_STORAGE_CAPACITY = 320 * 4096 For an read request, for every 4096byte block it will be checked if the block is already local on the computer (therefore was already written to before). -If so it will be read from disk, otherwise it will be requested from the dnbd3 server. To increase performance, multiple following blocks are also local/non local like the block before will be combined to to one larger reads from disc respectively one larger request from the server. +If so it will be read from disk, otherwise it will be requested from the dnbd3 server. To increase performance, multiple following blocks that are also local/non local like the block before will be combined to to one larger reads from disc respectively one larger request from the server.  @@ -126,14 +122,18 @@ inQueue=0 modifiedBlocks=0 idleBlocks=0 totalBlocksUploaded=0 +activeUploads:0 ulspeed=0.00 ``` - The `uuid` is the session uuid, which the cow server uses to identify the session. -- The `state` -- `inQueue` -- `modifiedBlocks` -- `totalBlocksUploaded` the total amount of cowblocks uploaded since the image was mounted. +- The `state` is `backgroundUpload` if the image is still mounted, an cow blocks are uploaded in the background. +It is `uploading` if the image got dismounted and all not yet uploaded blocks are uploading. +it is `done` if the image got dismounted and all blocks are uploaded. +- `inQueue` are the cow blocks which are currently uploaded or waiting for an free slot. +- `modifiedBlocks` are cow block which have changes which are not uploaded to the server yet, because the changes are to recent. +- `totalBlocksUploaded` the total amount of cow blocks uploaded since the image was mounted. +- `activeUploads` is the number blocks that are currently uploaded. - `ulspeed` the current upload speed in kb/s. Once all blocks are uploaded, the state will be set to `done`. @@ -214,7 +214,7 @@ The follwoing configuration variables have been added to ```config.h```. #define COW_API_START_MERGE "%s/api/File/StartMerge" ``` -- ```COW_MIN_UPLOAD_DELAY``` defines the minimum time in seconds that must have elapsed since the last modification of a cow block before it is uploaded. +- ```COW_MIN_UPLOAD_DELAY``` defines the minimum time in seconds that must have elapsed since the last modification of a cow block before it is uploaded. This value can be fine tuned. A larger value usually reduces duplicate block uploads. While a lower value usually reduces the time for the final upload after the image got unmounted. - ```COW_STATS_UPDATE_TIME``` defines the update frequency in seconds of the stdout print/ stats file update. Setting this to low could impact the performance since it hast to loop over all blocks. - ```COW_MAX_PARALLEL_UPLOADS``` defines to maximal number of parallel block uploads. These number is used once the image hast been dismounted and the final blocks are uploaded diff --git a/src/fuse/cowfile.c b/src/fuse/cowfile.c index d64d797..c18b6ec 100644 --- a/src/fuse/cowfile.c +++ b/src/fuse/cowfile.c @@ -12,7 +12,7 @@ static CURL *curl; static cowfile_metadata_header_t *metadata = NULL; static atomic_uint_fast64_t bytesUploaded; static uint64_t totalBlocksUploaded = 0; - +static atomic_int activeUploads = 0; atomic_bool uploadLoop = true; atomic_bool uploadLoopDone = false; @@ -106,7 +106,7 @@ static bool checkBit( atomic_char *bitfield, int n ) return ( atomic_load( ( bitfield + ( n / 8 ) ) ) >> ( n % 8 ) ) & 1; } -/** + /** * @brief Implementation of CURLOPT_WRITEFUNCTION , this function will be called when * the server sends back data. @@ -342,12 +342,13 @@ void updateCowStatsFile( uint64_t inQueue, uint64_t modified, uint64_t idle, cha } int len = snprintf( buffer, 300, "state=%s\n" - "inQueue=%u\n" - "modifiedBlocks=%u\n" - "idleBlocks=%u\n" - "totalBlocksUploaded=%u\n" + "inQueue=%"PRIu64"\n" + "modifiedBlocks=%"PRIu64"\n" + "idleBlocks=%"PRIu64"\n" + "totalBlocksUploaded=%"PRIu64"\n" + "activeUploads:%i\n" "%s=%s", - state, inQueue, modified, idle, totalBlocksUploaded, COW_SHOW_UL_SPEED ? "ulspeed" : "", speedBuffer ); + state, inQueue, modified, idle, totalBlocksUploaded, activeUploads,COW_SHOW_UL_SPEED ? "ulspeed" : "", speedBuffer ); if ( statStdout ) { logadd( LOG_INFO, "%s", buffer ); @@ -370,7 +371,7 @@ void updateCowStatsFile( uint64_t inQueue, uint64_t modified, uint64_t idle, cha * @param cm Curl_multi * @param curlUploadBlock cow_curl_read_upload_t containing the data for the block to upload */ -bool addUpload( CURLM *cm, cow_curl_read_upload_t *curlUploadBlock) +bool addUpload( CURLM *cm, cow_curl_read_upload_t *curlUploadBlock, struct curl_slist * headers) { CURL *eh = curl_easy_init(); @@ -391,9 +392,7 @@ bool addUpload( CURLM *cm, cow_curl_read_upload_t *curlUploadBlock) curl_easy_setopt( eh, CURLOPT_XFERINFOFUNCTION, progress_callback ); curl_easy_setopt( eh, CURLOPT_XFERINFODATA, eh ); } - curlUploadBlock->headers = NULL; - curlUploadBlock->headers = curl_slist_append( curlUploadBlock->headers, "Content-Type: application/octet-stream" ); - curl_easy_setopt( eh, CURLOPT_HTTPHEADER, curlUploadBlock->headers ); + curl_easy_setopt( eh, CURLOPT_HTTPHEADER, headers); curl_multi_add_handle( cm, eh ); return true; @@ -409,7 +408,7 @@ bool addUpload( CURLM *cm, cow_curl_read_upload_t *curlUploadBlock) * @return true returned if upload was successful or retries still possible * @return false returned if upload was unsuccessful */ -bool finishUpload( CURLM *cm, CURLMsg *msg ) +bool finishUpload( CURLM *cm, CURLMsg *msg, struct curl_slist * headers ) { bool status = true; cow_curl_read_upload_t *curlUploadBlock; @@ -425,19 +424,20 @@ bool finishUpload( CURLM *cm, CURLMsg *msg ) logadd( LOG_ERROR, "COW_API_UPDATE failed %i/5: %s\n", curlUploadBlock->fails, curl_easy_strerror( msg->data.result ) ); if ( curlUploadBlock->fails <= 5 ) { - addUpload( cm, curlUploadBlock ); + addUpload( cm, curlUploadBlock, headers ); goto CLEANUP; } - curl_slist_free_all(curlUploadBlock->headers); free( curlUploadBlock ); status = false; goto CLEANUP; } - // everything went ok, update timeUploaded - curlUploadBlock->block->timeUploaded = curlUploadBlock->time; + // everything went ok, update timeChanged + atomic_compare_exchange_strong( &curlUploadBlock->block->timeChanged, &curlUploadBlock->time, 0 ); + + curlUploadBlock->block->uploads++; + totalBlocksUploaded++; - curl_slist_free_all(curlUploadBlock->headers); free( curlUploadBlock ); CLEANUP: curl_multi_remove_handle( cm, msg->easy_handle ); @@ -456,7 +456,7 @@ CLEANUP: * @return true returned if all upload's were successful * @return false returned if one ore more upload's failed. */ -bool MessageHandler( CURLM *cm, int *activeUploads, bool breakIfNotMax, bool foregroundUpload ) +bool MessageHandler( CURLM *cm, atomic_int *activeUploads, bool breakIfNotMax, bool foregroundUpload, struct curl_slist * headers ) { CURLMsg *msg; int msgsLeft = -1; @@ -465,11 +465,11 @@ bool MessageHandler( CURLM *cm, int *activeUploads, bool breakIfNotMax, bool for curl_multi_perform( cm, activeUploads ); while ( ( msg = curl_multi_info_read( cm, &msgsLeft ) ) ) { - if ( !finishUpload( cm, msg ) ) { + if ( !finishUpload( cm, msg, headers ) ) { status = false; } } - if ( breakIfNotMax && *activeUploads <= ( foregroundUpload ? COW_MAX_PARALLEL_UPLOADS + if ( breakIfNotMax && *activeUploads < ( foregroundUpload ? COW_MAX_PARALLEL_UPLOADS : COW_MAX_PARALLEL_BACKGROUND_UPLOADS ) ) { break; } @@ -494,7 +494,9 @@ bool MessageHandler( CURLM *cm, int *activeUploads, bool breakIfNotMax, bool for bool uploaderLoop( bool ignoreMinUploadDelay, CURLM *cm ) { bool success = true; - int activeUploads = 0; + struct curl_slist * headers = NULL; + headers = curl_slist_append( headers, "Content-Type: application/octet-stream" ); + long unsigned int l1MaxOffset = 1 + ( ( metadata->imageSize - 1 ) / COW_L2_STORAGE_CAPACITY ); for ( long unsigned int l1Offset = 0; l1Offset < l1MaxOffset; l1Offset++ ) { if ( cow.l1[l1Offset] == -1 ) { @@ -505,21 +507,21 @@ bool uploaderLoop( bool ignoreMinUploadDelay, CURLM *cm ) if ( block->offset == -1 ) { continue; } - if ( block->timeUploaded < block->timeChanged ) { + if ( block->timeChanged != 0 ) { if ( ( time( NULL ) - block->timeChanged > COW_MIN_UPLOAD_DELAY ) || ignoreMinUploadDelay ) { do { - if ( !MessageHandler( cm, &activeUploads, true, ignoreMinUploadDelay ) ) { + if ( !MessageHandler( cm, &activeUploads, true, ignoreMinUploadDelay, headers ) ) { success = false; } - } while ( !( activeUploads <= ( ignoreMinUploadDelay ? COW_MAX_PARALLEL_UPLOADS : COW_MAX_PARALLEL_BACKGROUND_UPLOADS ) ) + } while ( !( activeUploads < ( ignoreMinUploadDelay ? COW_MAX_PARALLEL_UPLOADS : COW_MAX_PARALLEL_BACKGROUND_UPLOADS ) ) && activeUploads ); cow_curl_read_upload_t *b = malloc( sizeof( cow_curl_read_upload_t ) ); b->block = block; b->blocknumber = ( l1Offset * COW_L2_SIZE + l2Offset ); b->fails = 0; b->position = 0; - b->time = time( NULL ); - addUpload( cm, b ); + b->time = block->timeChanged; + addUpload( cm, b, headers ); if( !ignoreMinUploadDelay && !uploadLoop ) { goto DONE; } @@ -529,8 +531,9 @@ bool uploaderLoop( bool ignoreMinUploadDelay, CURLM *cm ) } DONE: while ( activeUploads > 0 ) { - MessageHandler( cm, &activeUploads, false, ignoreMinUploadDelay ); + MessageHandler( cm, &activeUploads, false, ignoreMinUploadDelay, headers ); } + curl_slist_free_all(headers); return success; } @@ -560,7 +563,7 @@ void * cowfile_statUpdater(__attribute__( ( unused ) ) void *something ) { if ( block->offset == -1 ) { continue; } - if ( block->timeUploaded < block->timeChanged ) { + if ( block->timeChanged != 0) { if( !uploadLoop || now > block->timeChanged + COW_MIN_UPLOAD_DELAY ) { inQueue++; } else { @@ -950,8 +953,8 @@ static bool createL2Block( int l1Offset ) if ( cow.l1[l1Offset] == -1 ) { for ( int i = 0; i < COW_L2_SIZE; i++ ) { cow.firstL2[metadata->nextL2][i].offset = -1; - cow.firstL2[metadata->nextL2][i].timeChanged = 0; - cow.firstL2[metadata->nextL2][i].timeUploaded = 0; + cow.firstL2[metadata->nextL2][i].timeChanged = ATOMIC_VAR_INIT( 0 ); + cow.firstL2[metadata->nextL2][i].uploads = ATOMIC_VAR_INIT( 0 ); for ( int j = 0; j < COW_BITFIELD_SIZE; j++ ) { cow.firstL2[metadata->nextL2][i].bitfield[j] = ATOMIC_VAR_INIT( 0 ); } diff --git a/src/fuse/cowfile.h b/src/fuse/cowfile.h index a61beab..9e4f1fc 100644 --- a/src/fuse/cowfile.h +++ b/src/fuse/cowfile.h @@ -51,7 +51,7 @@ typedef struct cow_block_metadata { atomic_int_least64_t offset; atomic_uint_least64_t timeChanged; - atomic_uint_least64_t timeUploaded; + atomic_uint_least64_t uploads; atomic_char bitfield[40]; } cow_block_metadata_t; _Static_assert( sizeof( cow_block_metadata_t ) == COW_METADATA_METADATA_SIZE, "cow_block_metadata_t is messed up" ); @@ -89,13 +89,12 @@ typedef struct cow_sub_request typedef struct cow_curl_read_upload { + atomic_uint_least64_t time; cow_block_metadata_t *block; size_t position; long unsigned int blocknumber; int fails; - uint64_t time; curl_off_t ulLast; - struct curl_slist * headers; } cow_curl_read_upload_t; |
