/* FIXME: should we send a different packet (arp/rarp/ping)? */
+ memset(buf, 0, 64);
memset(buf, 0xff, 6); /* h_dst */
memcpy(buf + 6, mac_addr, 6); /* h_src */
memcpy(buf + 12, &proto, 2); /* h_proto */
memcpy(buf + 14, &magic, 4); /* magic */
- return 18; /* len */
+ return 64; /* len */
}
-void qemu_announce_self(void)
+static void qemu_announce_self_once(void *opaque)
{
- int i, j, len;
+ int i, len;
VLANState *vlan;
VLANClientState *vc;
uint8_t buf[256];
+ static int count = SELF_ANNOUNCE_ROUNDS;
+ QEMUTimer *timer = *(QEMUTimer **)opaque;
for (i = 0; i < MAX_NICS; i++) {
if (!nd_table[i].used)
continue;
len = announce_self_create(buf, nd_table[i].macaddr);
vlan = nd_table[i].vlan;
- for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
- for (j=0; j < SELF_ANNOUNCE_ROUNDS; j++)
- vc->fd_read(vc->opaque, buf, len);
+ for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
+ vc->receive(vc, buf, len);
}
}
+ if (count--) {
+ qemu_mod_timer(timer, qemu_get_clock(rt_clock) + 100);
+ } else {
+ qemu_del_timer(timer);
+ qemu_free_timer(timer);
+ }
+}
+
+void qemu_announce_self(void)
+{
+ static QEMUTimer *timer;
+ timer = qemu_new_timer(rt_clock, qemu_announce_self_once, &timer);
+ qemu_announce_self_once(&timer);
}
/***********************************************************/
QEMUFileGetBufferFunc *get_buffer;
QEMUFileCloseFunc *close;
QEMUFileRateLimit *rate_limit;
+ QEMUFileSetRateLimit *set_rate_limit;
void *opaque;
int is_write;
ssize_t len;
do {
- len = recv(s->fd, buf, size, 0);
+ len = recv(s->fd, (void *)buf, size, 0);
} while (len == -1 && socket_error() == EINTR);
if (len == -1)
static int popen_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
{
QEMUFilePopen *s = opaque;
- return fread(buf, 1, size, s->popen_file);
+ FILE *fp = s->popen_file;
+ int bytes;
+
+ do {
+ clearerr(fp);
+ bytes = fread(buf, 1, size, fp);
+ } while ((bytes == 0) && ferror(fp) && (errno == EINTR));
+ return bytes;
}
static int popen_close(void *opaque)
s->popen_file = popen_file;
if(mode[0] == 'r') {
- s->file = qemu_fopen_ops(s, NULL, popen_get_buffer, popen_close, NULL);
+ s->file = qemu_fopen_ops(s, NULL, popen_get_buffer, popen_close, NULL, NULL);
} else {
- s->file = qemu_fopen_ops(s, popen_put_buffer, NULL, popen_close, NULL);
+ s->file = qemu_fopen_ops(s, popen_put_buffer, NULL, popen_close, NULL, NULL);
}
- fprintf(stderr, "qemu_popen: returning result of qemu_fopen_ops\n");
return s->file;
}
return qemu_popen(popen_file, mode);
}
+int qemu_popen_fd(QEMUFile *f)
+{
+ QEMUFilePopen *p;
+ int fd;
+
+ p = (QEMUFilePopen *)f->opaque;
+ fd = fileno(p->popen_file);
+
+ return fd;
+}
+
QEMUFile *qemu_fopen_socket(int fd)
{
QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket));
s->fd = fd;
- s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, socket_close, NULL);
+ s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, socket_close, NULL, NULL);
return s->file;
}
goto fail;
if (!strcmp(mode, "wb"))
- return qemu_fopen_ops(s, file_put_buffer, NULL, file_close, NULL);
+ return qemu_fopen_ops(s, file_put_buffer, NULL, file_close, NULL, NULL);
else if (!strcmp(mode, "rb"))
- return qemu_fopen_ops(s, NULL, file_get_buffer, file_close, NULL);
+ return qemu_fopen_ops(s, NULL, file_get_buffer, file_close, NULL, NULL);
fail:
if (s->outfile)
return NULL;
}
-typedef struct QEMUFileBdrv
-{
- BlockDriverState *bs;
- int64_t base_offset;
-} QEMUFileBdrv;
-
static int block_put_buffer(void *opaque, const uint8_t *buf,
int64_t pos, int size)
{
- QEMUFileBdrv *s = opaque;
- bdrv_put_buffer(s->bs, buf, s->base_offset + pos, size);
+ bdrv_save_vmstate(opaque, buf, pos, size);
return size;
}
static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
{
- QEMUFileBdrv *s = opaque;
- return bdrv_get_buffer(s->bs, buf, s->base_offset + pos, size);
+ return bdrv_load_vmstate(opaque, buf, pos, size);
}
static int bdrv_fclose(void *opaque)
{
- QEMUFileBdrv *s = opaque;
- qemu_free(s);
return 0;
}
-static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable)
+static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
{
- QEMUFileBdrv *s;
-
- s = qemu_mallocz(sizeof(QEMUFileBdrv));
-
- s->bs = bs;
- s->base_offset = offset;
-
if (is_writable)
- return qemu_fopen_ops(s, block_put_buffer, NULL, bdrv_fclose, NULL);
-
- return qemu_fopen_ops(s, NULL, block_get_buffer, bdrv_fclose, NULL);
+ return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose, NULL, NULL);
+ return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL);
}
QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
QEMUFileGetBufferFunc *get_buffer,
QEMUFileCloseFunc *close,
- QEMUFileRateLimit *rate_limit)
+ QEMUFileRateLimit *rate_limit,
+ QEMUFileSetRateLimit *set_rate_limit)
{
QEMUFile *f;
f->get_buffer = get_buffer;
f->close = close;
f->rate_limit = rate_limit;
+ f->set_rate_limit = set_rate_limit;
f->is_write = 0;
return f;
return 0;
}
+size_t qemu_file_set_rate_limit(QEMUFile *f, size_t new_rate)
+{
+ /* any failed or completed migration keeps its state to allow probing of
+ * migration data, but has no associated file anymore */
+ if (f && f->set_rate_limit)
+ return f->set_rate_limit(f->opaque, new_rate);
+
+ return 0;
+}
+
void qemu_put_be16(QEMUFile *f, unsigned int v)
{
qemu_put_byte(f, v >> 8);
NULL, save_state, load_state, opaque);
}
+void unregister_savevm(const char *idstr, void *opaque)
+{
+ SaveStateEntry **pse;
+
+ pse = &first_se;
+ while (*pse != NULL) {
+ if (strcmp((*pse)->idstr, idstr) == 0 && (*pse)->opaque == opaque) {
+ SaveStateEntry *next = (*pse)->next;
+ qemu_free(*pse);
+ *pse = next;
+ continue;
+ }
+ pse = &(*pse)->next;
+ }
+}
+
#define QEMU_VM_FILE_MAGIC 0x5145564d
#define QEMU_VM_FILE_VERSION_COMPAT 0x00000002
#define QEMU_VM_FILE_VERSION 0x00000003
if (ret < 0) {
fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
instance_id, idstr);
+ return ret;
}
}
/* always seek to exact end of record */
BlockDriverState *bs, *bs1;
QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
int must_delete, ret, i;
- BlockDriverInfo bdi1, *bdi = &bdi1;
QEMUFile *f;
int saved_vm_running;
uint32_t vm_state_size;
#endif
sn->vm_clock_nsec = qemu_get_clock(vm_clock);
- if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
- monitor_printf(mon, "Device %s does not support VM state snapshots\n",
- bdrv_get_device_name(bs));
- goto the_end;
- }
-
/* save the VM state */
- f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
+ f = qemu_fopen_bdrv(bs, 1);
if (!f) {
monitor_printf(mon, "Could not open VM state file\n");
goto the_end;
void do_loadvm(Monitor *mon, const char *name)
{
BlockDriverState *bs, *bs1;
- BlockDriverInfo bdi1, *bdi = &bdi1;
QEMUSnapshotInfo sn;
QEMUFile *f;
int i, ret;
}
}
- if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
- monitor_printf(mon, "Device %s does not support VM state snapshots\n",
- bdrv_get_device_name(bs));
- return;
- }
-
/* Don't even try to load empty VM states */
ret = bdrv_snapshot_find(bs, &sn, name);
if ((ret >= 0) && (sn.vm_state_size == 0))
goto the_end;
/* restore the VM state */
- f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
+ f = qemu_fopen_bdrv(bs, 0);
if (!f) {
monitor_printf(mon, "Could not open VM state file\n");
goto the_end;