[Spice-devel] [PATCH 32/35] zap migration code
Gerd Hoffmann
kraxel at redhat.com
Wed May 12 04:32:26 PDT 2010
Drop all code which depends on accessing the migration file handle.
---
server/reds.c | 642 +------------------------------------------------
server/vd_interface.h | 7 +-
2 files changed, 11 insertions(+), 638 deletions(-)
diff --git a/server/reds.c b/server/reds.c
index 0795d90..e499770 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3166,58 +3166,6 @@ typedef struct OptionsMap {
int val;
} OptionsMap;
-static int find_option(const char *str, OptionsMap *options_map)
-{
- int i = 0;
-
- for (i = 0; options_map[i].name != NULL; i++) {
- if (strcmp(str, options_map[i].name) == 0) {
- return options_map[i].val;
- }
- }
- return SPICE_OPTION_INVALID;
-}
-
-static void clear_blanks(char **ptr)
-{
- char *str = *ptr;
- while (isspace(*str)) {
- str++;
- }
- while (isspace(str[strlen(str) - 1])) {
- str[strlen(str) - 1] = 0;
- }
- *ptr = str;
-}
-
-static int get_option(char **args, char **out_val, OptionsMap *map, char seperator)
-{
- char *p;
- char *next;
- char *val;
-
- ASSERT(args && out_val);
-
- p = *args;
- if ((next = strchr(p, seperator))) {
- *next = 0;
- *args = next + 1;
- } else {
- *args = NULL;
- }
-
- if ((val = strchr(p, '='))) {
- *(val++) = 0;
- clear_blanks(&val);
- *out_val = (strlen(val) == 0) ? NULL : val;
- } else {
- *out_val = NULL;
- }
-
- clear_blanks(&p);
- return find_option(p, map);
-}
-
enum {
SPICE_TICKET_OPTION_INVALID,
SPICE_TICKET_OPTION_EXPIRATION,
@@ -3258,41 +3206,9 @@ static void set_one_channel_security(int id, uint32_t security)
#define REDS_SAVE_VERSION 1
-static OptionsMap spice_mig_options[] = {
- {"spicesport", SPICE_OPTION_SPORT},
- {"spiceport", SPICE_OPTION_PORT},
- {"spicehost", SPICE_OPTION_HOST},
- {NULL, 0},
-};
-
-struct RedsMigSpice;
-
-typedef struct RedsMigRead {
- uint8_t buf[RECIVE_BUF_SIZE];
- uint32_t end_pos;
- uint32_t size;
-
- void (*handle_data)(struct RedsMigSpice *message);
-} RedsMigRead;
-
-typedef struct RedsMigWrite {
- uint8_t buf[SEND_BUF_SIZE];
- uint8_t *now;
- uint32_t length;
-
- void (*handle_done)(struct RedsMigSpice *s);
-} RedsMigWrite;
-
typedef struct RedsMigSpice {
- int fd;
- SpiceWatch *watch;
- RedsMigWrite write;
- RedsMigRead read;
-
char pub_key[SPICE_TICKET_PUBKEY_BYTES];
uint32_t mig_key;
-
- char *local_args;
char *host;
int port;
int sport;
@@ -3310,104 +3226,6 @@ typedef struct RedsMigCertPubKeyInfo {
uint32_t len;
} RedsMigCertPubKeyInfo;
-static int reds_mig_actual_read(RedsMigSpice *s)
-{
- for (;;) {
- uint8_t *buf = s->read.buf;
- uint32_t pos = s->read.end_pos;
- int n;
- n = read(s->fd, buf + pos, s->read.size - pos);
- if (n <= 0) {
- if (n == 0) {
- return -1;
- }
- switch (errno) {
- case EAGAIN:
- return 0;
- case EINTR:
- break;
- case EPIPE:
- return -1;
- default:
- red_printf("%s", strerror(errno));
- return -1;
- }
- } else {
- s->read.end_pos += n;
- if (s->read.end_pos == s->read.size) {
- s->read.handle_data(s);
- return 0;
- }
- }
- }
-}
-
-static int reds_mig_actual_write(RedsMigSpice *s)
-{
- if (!s->write.length) {
- return 0;
- }
-
- while (s->write.length) {
- int n;
-
- n = write(s->fd, s->write.now, s->write.length);
- if (n <= 0) {
- if (n == 0) {
- return -1;
- }
- switch (errno) {
- case EAGAIN:
- return 0;
- case EINTR:
- break;
- case EPIPE:
- return -1;
- default:
- red_printf("%s", strerror(errno));
- return -1;
- }
- } else {
- s->write.now += n;
- s->write.length -= n;
- }
- }
-
- s->write.handle_done(s);
- return 0;
-}
-
-static void reds_mig_failed(RedsMigSpice *s)
-{
- red_printf("");
- core->watch_remove(s->watch);
- s->watch = NULL;
- if (s->local_args) {
- free(s->local_args);
- }
- free(s);
-
- reds_mig_disconnect();
-}
-
-static void reds_mig_event(int fd, int event, void *data)
-{
- RedsMigSpice *s = data;
-
- if (event & SPICE_WATCH_EVENT_READ) {
- if (reds_mig_actual_read((RedsMigSpice *)data)) {
- red_printf("read error cannot continue spice migration");
- reds_mig_failed(s);
- }
- }
- if (event & SPICE_WATCH_EVENT_WRITE) {
- if (reds_mig_actual_write((RedsMigSpice *)data)) {
- red_printf("write error cannot continue spice migration");
- reds_mig_failed(s);
- }
- }
-}
-
static void reds_mig_continue(RedsMigSpice *s)
{
SpiceMsgMainMigrationBegin *migrate;
@@ -3415,8 +3233,6 @@ static void reds_mig_continue(RedsMigSpice *s)
int host_len;
red_printf("");
- core->watch_remove(s->watch);
- s->watch = NULL;
host_len = strlen(s->host) + 1;
item = new_simple_out_item(SPICE_MSG_MAIN_MIGRATE_BEGIN,
sizeof(SpiceMsgMainMigrationBegin) + host_len + s->cert_pub_key_len);
@@ -3432,174 +3248,15 @@ static void reds_mig_continue(RedsMigSpice *s)
memcpy((uint8_t*)(migrate) + migrate->pub_key_offset, s->cert_pub_key, s->cert_pub_key_len);
reds_push_pipe_item(&item->base);
- free(s->local_args);
free(s);
reds->mig_wait_connect = TRUE;
core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
}
-static void reds_mig_receive_ack(RedsMigSpice *s)
-{
- s->read.size = sizeof(uint32_t);
- s->read.end_pos = 0;
- s->read.handle_data = reds_mig_continue;
-
- core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
-}
-
-static void reds_mig_send_link_id(RedsMigSpice *s)
-{
- RedsMigSpiceMessage *data = (RedsMigSpiceMessage *)s->write.buf;
-
- memcpy(&data->link_id, &reds->link_id, sizeof(reds->link_id));
-
- s->write.now = s->write.buf;
- s->write.length = sizeof(RedsMigSpiceMessage);
- s->write.handle_done = reds_mig_receive_ack;
-
- core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
-}
-
-static void reds_mig_send_ticket(RedsMigSpice *s)
-{
- EVP_PKEY *pubkey = NULL;
- BIO *bio_key;
- RSA *rsa;
- int rsa_size = 0;
-
- red_printf("");
-
- bio_key = BIO_new(BIO_s_mem());
- if (bio_key != NULL) {
- BIO_write(bio_key, s->read.buf, SPICE_TICKET_PUBKEY_BYTES);
- pubkey = d2i_PUBKEY_bio(bio_key, NULL);
- rsa = pubkey->pkey.rsa;
- rsa_size = RSA_size(rsa);
- if (RSA_public_encrypt(strlen(reds->taTicket.password) + 1,
- (unsigned char *)reds->taTicket.password,
- (uint8_t *)(s->write.buf),
- rsa, RSA_PKCS1_OAEP_PADDING) > 0) {
- s->write.length = RSA_size(rsa);
- s->write.now = s->write.buf;
- s->write.handle_done = reds_mig_send_link_id;
- core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
- } else {
- reds_mig_failed(s);
- }
- } else {
- reds_mig_failed(s);
- }
-
- EVP_PKEY_free(pubkey);
- BIO_free(bio_key);
-}
-
-static void reds_mig_receive_cert_public_key(RedsMigSpice *s)
-{
- s->cert_pub_key = spice_memdup(s->read.buf, s->cert_pub_key_len);
-
- s->read.size = SPICE_TICKET_PUBKEY_BYTES;
- s->read.end_pos = 0;
- s->read.handle_data = reds_mig_send_ticket;
-
- core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
-}
-
-static void reds_mig_receive_cert_public_key_info(RedsMigSpice *s)
-{
- RedsMigCertPubKeyInfo* pubkey_info = (RedsMigCertPubKeyInfo*)s->read.buf;
- s->cert_pub_key_type = pubkey_info->type;
- s->cert_pub_key_len = pubkey_info->len;
-
- if (s->cert_pub_key_len > RECIVE_BUF_SIZE) {
- red_printf("certificate public key length exceeds buffer size");
- reds_mig_failed(s);
- return;
- }
-
- if (s->cert_pub_key_len) {
- s->read.size = s->cert_pub_key_len;
- s->read.end_pos = 0;
- s->read.handle_data = reds_mig_receive_cert_public_key;
- } else {
- s->cert_pub_key = NULL;
- s->read.size = SPICE_TICKET_PUBKEY_BYTES;
- s->read.end_pos = 0;
- s->read.handle_data = reds_mig_send_ticket;
- }
-
- core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ);
-}
-
-static void reds_mig_handle_send_abort_done(RedsMigSpice *s)
-{
- reds_mig_failed(s);
-}
-
-static void reds_mig_receive_version(RedsMigSpice *s)
-{
- uint32_t* dest_version;
- uint32_t resault;
- dest_version = (uint32_t*)s->read.buf;
- resault = REDS_MIG_ABORT;
- memcpy(s->write.buf, &resault, sizeof(resault));
- s->write.length = sizeof(resault);
- s->write.now = s->write.buf;
- s->write.handle_done = reds_mig_handle_send_abort_done;
- core->watch_update_mask(s->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE);
-}
-
-static void reds_mig_control(RedsMigSpice *spice_migration)
-{
- uint32_t *control;
-
- core->watch_update_mask(spice_migration->watch, 0);
- control = (uint32_t *)spice_migration->read.buf;
-
- switch (*control) {
- case REDS_MIG_CONTINUE:
- spice_migration->read.size = sizeof(RedsMigCertPubKeyInfo);
- spice_migration->read.end_pos = 0;
- spice_migration->read.handle_data = reds_mig_receive_cert_public_key_info;
-
- core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
- break;
- case REDS_MIG_ABORT:
- red_printf("abort");
- reds_mig_failed(spice_migration);
- break;
- case REDS_MIG_DIFF_VERSION:
- red_printf("different versions");
- spice_migration->read.size = sizeof(uint32_t);
- spice_migration->read.end_pos = 0;
- spice_migration->read.handle_data = reds_mig_receive_version;
-
- core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
- break;
- default:
- red_printf("invalid control");
- reds_mig_failed(spice_migration);
- }
-}
-
-static void reds_mig_receive_control(RedsMigSpice *spice_migration)
-{
- spice_migration->read.size = sizeof(uint32_t);
- spice_migration->read.end_pos = 0;
- spice_migration->read.handle_data = reds_mig_control;
-
- core->watch_update_mask(spice_migration->watch, SPICE_WATCH_EVENT_READ);
-}
-
-static void reds_mig_started(void *opaque, const char *in_args)
+static void reds_mig_started(void *opaque)
{
RedsMigSpice *spice_migration = NULL;
- uint32_t *version;
- char *val;
- char *args;
- int option;
- ASSERT(in_args);
red_printf("");
reds->mig_inprogress = TRUE;
@@ -3627,48 +3284,7 @@ static void reds_mig_started(void *opaque, const char *in_args)
spice_migration->port = -1;
spice_migration->sport = -1;
- spice_migration->local_args = spice_strdup(in_args);
-
- args = spice_migration->local_args;
- do {
- switch (option = get_option(&args, &val, spice_mig_options, ',')) {
- case SPICE_OPTION_SPORT: {
- char *endptr;
-
- if (!val) {
- goto error;
- }
- spice_migration->sport = strtol(val, &endptr, 0);
- if (endptr != val + strlen(val) || spice_migration->sport < 0 ||
- spice_migration->sport > 0xffff) {
- goto error;
- }
- break;
- }
- case SPICE_OPTION_PORT: {
- char *endptr;
-
- if (!val) {
- goto error;
- }
- spice_migration->port = strtol(val, &endptr, 0);
- if (
- endptr != val + strlen(val) ||
- spice_migration->port < 0 ||
- spice_migration->port > 0xffff
- ) {
- goto error;
- }
- break;
- }
- case SPICE_OPTION_HOST:
- if (!val) {
- goto error;
- }
- spice_migration->host = val;
- break;
- }
- } while (args);
+ /* FIXME */
if ((spice_migration->sport == -1 && spice_migration->port == -1) || !spice_migration->host) {
red_printf("invalid args port %d sport %d host %s",
@@ -3678,31 +3294,12 @@ static void reds_mig_started(void *opaque, const char *in_args)
goto error;
}
- spice_migration->fd = mig->begin_hook(mig, reds->mig_notifier);
-
- if (spice_migration->fd == -1) {
- goto error;
- }
-
- spice_migration->write.now = spice_migration->write.buf;
- spice_migration->write.length = sizeof(uint32_t);
- version = (uint32_t *)spice_migration->write.buf;
- *version = REDS_MIG_VERSION;
- spice_migration->write.handle_done = reds_mig_receive_control;
- spice_migration->watch = core->watch_add(spice_migration->fd,
- SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE,
- reds_mig_event,
- spice_migration);
+ /* FIXME: send SPICE_MSG_MAIN_MIGRATE_BEGIN ??? */
+ reds_mig_continue(spice_migration);
return;
error:
- if (spice_migration) {
- if (spice_migration->local_args) {
- free(spice_migration->local_args);
- }
- free(spice_migration);
- }
-
+ free(spice_migration);
reds_mig_disconnect();
}
@@ -3749,228 +3346,6 @@ static void reds_mig_finished(void *opaque, int completed)
}
}
-static int write_all(int fd, const void *in_buf, int len1)
-{
- int ret, len;
- uint8_t *buf = (uint8_t *)in_buf;
-
- len = len1;
- while (len > 0) {
- ret = write(fd, buf, len);
- if (ret < 0) {
- if (errno != EINTR && errno != EAGAIN) {
- return -1;
- }
- } else if (ret == 0) {
- break;
- } else {
- buf += ret;
- len -= ret;
- }
- }
- return len1 - len;
-}
-
-static int read_all(int fd, void *in_nuf, int lenl)
-{
- int ret, len;
- uint8_t *buf = in_nuf;
-
- len = lenl;
- while (len > 0) {
- ret = read(fd, buf, len);
- if (ret < 0) {
- if (errno != EINTR && errno != EAGAIN) {
- return -1;
- }
- } else if (ret == 0) {
- break;
- } else {
- buf += ret;
- len -= ret;
- }
- }
- return lenl - len;
-}
-
-static void reds_mig_read_all(int fd, void *buf, int len, const char *name)
-{
- int n = read_all(fd, buf, len);
- if (n != len) {
- red_error("read %s failed, n=%d (%s)", name, n, strerror(errno));
- }
-}
-
-static void reds_mig_write_all(int fd, void *buf, int len, const char *name)
-{
- int n = write_all(fd, buf, len);
- if (n != len) {
- red_error("write %s faile, n=%d (%s)", name, n, strerror(errno));
- }
-}
-
-static void reds_mig_send_cert_public_key(int fd)
-{
- FILE* cert_file;
- X509* x509;
- EVP_PKEY* pub_key;
- unsigned char* pp = NULL;
- int length;
- BIO* mem_bio;
- RedsMigCertPubKeyInfo pub_key_info_msg;
-
- if (spice_secure_port == -1) {
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_INVALID;
- pub_key_info_msg.len = 0;
- reds_mig_write_all(fd, &pub_key_info_msg, sizeof(pub_key_info_msg), "cert public key info");
- return;
- }
-
- cert_file = fopen(ssl_parameters.certs_file, "r");
- if (!cert_file) {
- red_error("opening certificate failed");
- }
-
- x509 = PEM_read_X509_AUX(cert_file, NULL, NULL, NULL);
- if (!x509) {
- red_error("reading x509 cert failed");
- }
- pub_key = X509_get_pubkey(x509);
- if (!pub_key) {
- red_error("reading public key failed");
- }
-
- mem_bio = BIO_new(BIO_s_mem());
- i2d_PUBKEY_bio(mem_bio, pub_key);
- if (BIO_flush(mem_bio) != 1) {
- red_error("bio flush failed");
- }
- length = BIO_get_mem_data(mem_bio, &pp);
-
- switch(pub_key->type) {
- case EVP_PKEY_RSA:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_RSA;
- break;
- case EVP_PKEY_RSA2:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_RSA2;
- break;
- case EVP_PKEY_DSA:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA;
- break;
- case EVP_PKEY_DSA1:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA1;
- break;
- case EVP_PKEY_DSA2:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA2;
- break;
- case EVP_PKEY_DSA3:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA3;
- break;
- case EVP_PKEY_DSA4:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DSA4;
- break;
- case EVP_PKEY_DH:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_DH;
- break;
- case EVP_PKEY_EC:
- pub_key_info_msg.type = SPICE_PUBKEY_TYPE_EC;
- break;
- default:
- red_error("invalid public key type");
- }
- pub_key_info_msg.len = length;
- reds_mig_write_all(fd, &pub_key_info_msg, sizeof(pub_key_info_msg), "cert public key info");
- reds_mig_write_all(fd, pp, length, "cert public key");
-
- BIO_free(mem_bio);
- fclose(cert_file);
- EVP_PKEY_free(pub_key);
- X509_free(x509);
-}
-
-static void reds_mig_recv(void *opaque, int fd)
-{
- uint32_t ack_message = *(uint32_t *)"ack_";
- char password[SPICE_MAX_PASSWORD_LENGTH];
- RedsMigSpiceMessage mig_message;
- unsigned long f4 = RSA_F4;
- TicketInfo ticketing_info;
- uint32_t version;
- uint32_t resault;
- BIO *bio;
-
- BUF_MEM *buff;
-
- reds_mig_read_all(fd, &version, sizeof(version), "version");
- // starting from version 3, if the version of the src is bigger
- // than ours, we send our version to the src.
- if (version < REDS_MIG_VERSION) {
- resault = REDS_MIG_ABORT;
- reds_mig_write_all(fd, &resault, sizeof(resault), "resault");
- mig->notifier_done(mig, reds->mig_notifier);
- return;
- } else if (version > REDS_MIG_VERSION) {
- uint32_t src_resault;
- uint32_t self_version = REDS_MIG_VERSION;
- resault = REDS_MIG_DIFF_VERSION;
- reds_mig_write_all(fd, &resault, sizeof(resault), "resault");
- reds_mig_write_all(fd, &self_version, sizeof(self_version), "dest-version");
- reds_mig_read_all(fd, &src_resault, sizeof(src_resault), "src resault");
-
- if (src_resault == REDS_MIG_ABORT) {
- red_printf("abort (response to REDS_MIG_DIFF_VERSION)");
- mig->notifier_done(mig, reds->mig_notifier);
- return;
- } else if (src_resault != REDS_MIG_CONTINUE) {
- red_printf("invalid response to REDS_MIG_DIFF_VERSION");
- mig->notifier_done(mig, reds->mig_notifier);
- return;
- }
- } else {
- resault = REDS_MIG_CONTINUE;
- reds_mig_write_all(fd, &resault, sizeof(resault), "resault");
- }
-
- reds_mig_send_cert_public_key(fd);
-
- ticketing_info.bn = BN_new();
- if (!ticketing_info.bn) {
- red_error("OpenSSL BIGNUMS alloc failed");
- }
-
- BN_set_word(ticketing_info.bn, f4);
- if (!(ticketing_info.rsa = RSA_new())) {
- red_error("OpenSSL RSA alloc failed");
- }
-
- RSA_generate_key_ex(ticketing_info.rsa, SPICE_TICKET_KEY_PAIR_LENGTH, ticketing_info.bn, NULL);
- ticketing_info.rsa_size = RSA_size(ticketing_info.rsa);
-
- if (!(bio = BIO_new(BIO_s_mem()))) {
- red_error("OpenSSL BIO alloc failed");
- }
-
- i2d_RSA_PUBKEY_bio(bio, ticketing_info.rsa);
- BIO_get_mem_ptr(bio, &buff);
-
- reds_mig_write_all(fd, buff->data, SPICE_TICKET_PUBKEY_BYTES, "publick key");
- reds_mig_read_all(fd, ticketing_info.encrypted_ticket.encrypted_data, ticketing_info.rsa_size,
- "ticket");
-
- RSA_private_decrypt(ticketing_info.rsa_size, ticketing_info.encrypted_ticket.encrypted_data,
- (unsigned char *)password, ticketing_info.rsa, RSA_PKCS1_OAEP_PADDING);
-
- BN_free(ticketing_info.bn);
- BIO_free(bio);
- RSA_free(ticketing_info.rsa);
-
- memcpy(reds->taTicket.password, password, sizeof(reds->taTicket.password));
- reds_mig_read_all(fd, &mig_message, sizeof(mig_message), "mig data");
- reds->link_id = mig_message.link_id;
- reds_mig_write_all(fd, &ack_message, sizeof(uint32_t), "ack");
- mig->notifier_done(mig, reds->mig_notifier);
-}
-
static void migrate_timout(void *opaque)
{
red_printf("");
@@ -4096,9 +3471,10 @@ __visible__ int spice_server_add_interface(SpiceServer *s,
return -1;
}
mig = (MigrationInterface *)interface;
- reds->mig_notifier = mig->register_notifiers(mig, MIGRATION_NOTIFY_SPICE_KEY,
- reds_mig_started, reds_mig_finished,
- reds_mig_recv, NULL);
+ reds->mig_notifier = mig->register_notifiers(mig,
+ reds_mig_started,
+ reds_mig_finished,
+ NULL);
if (reds->mig_notifier == INVALID_VD_OBJECT_REF) {
red_error("migration register failed");
}
diff --git a/server/vd_interface.h b/server/vd_interface.h
index d3cf5cb..7c7c202 100644
--- a/server/vd_interface.h
+++ b/server/vd_interface.h
@@ -268,21 +268,18 @@ struct SpiceTabletInstance {
#define VD_INTERFACE_MIGRATION_MAJOR 1
#define VD_INTERFACE_MIGRATION_MINOR 1
typedef struct MigrationInterface MigrationInterface;
-typedef void (*migration_notify_started_t)(void *opaque, const char *args);
+typedef void (*migration_notify_started_t)(void *opaque);
typedef void (*migration_notify_finished_t)(void *opaque, int completed);
-typedef void (*migration_notify_recv_t)(void *opaque, int fd);
struct MigrationInterface {
SpiceBaseInterface base;
- VDObjectRef (*register_notifiers)(MigrationInterface* mig, const char *key,
+ VDObjectRef (*register_notifiers)(MigrationInterface* mig,
migration_notify_started_t,
migration_notify_finished_t,
- migration_notify_recv_t,
void *opaque);
void (*unregister_notifiers)(MigrationInterface* mig, VDObjectRef notifier);
void (*notifier_done)(MigrationInterface *mig, VDObjectRef notifier);
- int (*begin_hook)(MigrationInterface *mig, VDObjectRef notifier);
};
enum VDIArgType{
--
1.6.6.1
More information about the Spice-devel
mailing list