-
Notifications
You must be signed in to change notification settings - Fork 32
/
target_bus_assignment.ml
122 lines (110 loc) · 4.36 KB
/
target_bus_assignment.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
(* virt-v2v
* Copyright (C) 2009-2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
open Std_utils
open Tools_utils
open Common_gettext.Gettext
open Types
let rec target_bus_assignment source_disks source_removables guestcaps =
let virtio_blk_bus = ref [| |]
and ide_bus = ref [| |]
and scsi_bus = ref [| |]
and floppy_bus = ref [| |] in
(* Assign the fixed disks (source_disks) to either the virtio-blk or
* IDE bus, depending on whether the guest has virtio drivers or not.
*)
let () =
let bus =
match guestcaps.gcaps_block_bus with
| Virtio_blk -> virtio_blk_bus
| IDE -> ide_bus in
List.iteri (
fun i d ->
let d = BusSlotDisk d in
insert bus i d
) source_disks in
(* Now we have to assign the removable disks. These go in the
* same slot they originally occupied, except in two cases: (1) That
* slot is now occupied by a target disk, or (2) we don't
* have information about the original slot. In these cases
* insert the disk in the next empty slot in that bus.
*)
(* Split the removables into a list of devices that desire a
* particular slot, and those that don't care. Assign the first
* group first so they have a greater chance of getting the
* desired slot.
*)
let removables_desire, removables_no_desire =
List.partition (
function
| { s_removable_slot = Some _ } -> true
| { s_removable_slot = None } -> false
) source_removables in
let assign_removables removables =
List.iter (
fun r ->
let t = BusSlotRemovable r in
let bus =
match r.s_removable_type with
| Floppy -> floppy_bus
| CDROM ->
match r.s_removable_controller with
| None -> ide_bus (* Wild guess, but should be safe. *)
| Some Source_virtio_blk -> virtio_blk_bus
| Some Source_IDE -> ide_bus
| Some (Source_virtio_SCSI | Source_SCSI | Source_SATA) ->
scsi_bus in
match r.s_removable_slot with
| None ->
ignore (insert_after bus 0 t)
| Some desired_slot_nr ->
if not (insert_after bus desired_slot_nr t) then
warning (f_"removable %s device in slot %d clashes with another disk, so it has been moved to a higher numbered slot on the same bus. This may mean that this removable device has a different name inside the guest (for example a CD-ROM originally called /dev/hdc might move to /dev/hdd, or from D: to E: on a Windows guest).")
(match r.s_removable_type with
| CDROM -> s_"CD-ROM"
| Floppy -> s_"floppy disk")
desired_slot_nr
) removables
in
assign_removables removables_desire;
assign_removables removables_no_desire;
{ target_virtio_blk_bus = !virtio_blk_bus;
target_ide_bus = !ide_bus;
target_scsi_bus = !scsi_bus;
target_floppy_bus = !floppy_bus }
(* Insert a slot into the bus array, making the array bigger if necessary. *)
and insert bus i slot =
let oldbus = !bus in
let oldlen = Array.length oldbus in
if i >= oldlen then (
bus := Array.make (i+1) BusSlotEmpty;
Array.blit oldbus 0 !bus 0 oldlen
);
assert (!bus.(i) = BusSlotEmpty);
!bus.(i) <- slot
(* Insert a slot into the bus, but if the desired slot is not empty, then
* increment the slot number until we find an empty one. Returns
* true if we got the desired slot.
*)
and insert_after bus i slot =
if slot_is_empty bus i then (
insert bus i slot; true
) else (
ignore (insert_after bus (i+1) slot); false
)
(* Return true if slot i is empty in the bus. *)
and slot_is_empty bus i = i >= Array.length !bus || !bus.(i) = BusSlotEmpty