summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Scherle2022-06-02 15:24:57 +0200
committerMichael Scherle2022-06-02 15:24:57 +0200
commit6923361c91b4502c7e56ceed1a4b075248cf0390 (patch)
tree7c0e2ce6101b8b9a490f3b145eaed50d601ddf88
parentadded cow upload status file & started doc (diff)
downloaddnbd3-6923361c91b4502c7e56ceed1a4b075248cf0390.tar.gz
dnbd3-6923361c91b4502c7e56ceed1a4b075248cf0390.tar.xz
dnbd3-6923361c91b4502c7e56ceed1a4b075248cf0390.zip
fixed wrong bitfield size
-rw-r--r--inc/dnbd3/config.h7
-rw-r--r--src/cowtest/main.c4
-rw-r--r--src/fuse/cowDoc/readme.md45
-rw-r--r--src/fuse/cowfile.c82
-rw-r--r--src/fuse/cowfile.h2
5 files changed, 98 insertions, 42 deletions
diff --git a/inc/dnbd3/config.h b/inc/dnbd3/config.h
index 88ba4cc..98af571 100644
--- a/inc/dnbd3/config.h
+++ b/inc/dnbd3/config.h
@@ -42,13 +42,14 @@
// +++++ COW +++++
#define COW_BITFIELD_SIZE 40 // NEVER CHANGE THIS OR THE WORLD WILL ALSO END!
-#define COW_FILE_META_MAGIC_VALUE ((uint64_t)0xEBE44D6E72F7825E) // Magic Value to recognize a Cow .meta file
-#define COW_FILE_DATA_MAGIC_VALUE ((uint64_t)0xEBE44D6E72F7825F) // Magic Value to recognize a Cow .data file
+#define COW_FILE_META_MAGIC_VALUE ((uint64_t)0xEBE44D6E72F7825E) // Magic Value to recognize a Cow meta file
+#define COW_FILE_DATA_MAGIC_VALUE ((uint64_t)0xEBE44D6E72F7825F) // Magic Value to recognize a Cow data file
#define COW_MIN_UPLOAD_DELAY 60 // in seconds
#define COW_STATS_UPDATE_TIME 5 // time in seconds the cow status files gets updated (while uploading blocks)
+#define COW_MAX_PARALLEL_UPLOADS 10 // maximum number of parallel uploads
// +++++ COW API Endpoints +++++
#define COW_API_CREATE "%s/api/File/Create"
#define COW_API_UPDATE "%s/api/File/Update?guid=%s&BlockNumber=%u"
-#define COW_API_START_MERGE "%s/api/File/StartMerge?guid=%s&fileSize=%lld"
+#define COW_API_START_MERGE "%s/api/File/StartMerge"
#endif /* CONFIG_H_ */
diff --git a/src/cowtest/main.c b/src/cowtest/main.c
index e369f2d..e9f7e4c 100644
--- a/src/cowtest/main.c
+++ b/src/cowtest/main.c
@@ -23,7 +23,7 @@ typedef struct verify_test
const size_t l2Size = 1024;
const size_t bitfieldByteSize = 40;
-const size_t l2Capacity = l2Size * DNBD3_BLOCK_SIZE * bitfieldByteSize;
+const size_t l2Capacity = l2Size * DNBD3_BLOCK_SIZE * bitfieldByteSize * 8;
const size_t testFileSize = l2Size * bitfieldByteSize * DNBD3_BLOCK_SIZE * 8L * 2.9L;
@@ -442,7 +442,7 @@ void verifyFinalFile( char *path )
// read to whole file
- int maxReadSize = DNBD3_BLOCK_SIZE * COW_BITFIELD_SIZE;
+ int maxReadSize = DNBD3_BLOCK_SIZE * COW_BITFIELD_SIZE * 8;
char buffer[maxReadSize];
char emptyData[maxReadSize];
memset( emptyData, 0, maxReadSize );
diff --git a/src/fuse/cowDoc/readme.md b/src/fuse/cowDoc/readme.md
index 2eeafb0..0c63e60 100644
--- a/src/fuse/cowDoc/readme.md
+++ b/src/fuse/cowDoc/readme.md
@@ -10,7 +10,7 @@
# Introduction
-This extension to the fuse dnbd3 client allows it to mount images writable. The changes to an writeable mounted image will be stored in a separate files (also called Copy on Write (Cow)) on the client computer. These changes are uploaded in the background to the cow server. Once the user unmounts the images all remaining changes will be uploaded. Then the image will be merged on the server (depending on the startup parameters).
+This extension to the fuse dnbd3 client allows it to mount images writable. The changes to an writeable mounted image will be stored in a separate files (also called Copy on Write (Cow)) on the client computer. These changes are uploaded in the background to the cow server. Once the user unmounts the images all remaining changes will be uploaded. Then the image will be merged on the server (if set so in the startup parameters).
# Usage
@@ -31,10 +31,37 @@ Example parameters for creating a new cow session:
## Files
-If a new CoW session is started, a new `.meta` and `.data` file is created.
+If a new CoW session is started, a new `meta`, `data` and `status.txt` file is created.
-### .meta
-The `.meta` file contains the following header:
+### status.txt
+While the cow session ist active the file contains:
+
+```
+uuid: <uuid>
+state: active
+```
+- The `uuid` is the session uuid, which the cow server uses to identify the session.
+
+
+Once the user unmounts the image the file contains:
+
+```
+uid: <uuid>
+state: uploading
+uploaded: <number>
+totalBlocks: <number>
+```
+- `uploaded` is the number of Blocks which are already uploaded.
+
+- `totalBlocks` is the total Number of Blocks which need to be uploaded.
+
+
+Once all blocks are uploaded the state will be set to `done`.
+
+
+
+### meta.dat
+The `meta` file contains the following header:
```C
// cowfile.h
typedef struct __attribute__( ( packed ) ) cowfile_metadata_header
@@ -57,8 +84,8 @@ typedef struct __attribute__( ( packed ) ) cowfile_metadata_header
```
-### .data
-The `.data` files contains
+### data
+The `data` files contains
@@ -66,11 +93,11 @@ The `.data` files contains
The magic values in both files are used to ensure that a suitable file is read and that the machine has the correct endianness.
```C
//config.h
-#define COW_FILE_META_MAGIC_VALUE ((uint64_t)0xEBE44D6E72F7825E) // Magic Value to recognize a Cow .meta file
-#define COW_FILE_DATA_MAGIC_VALUE ((uint64_t)0xEBE44D6E72F7825F) // Magic Value to recognize a Cow .data file
+#define COW_FILE_META_MAGIC_VALUE ((uint64_t)0xEBE44D6E72F7825E) // Magic Value to recognize a Cow meta file
+#define COW_FILE_DATA_MAGIC_VALUE ((uint64_t)0xEBE44D6E72F7825F) // Magic Value to recognize a Cow data file
```
## Data strucure
-![Datastructure](img/Bild1.jpg "")
+![Datastructure](img/Bild1.jpg)
# REST Api
diff --git a/src/fuse/cowfile.c b/src/fuse/cowfile.c
index fb900d8..14db252 100644
--- a/src/fuse/cowfile.c
+++ b/src/fuse/cowfile.c
@@ -54,11 +54,11 @@ static int getL2Offset( size_t offset )
* @brief computes the bit in the bitfield from the absolute file offset
*
* @param offset absolute file offset
- * @return int bit(0-39) in the bitfield
+ * @return int bit(0-319) in the bitfield
*/
static int getBitfieldOffset( size_t offset )
{
- return (int)( offset / DNBD3_BLOCK_SIZE ) % COW_BITFIELD_SIZE;
+ return (int)( offset / DNBD3_BLOCK_SIZE ) % (COW_BITFIELD_SIZE * 8);
}
/**
@@ -83,7 +83,7 @@ static void setBits( atomic_char *byte, int from, int to )
*/
static void setBitsInBitfield( atomic_char *bitfield, int from, int to )
{
- assert( from >= 0 || to < COW_BITFIELD_SIZE );
+ assert( from >= 0 || to < COW_BITFIELD_SIZE * 8 );
int start = from / 8;
int end = to / 8;
@@ -129,7 +129,7 @@ bool createSession( char *imageName, uint16_t version )
char url[300];
sprintf( url, COW_API_CREATE, cowServerAddress );
logadd( LOG_INFO, "COW_API_CREATE URL: %s", url );
- curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "POST" );
+ curl_easy_setopt( curl, CURLOPT_POST, 1L );
curl_easy_setopt( curl, CURLOPT_URL, url );
curl_mime *mime;
@@ -215,16 +215,16 @@ size_t curlReadCallbackUploadBlock( char *ptr, size_t size, size_t nmemb, void *
{
cow_curl_read_upload_t *uploadBlock = (cow_curl_read_upload_t *)userdata;
size_t len = 0;
- if ( uploadBlock->position < (size_t)metadata->bitfieldSize / 8 ) {
- size_t lenCpy = MIN( metadata->bitfieldSize / 8 - uploadBlock->position, size * nmemb );
+ if ( uploadBlock->position < (size_t)metadata->bitfieldSize ) {
+ size_t lenCpy = MIN( metadata->bitfieldSize - uploadBlock->position, size * nmemb );
memcpy( ptr, uploadBlock->block->bitfield + uploadBlock->position, lenCpy );
uploadBlock->position += lenCpy;
len += lenCpy;
}
- if ( uploadBlock->position >= (size_t)metadata->bitfieldSize / 8 ) {
- size_t lenRead = MIN( COW_METADATA_STORAGE_CAPACITY - ( uploadBlock->position - ( metadata->bitfieldSize / 8 ) ),
+ if ( uploadBlock->position >= (size_t)metadata->bitfieldSize ) {
+ size_t lenRead = MIN( COW_METADATA_STORAGE_CAPACITY - ( uploadBlock->position - ( metadata->bitfieldSize ) ),
( size * nmemb ) - len );
- off_t inBlockOffset = uploadBlock->position - metadata->bitfieldSize / 8;
+ off_t inBlockOffset = uploadBlock->position - metadata->bitfieldSize;
size_t lengthRead = pread( cow.fhd, ( ptr + len ), lenRead, uploadBlock->block->offset + inBlockOffset );
uploadBlock->position += lengthRead;
len += lengthRead;
@@ -255,10 +255,9 @@ bool uploadBlock( cow_block_metadata_t *block, uint32_t blocknumber, uint32_t ti
curl_easy_setopt( curl, CURLOPT_POST, 1L );
curl_easy_setopt( curl, CURLOPT_READFUNCTION, curlReadCallbackUploadBlock );
curl_easy_setopt( curl, CURLOPT_READDATA, (void *)&curlUploadBlock );
-
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(
- curl, CURLOPT_POSTFIELDSIZE_LARGE, (long)( metadata->bitfieldSize / 8 + COW_METADATA_STORAGE_CAPACITY ) );
+ curl, CURLOPT_POSTFIELDSIZE_LARGE, (long)( metadata->bitfieldSize + COW_METADATA_STORAGE_CAPACITY ) );
struct curl_slist *headers = NULL;
headers = curl_slist_append( headers, "Content-Type: application/octet-stream" );
@@ -267,13 +266,26 @@ bool uploadBlock( cow_block_metadata_t *block, uint32_t blocknumber, uint32_t ti
res = curl_easy_perform( curl );
-
/* Check for errors */
if ( res != CURLE_OK ) {
logadd( LOG_ERROR, "COW_API_UPDATE failed: %s\n", curl_easy_strerror( res ) );
curl_easy_reset( curl );
return false;
}
+ ///////////////// TODO DEBUG REMOVE LATER
+ double total;
+ res = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total);
+ if(CURLE_OK == res) {
+ curl_off_t ul;
+ res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD_T, &ul);
+ if(CURLE_OK == res) {
+ logadd( LOG_INFO, "Speed: %ld kb/s", (long) ((ul/total)/1000));
+ }
+ }
+ logadd( LOG_INFO, "CURLINFO_TOTAL_TIME: %f", total);
+ ////////////////////
+
+
long http_code = 0;
curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &http_code );
if ( http_code != 200 ) {
@@ -296,12 +308,29 @@ bool uploadBlock( cow_block_metadata_t *block, uint32_t blocknumber, uint32_t ti
bool mergeRequest()
{
CURLcode res;
- curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "GET" );
+ curl_easy_setopt( curl, CURLOPT_POST, 1L );
char url[400];
- sprintf( url, COW_API_START_MERGE, cowServerAddress, uuidStr, metadata->imageSize );
+ sprintf( url, COW_API_START_MERGE, cowServerAddress);
curl_easy_setopt( curl, CURLOPT_URL, url );
+
+ curl_mime *mime;
+ curl_mimepart *part;
+ mime = curl_mime_init( curl );
+ part = curl_mime_addpart( mime );
+
+ curl_mime_name( part, "guid" );
+ curl_mime_data( part, uuidStr, CURL_ZERO_TERMINATED );
+ part = curl_mime_addpart( mime );
+
+ curl_mime_name( part, "fileSize" );
+ char buf[21];
+ snprintf( buf, sizeof buf, "%" PRIu64, metadata->imageSize );
+ curl_mime_data( part, buf, CURL_ZERO_TERMINATED );
+ curl_easy_setopt( curl, CURLOPT_MIMEPOST, mime );
+
+
res = curl_easy_perform( curl );
if ( res != CURLE_OK ) {
logadd( LOG_WARNING, "COW_API_START_MERGE failed: %s\n", curl_easy_strerror( res ) );
@@ -433,7 +462,7 @@ void cowfile_uploader( void *something )
}
/**
- * @brief initializes the cow functionality, creates the .data & .meta file.
+ * @brief initializes the cow functionality, creates the data & meta file.
*
* @param path where the files should be stored
* @param image_Name name of the original file/image
@@ -446,13 +475,13 @@ bool cowfile_init(
char pathData[strlen( path ) + 6];
strcpy( pathMeta, path );
strcpy( pathData, path );
- strcat( pathMeta, ".meta" );
+ strcat( pathMeta, "/meta" );
if ( ( cow.fhm = open( pathMeta, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR ) ) == -1 ) {
- logadd( LOG_ERROR, "Could not create cow meta file. Bye.\n" );
+ logadd( LOG_ERROR, "Could not create cow meta file. Bye.\n %s \n", pathMeta );
return false;
}
- strcat( pathData, ".data" );
+ strcat( pathData, "/data" );
if ( ( cow.fhd = open( pathData, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR ) ) == -1 ) {
logadd( LOG_ERROR, "Could not create cow data file. Bye.\n" );
return false;
@@ -538,9 +567,9 @@ bool cowfile_init(
return true;
}
/**
- * @brief loads an existing cow state from the .meta & .data files
+ * @brief loads an existing cow state from the meta & data files
*
- * @param path where the .meta & .data file is located
+ * @param path where the meta & data file is located
* @param imageSizePtr
*/
@@ -551,8 +580,8 @@ bool cowfile_load( char *path, size_t **imageSizePtr, char *serverAddress )
char pathData[strlen( path ) + 6];
strcpy( pathMeta, path );
strcpy( pathData, path );
- strcat( pathMeta, ".meta" );
- strcat( pathData, ".data" );
+ strcat( pathMeta, "/meta" );
+ strcat( pathData, "/data" );
if ( ( cow.fhm = open( pathMeta, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ) ) == -1 ) {
logadd( LOG_ERROR, "Could not open cow meta file. Bye.\n" );
return false;
@@ -643,7 +672,7 @@ bool cowfile_load( char *path, size_t **imageSizePtr, char *serverAddress )
}
/**
- * @brief writes the given data in the .data file
+ * @brief writes the given data in the data file
*
* @param buffer containing the data
* @param size of the buffer
@@ -905,7 +934,6 @@ void cowfile_write( fuse_req_t req, cow_request_t *cowRequest, off_t offset, siz
writeData( cowRequest->writeBuffer + ( ( currentOffset - offset ) * !cowRequest->replyAttr ),
(ssize_t)sizeToWriteToBlock, sizeToWriteToBlock, cowRequest, metaBlock, inBlockOffset );
- cow_block_metadata_t *b = getBlock( l1Offset, l2Offset );
currentOffset += sizeToWriteToBlock;
currentOffset += endPaddedSize;
@@ -1009,7 +1037,7 @@ void cowfile_read( fuse_req_t req, size_t size, off_t offset )
bitfieldOffset++;
}
- if ( bitfieldOffset >= COW_BITFIELD_SIZE ) {
+ if ( bitfieldOffset >= COW_BITFIELD_SIZE * 8 ) {
bitfieldOffset = 0;
l2Offset++;
if ( l2Offset >= COW_L2_SIZE ) {
@@ -1029,7 +1057,7 @@ void cowfile_read( fuse_req_t req, size_t size, off_t offset )
if ( !isLocal ) {
readRemote( req, lastReadOffset, sizeToRead, cowRequest );
} else {
- // Compute the offset in the .data file where the read starts
+ // Compute the offset in the data file where the read starts
off_t localRead =
block->offset + ( ( lastReadOffset % COW_L2_STORAGE_CAPACITY ) % COW_METADATA_STORAGE_CAPACITY );
ssize_t totalBytesRead = 0;
@@ -1079,7 +1107,7 @@ fail:;
void createCowStatsFile( char* path ) {
char pathStatus[strlen( path ) + 11];
strcpy( pathStatus, path );
- strcat( pathStatus, "status.txt" );
+ strcat( pathStatus, "/status.txt" );
if ( ( cow.fhs = open( pathStatus, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR ) ) == -1 ) {
logadd( LOG_ERROR, "Could not create cow status file. Bye.\n" );
return false;
diff --git a/src/fuse/cowfile.h b/src/fuse/cowfile.h
index 48ba849..416a1fd 100644
--- a/src/fuse/cowfile.h
+++ b/src/fuse/cowfile.h
@@ -15,7 +15,7 @@
#include <curl/curl.h>
-#define COW_METADATA_STORAGE_CAPACITY ( COW_BITFIELD_SIZE * DNBD3_BLOCK_SIZE )
+#define COW_METADATA_STORAGE_CAPACITY ( COW_BITFIELD_SIZE * 8 * DNBD3_BLOCK_SIZE )
#define COW_L2_SIZE 1024
#define COW_L2_STORAGE_CAPACITY ( COW_L2_SIZE * COW_METADATA_STORAGE_CAPACITY )
#define container_of( ptr, type, member ) ( (type *)( (char *)( ptr ) - (char *)&( ( (type *)NULL )->member ) ) )