summaryrefslogtreecommitdiffstats
path: root/src/server/image.c
diff options
context:
space:
mode:
authorSimon Rettberg2025-12-09 15:49:52 +0100
committerSimon Rettberg2025-12-09 15:49:52 +0100
commitb3062b85b6778acb499998216fb8f3fd71119583 (patch)
tree2df3de5930e1430cfaf792f4b6dae7b8993dfc0c /src/server/image.c
parent[KERNEL] Fix build on newer gcc (diff)
parent[SERVER] iscsi: More comments (diff)
downloaddnbd3-b3062b85b6778acb499998216fb8f3fd71119583.tar.gz
dnbd3-b3062b85b6778acb499998216fb8f3fd71119583.tar.xz
dnbd3-b3062b85b6778acb499998216fb8f3fd71119583.zip
Merge branch 'iscsi-refactor'
Diffstat (limited to 'src/server/image.c')
-rw-r--r--src/server/image.c76
1 files changed, 63 insertions, 13 deletions
diff --git a/src/server/image.c b/src/server/image.c
index f438c18..5d1f4a1 100644
--- a/src/server/image.c
+++ b/src/server/image.c
@@ -55,12 +55,14 @@ static dnbd3_cache_map_t* image_loadCacheMap(const char * const imagePath, const
static uint32_t* image_loadCrcList(const char * const imagePath, const int64_t fileSize, uint32_t *masterCrc);
static bool image_checkRandomBlocks(dnbd3_image_t *image, const int count, int fromFd);
static void* closeUnusedFds(void*);
+static dnbd3_image_t* runEnsureOpenCheck(dnbd3_image_t *candidate);
static bool isImageFromUpstream(dnbd3_image_t *image);
static void* saveLoadAllCacheMaps(void*);
static void saveCacheMap(dnbd3_image_t *image);
static void allocCacheMap(dnbd3_image_t *image, bool complete);
static void saveMetaData(dnbd3_image_t *image, ticks *now, time_t walltime);
static void loadImageMeta(dnbd3_image_t *image);
+static void calculateImageWwn(dnbd3_image_t *image);
static void cmfree(ref *ref)
{
@@ -334,6 +336,38 @@ dnbd3_image_t* image_byId(int imgId)
}
/**
+ * Get image by its wwn and revision id.
+ * Locks on imageListLock.
+ */
+dnbd3_image_t* image_getByWwn(uint64_t wwn, uint16_t revision, bool ensureFdOpen)
+{
+ int i;
+ dnbd3_image_t *candidate = NULL;
+
+ mutex_lock( &imageListLock );
+ for ( i = 0; i < _num_images; ++i ) {
+ dnbd3_image_t * const image = _images[i];
+ if ( image == NULL || wwn != image->wwn )
+ continue;
+ if ( revision == image->rid ) {
+ candidate = image;
+ break;
+ } else if ( revision == 0 && (candidate == NULL || candidate->rid < image->rid) ) {
+ candidate = image;
+ }
+ }
+ if ( candidate != NULL ) {
+ candidate->users++;
+ }
+ mutex_unlock( &imageListLock );
+
+ if ( candidate != NULL && ensureFdOpen ) {
+ candidate = runEnsureOpenCheck( candidate );
+ }
+ return candidate;
+}
+
+/**
* Get an image by name+rid. This function increases a reference counter,
* so you HAVE TO CALL image_release for every image_get() call at some
* point...
@@ -358,19 +392,19 @@ dnbd3_image_t* image_get(const char *name, uint16_t revision, bool ensureFdOpen)
candidate = image;
}
}
-
- // Not found
- if ( candidate == NULL ) {
- mutex_unlock( &imageListLock );
- return NULL ;
+ if ( candidate != NULL ) {
+ candidate->users++;
}
-
- candidate->users++;
mutex_unlock( &imageListLock );
- if ( !ensureFdOpen ) // Don't want to re-check
- return candidate;
+ if ( candidate != NULL && ensureFdOpen ) {
+ candidate = runEnsureOpenCheck( candidate );
+ }
+ return candidate;
+}
+static dnbd3_image_t* runEnsureOpenCheck(dnbd3_image_t *candidate)
+{
if ( image_ensureOpen( candidate ) && !candidate->problem.read )
return candidate; // We have a read fd and no read or changed problems
@@ -386,7 +420,7 @@ dnbd3_image_t* image_get(const char *name, uint16_t revision, bool ensureFdOpen)
// make a copy of the image struct but keep the old one around. If/When it's not being used
// anymore, it will be freed automatically.
logadd( LOG_DEBUG1, "Reloading image file %s because of read problem/changed", candidate->path );
- dnbd3_image_t *img = calloc( sizeof(dnbd3_image_t), 1 );
+ dnbd3_image_t *img = calloc( 1, sizeof(dnbd3_image_t) );
img->path = strdup( candidate->path );
img->name = strdup( candidate->name );
img->virtualFilesize = candidate->virtualFilesize;
@@ -399,6 +433,7 @@ dnbd3_image_t* image_get(const char *name, uint16_t revision, bool ensureFdOpen)
img->problem.read = true;
img->problem.changed = candidate->problem.changed;
img->ref_cacheMap = NULL;
+ calculateImageWwn( candidate );
mutex_init( &img->lock, LOCK_IMAGE );
if ( candidate->crc32 != NULL ) {
const size_t mb = IMGSIZE_TO_HASHBLOCKS( candidate->virtualFilesize ) * sizeof(uint32_t);
@@ -426,7 +461,8 @@ dnbd3_image_t* image_get(const char *name, uint16_t revision, bool ensureFdOpen)
// readFd == -1 and problem.read == true
}
- return candidate; // We did all we can, hopefully it's working
+ // We did all we can, hopefully it's working
+ return candidate;
}
/**
@@ -908,6 +944,7 @@ static bool image_load(char *base, char *path, bool withUplink)
image->completenessEstimate = -1;
mutex_init( &image->lock, LOCK_IMAGE );
loadImageMeta( image );
+ calculateImageWwn( image );
// Prevent freeing in cleanup
cache = NULL;
@@ -1324,7 +1361,7 @@ server_fail: ;
image_release( image );
}
// If everything worked out, this call should now actually return the image
- image = image_get( name, acceptedRemoteRid, false );
+ image = image_get( name, revision == 0 ? acceptedRemoteRid : revision, false );
if ( image != NULL && uplinkSock != -1 ) {
// If so, init the uplink and pass it the socket
if ( !uplink_init( image, uplinkSock, &uplinkServer, remoteProtocolVersion ) ) {
@@ -1609,9 +1646,10 @@ json_t* image_getListAsJson()
addproblem(uplink, 3);
addproblem(queue, 4);
- jsonImage = json_pack( "{sisssisisisisIsi}",
+ jsonImage = json_pack( "{sisssIsisisisisIsi}",
"id", image->id, // id, name, rid never change, so access them without locking
"name", image->name,
+ "wwn", (json_int_t)image->wwn,
"rid", (int) image->rid,
"users", image->users,
"complete", completeness,
@@ -2125,6 +2163,18 @@ static void loadImageMeta(dnbd3_image_t *image)
timing_gets( &image->atime, offset );
}
+static void calculateImageWwn(dnbd3_image_t *image)
+{
+ uint64_t value = 0ULL;
+ const char *name = image->name;
+
+ while ( *name != '\0' ) {
+ value = (value * 131ULL) + *name++;
+ }
+ const uint64_t id_a = (value & 0xFFF000000ULL) << 24ULL;
+ image->wwn = (value & 0xFFFFFFULL) | 0x2000000347000000ULL | id_a;
+}
+
void image_checkForNextFullCheck(void)
{
int i;