summaryrefslogtreecommitdiffstats
path: root/src/server/image.c
diff options
context:
space:
mode:
authorSimon Rettberg2015-01-27 19:39:04 +0100
committerSimon Rettberg2015-01-27 19:39:04 +0100
commit2b722b756864b14b6299a8b24067a37e12aabfc4 (patch)
treec73c47c7f4a8a9a24f218ca865176c3b237687a4 /src/server/image.c
parent[SERVER] Crank up warning levels of gcc and fix them all (mostly sign compare... (diff)
downloaddnbd3-2b722b756864b14b6299a8b24067a37e12aabfc4.tar.gz
dnbd3-2b722b756864b14b6299a8b24067a37e12aabfc4.tar.xz
dnbd3-2b722b756864b14b6299a8b24067a37e12aabfc4.zip
[SERVER] Fix automatic proxying to use supplied connection; fix race condition in uplink_init
Diffstat (limited to 'src/server/image.c')
-rw-r--r--src/server/image.c30
1 files changed, 16 insertions, 14 deletions
diff --git a/src/server/image.c b/src/server/image.c
index 27b737e..d8c7113 100644
--- a/src/server/image.c
+++ b/src/server/image.c
@@ -40,7 +40,7 @@ typedef struct
time_t deadline;
} imagecache;
static imagecache remoteCloneCache[CACHELEN];
-static int remoteCloneCacheIndex = -1;
+static int remoteCloneCacheIndex = 0;
// ##########################################
@@ -232,7 +232,7 @@ bool image_saveCacheMap(dnbd3_image_t *image)
* point...
* Locks on: _images_lock, _images[].lock
*/
-dnbd3_image_t* image_get(char *name, uint16_t revision)
+dnbd3_image_t* image_get(char *name, uint16_t revision, bool checkIfWorking)
{
int i;
dnbd3_image_t *candidate = NULL;
@@ -265,6 +265,8 @@ dnbd3_image_t* image_get(char *name, uint16_t revision)
candidate->users++;
spin_unlock( &candidate->lock );
+ if ( !checkIfWorking ) return candidate;
+
// Found, see if it works
struct stat st;
if ( candidate->working && stat( candidate->path, &st ) < 0 ) {
@@ -420,16 +422,18 @@ static dnbd3_image_t* image_free(dnbd3_image_t *image)
//
image_saveCacheMap( image );
uplink_shutdown( image );
+ spin_lock( &image->lock );
free( image->cache_map );
free( image->crc32 );
free( image->path );
free( image->lower_name );
+ spin_unlock( &image->lock );
if ( image->cacheFd != -1 ) {
close( image->cacheFd );
}
spin_destroy( &image->lock );
//
- memset( image, 0, sizeof(dnbd3_image_t) );
+ memset( image, 0, sizeof(*image) );
free( image );
return NULL ;
}
@@ -557,7 +561,7 @@ static bool image_load(char *base, char *path, int withUplink)
strtolower( imgName );
// Get pointer to already existing image if possible
- existing = image_get( imgName, revision );
+ existing = image_get( imgName, revision, true );
// ### Now load the actual image related data ###
fdImage = open( path, O_RDONLY );
@@ -874,19 +878,15 @@ bool image_create(char *image, int revision, uint64_t size)
*/
dnbd3_image_t* image_getOrClone(char *name, uint16_t revision)
{
- if ( !_isProxy ) return image_get( name, revision );
+ if ( !_isProxy ) return image_get( name, revision, true );
int i;
const size_t len = strlen( name );
// Sanity check
if ( len == 0 || name[len - 1] == '/' || name[0] == '/' ) return NULL ;
// Already existing locally?
- dnbd3_image_t *image = image_get( name, revision );
+ dnbd3_image_t *image = image_get( name, revision, true );
if ( image != NULL ) return image;
// Doesn't exist, try remote if not already tried it recently
- if ( remoteCloneCacheIndex == -1 ) {
- remoteCloneCacheIndex = 0;
- memset( remoteCloneCache, 0, sizeof(remoteCloneCache) );
- }
const time_t now = time( NULL );
char *cmpname = name;
@@ -897,10 +897,10 @@ dnbd3_image_t* image_getOrClone(char *name, uint16_t revision)
|| remoteCloneCache[i].deadline < now
|| strcmp( cmpname, remoteCloneCache[i].name ) != 0 ) continue;
pthread_mutex_unlock( &remoteCloneLock ); // Was recently checked...
- return image_get( name, revision );
+ return image_get( name, revision, true );
}
// Re-check to prevent two clients at the same time triggering this
- image = image_get( name, revision );
+ image = image_get( name, revision, true );
if ( image != NULL ) {
pthread_mutex_unlock( &remoteCloneLock );
return image;
@@ -940,11 +940,13 @@ dnbd3_image_t* image_getOrClone(char *name, uint16_t revision)
}
pthread_mutex_unlock( &remoteCloneLock );
// If everything worked out, this call should now actually return the image
- image = image_get( name, remoteRid );
+ image = image_get( name, remoteRid, false );
if ( image != NULL && uplinkSock != -1 && uplinkServer != NULL ) {
// If so, init the uplink and pass it the socket
uplink_init( image, uplinkSock, uplinkServer );
- image->working = true;
+ i = 0;
+ while ( !image->working && ++i < 100 )
+ usleep( 1000 );
} else if ( uplinkSock >= 0 ) {
close( uplinkSock );
}