1 /* 2 * Copyright (c) 2021-2023 Oracle and/or its affiliates. 3 * 4 * This work is licensed under the terms of the GNU GPL, version 2 or later. 5 * See the COPYING file in the top-level directory. 6 */ 7 8 #include "qemu/osdep.h" 9 #include "qemu/cutils.h" 10 #include "qapi/error.h" 11 #include "channel.h" 12 #include "file.h" 13 #include "migration.h" 14 #include "io/channel-file.h" 15 #include "io/channel-util.h" 16 #include "trace.h" 17 18 #define OFFSET_OPTION ",offset=" 19 20 /* Remove the offset option from @filespec and return it in @offsetp. */ 21 22 int file_parse_offset(char *filespec, uint64_t *offsetp, Error **errp) 23 { 24 char *option = strstr(filespec, OFFSET_OPTION); 25 int ret; 26 27 if (option) { 28 *option = 0; 29 option += sizeof(OFFSET_OPTION) - 1; 30 ret = qemu_strtosz(option, NULL, offsetp); 31 if (ret) { 32 error_setg_errno(errp, -ret, "file URI has bad offset %s", option); 33 return -1; 34 } 35 } 36 return 0; 37 } 38 39 void file_start_outgoing_migration(MigrationState *s, 40 FileMigrationArgs *file_args, Error **errp) 41 { 42 g_autoptr(QIOChannelFile) fioc = NULL; 43 g_autofree char *filename = g_strdup(file_args->filename); 44 uint64_t offset = file_args->offset; 45 QIOChannel *ioc; 46 47 trace_migration_file_outgoing(filename); 48 49 fioc = qio_channel_file_new_path(filename, O_CREAT | O_WRONLY | O_TRUNC, 50 0600, errp); 51 if (!fioc) { 52 return; 53 } 54 55 ioc = QIO_CHANNEL(fioc); 56 if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) { 57 return; 58 } 59 qio_channel_set_name(ioc, "migration-file-outgoing"); 60 migration_channel_connect(s, ioc, NULL, NULL); 61 } 62 63 static gboolean file_accept_incoming_migration(QIOChannel *ioc, 64 GIOCondition condition, 65 gpointer opaque) 66 { 67 migration_channel_process_incoming(ioc); 68 object_unref(OBJECT(ioc)); 69 return G_SOURCE_REMOVE; 70 } 71 72 void file_start_incoming_migration(FileMigrationArgs *file_args, Error **errp) 73 { 74 g_autofree char *filename = g_strdup(file_args->filename); 75 QIOChannelFile *fioc = NULL; 76 uint64_t offset = file_args->offset; 77 QIOChannel *ioc; 78 79 trace_migration_file_incoming(filename); 80 81 fioc = qio_channel_file_new_path(filename, O_RDONLY, 0, errp); 82 if (!fioc) { 83 return; 84 } 85 86 ioc = QIO_CHANNEL(fioc); 87 if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) { 88 return; 89 } 90 qio_channel_set_name(QIO_CHANNEL(ioc), "migration-file-incoming"); 91 qio_channel_add_watch_full(ioc, G_IO_IN, 92 file_accept_incoming_migration, 93 NULL, NULL, 94 g_main_context_get_thread_default()); 95 } 96