Add .INCOMPLETE file marker to flexnbd listen
We drop a marker onto the filesystem to say when we know the image we're serving is not yet ready.
This commit is contained in:
@@ -81,6 +81,12 @@ the source in the interim.
|
||||
To support transparently replacing an existing server, flexnbd can
|
||||
switch addresses once it has received a successful migration.
|
||||
|
||||
When `flexnbd listen` is run, it will create a file named
|
||||
<FILE>.INCOMPLETE next to FILE. This will be removed when a migration
|
||||
has successfully completed. The .INCOMPLETE file will be created before
|
||||
the listening socket is opened.
|
||||
|
||||
|
||||
Options
|
||||
^^^^^^^
|
||||
As for 'serve', with these additions:
|
||||
|
@@ -283,6 +283,85 @@ int flexnbd_default_deny( struct flexnbd * flexnbd )
|
||||
}
|
||||
|
||||
|
||||
char * flexnbd_incomplete_filename( struct flexnbd * flexnbd )
|
||||
{
|
||||
NULLCHECK( flexnbd );
|
||||
struct server * serve = flexnbd_server( flexnbd );
|
||||
|
||||
return serve->filename_incomplete;
|
||||
}
|
||||
|
||||
void make_writable( const char * filename )
|
||||
{
|
||||
NULLCHECK( filename );
|
||||
FATAL_IF_NEGATIVE( chmod( filename, S_IWUSR ),
|
||||
"Couldn't chmod %s: %s",
|
||||
filename,
|
||||
strerror( errno ) );
|
||||
}
|
||||
|
||||
/** Drops a marker file on the filesystem to show that the image we're
|
||||
* serving hasn't yet finished its migration yet
|
||||
*/
|
||||
void flexnbd_mark_incomplete( struct flexnbd * flexnbd )
|
||||
{
|
||||
char * filename =
|
||||
flexnbd_incomplete_filename( flexnbd );
|
||||
int fd;
|
||||
|
||||
NULLCHECK( filename );
|
||||
|
||||
/* It's OK if the file already exists - it's perfectly possible
|
||||
* that a previous process died part-way through and left it
|
||||
* behind. However, we might have left the file mode in a bad
|
||||
* state.
|
||||
*/
|
||||
|
||||
struct stat ignored;
|
||||
int exists = stat( filename, &ignored ) == 0;
|
||||
if ( exists ) {
|
||||
/* definitely there, need to chmod */
|
||||
debug( "%s exists, making it writable", filename );
|
||||
make_writable( filename );
|
||||
}
|
||||
else if ( ENOENT != errno ) {
|
||||
/* Can't tell if it's there or not, weirdness. */
|
||||
fatal( "Unable to stat %s", filename );
|
||||
}
|
||||
else { /* definitely not there. NOP. */ }
|
||||
|
||||
|
||||
fd = open( filename, O_CREAT|O_WRONLY, 0 );
|
||||
FATAL_IF_NEGATIVE( fd,
|
||||
"Couldn't open %s: %s",
|
||||
filename,
|
||||
strerror( errno ) );
|
||||
|
||||
/* Minor race here - in principle we could see the file
|
||||
* disappear before the chmod */
|
||||
close( fd );
|
||||
}
|
||||
|
||||
|
||||
/** Removes the .INCOMPLETE marker file from the filesystem. Call this
|
||||
* only when you know the migration has completed successfully.
|
||||
*/
|
||||
void flexnbd_mark_complete( struct flexnbd * flexnbd )
|
||||
{
|
||||
char * filename =
|
||||
flexnbd_incomplete_filename( flexnbd );
|
||||
|
||||
NULLCHECK( filename );
|
||||
|
||||
make_writable( filename );
|
||||
|
||||
FATAL_IF_NEGATIVE( unlink( filename ),
|
||||
"Couldn't unlink %s: %s",
|
||||
filename,
|
||||
strerror( errno ) );
|
||||
}
|
||||
|
||||
|
||||
int flexnbd_serve( struct flexnbd * flexnbd )
|
||||
{
|
||||
NULLCHECK( flexnbd );
|
||||
|
@@ -69,6 +69,9 @@ void flexnbd_set_server( struct flexnbd * flexnbd, struct server * serve );
|
||||
void flexnbd_switch( struct flexnbd * flexnbd, struct server *(listen_cb)(struct listen *) );
|
||||
int flexnbd_signal_fd( struct flexnbd * flexnbd );
|
||||
|
||||
void flexnbd_mark_incomplete( struct flexnbd * flexnbd );
|
||||
void flexnbd_mark_complete( struct flexnbd * flexnbd );
|
||||
|
||||
|
||||
int flexnbd_serve( struct flexnbd * flexnbd );
|
||||
struct server * flexnbd_server( struct flexnbd * flexnbd );
|
||||
|
@@ -83,6 +83,7 @@ int do_listen( struct listen * listen )
|
||||
flexnbd_lock_switch( listen->flexnbd );
|
||||
{
|
||||
flexnbd_set_server( listen->flexnbd, listen->init_serve );
|
||||
flexnbd_mark_incomplete( listen->flexnbd );
|
||||
}
|
||||
flexnbd_unlock_switch( listen->flexnbd );
|
||||
|
||||
@@ -93,6 +94,8 @@ int do_listen( struct listen * listen )
|
||||
|
||||
|
||||
if( have_control ) {
|
||||
flexnbd_mark_complete( listen->flexnbd );
|
||||
|
||||
info( "Taking control.");
|
||||
flexnbd_switch( listen->flexnbd, listen_switch );
|
||||
/* WATCH FOR RACES HERE: the server hasn't been
|
||||
|
Reference in New Issue
Block a user