>From f765d3baaf10174e7942f15dd801975125bc3d34 Mon Sep 17 00:00:00 2001 From: Uri Lublin Date: Tue, 24 Feb 2009 07:12:18 +0200 Subject: [PATCH 2/2 FOR REVIEW] migration to file: use signal for async-write notification Instead of looping by io-handler called by writeable fd, do not register handler, and use signal SIGUSR1 for aio completion notifications. Signed-off-by: Uri Lublin --- migration-file.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 113 insertions(+), 11 deletions(-) diff --git a/migration-file.c b/migration-file.c index 6d3dbf5..02726fc 100644 --- a/migration-file.c +++ b/migration-file.c @@ -38,17 +38,19 @@ typedef struct FileMigrationState_s { off_t write_offset; struct qemu_paiocb aiocb; int aio_in_use; + int aio_rfd, aio_wfd; } FileMigrationState; +static FileMigrationState *fm = NULL; -static int file_errno(FdMigrationState *fds) -{ - return errno; -} -static void mig_file_check_aiocb(FileMigrationState *s) +/* returns 0 if done nothing + * returns >0 if an aio operation was completed + */ +static int mig_file_check_aiocb(FileMigrationState *s) { ssize_t ret; + int rc = 0; if (s->aio_in_use) { ret = qemu_paio_return(&s->aiocb); @@ -56,17 +58,102 @@ static void mig_file_check_aiocb(FileMigrationState *s) &s->aiocb, s->aiocb.aio_nbytes, ret); if (ret == -EINPROGRESS) - return; - if (ret == s->aiocb.aio_nbytes) { + ; /* do nothing --> return 0 */ + else if(ret == s->aiocb.aio_nbytes) { s->aio_in_use = 0; + rc = 1; } else { - dprintf("posix aio write failed, returned %ld expected %ld\n", + fprintf(stderr, "posix aio write failed, returned %ld expected %ld\n", ret, s->aiocb.aio_nbytes); if (s->fds.state == MIG_STATE_ACTIVE) s->fds.state = MIG_STATE_ERROR; } } + return rc; +} + +static void mig_file_aio_read(void *opaque) +{ + FileMigrationState *s = (FileMigrationState *)opaque; + ssize_t len; + + dprintf("mig_file_aio_read: IN\n"); + /* read all bytes from signal pipe */ + for (;;) { + char bytes[16]; + + len = read(s->aio_rfd, bytes, sizeof(bytes)); + if (len == -1 && errno == EINTR) + continue; /* try again */ + if (len == sizeof(bytes)) + continue; /* more to read */ + break; + } + + if (mig_file_check_aiocb(s)) + migrate_fd_set_fd(&s->fds); +} + +static void mig_file_aio_signal_handler(int signum) +{ + if (fm) { + char byte = 0; + + write(fm->aio_wfd, &byte, sizeof(byte)); + } + + qemu_service_io(); +} + +static int mig_file_aio_init(FileMigrationState *s) +{ + struct sigaction act; + int fds[2]; + + sigfillset(&act.sa_mask); + act.sa_flags = 0; /* do not restart syscalls to interrupt select() */ + act.sa_handler = mig_file_aio_signal_handler; + sigaction(SIGUSR1, &act, NULL); + + if (pipe(fds) == -1) { + perror("file-migration: failed to create pipe\n"); + return -errno; + } + + s->aio_rfd = fds[0]; + s->aio_wfd = fds[1]; + + fcntl(s->aio_rfd, F_SETFL, O_NONBLOCK); + fcntl(s->aio_wfd, F_SETFL, O_NONBLOCK); + + qemu_set_fd_handler2(s->aio_rfd, NULL, mig_file_aio_read, NULL, s); + + return 0; +} + +static void mig_file_aio_cleanup(FileMigrationState *s) +{ + struct sigaction act; + + sigfillset(&act.sa_mask); + act.sa_flags = 0; /* do not restart syscalls to interrupt select() */ + act.sa_handler = SIG_DFL; + sigaction(SIGUSR1, &act, NULL); + + qemu_aio_set_fd_handler(s->aio_rfd, NULL, NULL, NULL, NULL); + close(s->aio_rfd); + close(s->aio_wfd); + s->aio_rfd = s->aio_wfd = -1; + + fm = NULL; +} + + + +static int file_errno(FdMigrationState *fds) +{ + return errno; } static struct qemu_paiocb* mig_file_get_aiocb(FileMigrationState *s) @@ -115,7 +202,7 @@ static int write_async(FileMigrationState *s, const void *buf, size_t size) paiocb->aio_fildes = s->fds.fd; paiocb->aio_nbytes = size; - paiocb->ev_signo = 0; /* No notification is needed */ + paiocb->ev_signo = SIGUSR1; paiocb->aio_offset = s->write_offset; s->write_offset += size; @@ -150,6 +237,11 @@ static int file_write(FdMigrationState *fds, const void * buf, size_t size) return offset; } +static int file_set_fd(FdMigrationState *s) +{ + return 0; +} + static int file_close(FdMigrationState *fds) { FileMigrationState *s = (FileMigrationState*)fds; @@ -162,6 +254,8 @@ static int file_close(FdMigrationState *fds) break; sleep(1); } + + mig_file_aio_cleanup(s); close(fds->fd); free_aio_buf(s); @@ -178,20 +272,25 @@ MigrationState *file_start_outgoing_migration(const char *filename, int fd; s = qemu_mallocz(sizeof(*s)); + fm = s; fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { perror("file_migration: failed to open filename"); term_printf("file_migration: failed to open filename %s\n", filename); - goto err; + goto err1; } + if (mig_file_aio_init(s) < 0) + goto err2; + fds = &s->fds; fds->fd = fd; fds->close = file_close; fds->get_error = file_errno; fds->write = file_write; + fds->set_fd = file_set_fd; fds->mig_state.cancel = migrate_fd_cancel; fds->mig_state.get_status = migrate_fd_get_status; fds->mig_state.release = migrate_fd_release; @@ -209,8 +308,11 @@ MigrationState *file_start_outgoing_migration(const char *filename, migrate_fd_connect(fds); return &fds->mig_state; -err: +err2: + close(fd); +err1: qemu_free(s); + fm = NULL; return NULL; } -- 1.6.0.6