]>
Commit | Line | Data |
---|---|---|
2a9e2e59 SS |
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" | |
385f510d SS |
9 | #include "qemu/cutils.h" |
10 | #include "qapi/error.h" | |
2a9e2e59 SS |
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 | ||
385f510d SS |
18 | #define OFFSET_OPTION ",offset=" |
19 | ||
20 | /* Remove the offset option from @filespec and return it in @offsetp. */ | |
21 | ||
72a8192e | 22 | int file_parse_offset(char *filespec, uint64_t *offsetp, Error **errp) |
385f510d SS |
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 | ||
02afba63 FR |
39 | void file_start_outgoing_migration(MigrationState *s, |
40 | FileMigrationArgs *file_args, Error **errp) | |
2a9e2e59 SS |
41 | { |
42 | g_autoptr(QIOChannelFile) fioc = NULL; | |
02afba63 FR |
43 | g_autofree char *filename = g_strdup(file_args->filename); |
44 | uint64_t offset = file_args->offset; | |
2a9e2e59 SS |
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); | |
385f510d SS |
56 | if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) { |
57 | return; | |
58 | } | |
2a9e2e59 SS |
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 | ||
02afba63 | 72 | void file_start_incoming_migration(FileMigrationArgs *file_args, Error **errp) |
2a9e2e59 | 73 | { |
02afba63 | 74 | g_autofree char *filename = g_strdup(file_args->filename); |
2a9e2e59 | 75 | QIOChannelFile *fioc = NULL; |
02afba63 | 76 | uint64_t offset = file_args->offset; |
2a9e2e59 SS |
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); | |
385f510d SS |
87 | if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) { |
88 | return; | |
89 | } | |
2a9e2e59 SS |
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 | } |