]>
Commit | Line | Data |
---|---|---|
911525db MA |
1 | /* |
2 | * Common code for block device models | |
3 | * | |
4 | * Copyright (C) 2012 Red Hat, Inc. | |
5 | * | |
6 | * This work is licensed under the terms of the GNU GPL, version 2 or | |
7 | * later. See the COPYING file in the top-level directory. | |
8 | */ | |
9 | ||
80c71a24 | 10 | #include "qemu/osdep.h" |
9c17d615 | 11 | #include "sysemu/blockdev.h" |
4be74634 | 12 | #include "sysemu/block-backend.h" |
0d09e41a | 13 | #include "hw/block/block.h" |
da34e65c | 14 | #include "qapi/error.h" |
9af23989 | 15 | #include "qapi/qapi-types-block.h" |
1de7afc9 | 16 | #include "qemu/error-report.h" |
911525db MA |
17 | |
18 | void blkconf_serial(BlockConf *conf, char **serial) | |
19 | { | |
20 | DriveInfo *dinfo; | |
21 | ||
22 | if (!*serial) { | |
23 | /* try to fall back to value set with legacy -drive serial=... */ | |
4be74634 | 24 | dinfo = blk_legacy_dinfo(conf->blk); |
26f8b3a8 MA |
25 | if (dinfo) { |
26 | *serial = g_strdup(dinfo->serial); | |
27 | } | |
911525db MA |
28 | } |
29 | } | |
b7eb0c9f | 30 | |
0eb28a42 ET |
31 | void blkconf_blocksizes(BlockConf *conf) |
32 | { | |
33 | BlockBackend *blk = conf->blk; | |
34 | BlockSizes blocksizes; | |
35 | int backend_ret; | |
36 | ||
37 | backend_ret = blk_probe_blocksizes(blk, &blocksizes); | |
38 | /* fill in detected values if they are not defined via qemu command line */ | |
39 | if (!conf->physical_block_size) { | |
40 | if (!backend_ret) { | |
41 | conf->physical_block_size = blocksizes.phys; | |
42 | } else { | |
43 | conf->physical_block_size = BDRV_SECTOR_SIZE; | |
44 | } | |
45 | } | |
46 | if (!conf->logical_block_size) { | |
47 | if (!backend_ret) { | |
48 | conf->logical_block_size = blocksizes.log; | |
49 | } else { | |
50 | conf->logical_block_size = BDRV_SECTOR_SIZE; | |
51 | } | |
52 | } | |
53 | } | |
54 | ||
9d3b1551 | 55 | bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, |
a17c17a2 | 56 | bool resizable, Error **errp) |
f6166a06 KW |
57 | { |
58 | BlockBackend *blk = conf->blk; | |
8c398252 | 59 | BlockdevOnError rerror, werror; |
a17c17a2 | 60 | uint64_t perm, shared_perm; |
f6166a06 | 61 | bool wce; |
a17c17a2 KW |
62 | int ret; |
63 | ||
64 | perm = BLK_PERM_CONSISTENT_READ; | |
65 | if (!readonly) { | |
66 | perm |= BLK_PERM_WRITE; | |
67 | } | |
68 | ||
a17c17a2 | 69 | shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | |
dabd18f6 | 70 | BLK_PERM_GRAPH_MOD; |
a17c17a2 KW |
71 | if (resizable) { |
72 | shared_perm |= BLK_PERM_RESIZE; | |
73 | } | |
dabd18f6 KW |
74 | if (conf->share_rw) { |
75 | shared_perm |= BLK_PERM_WRITE; | |
76 | } | |
a17c17a2 KW |
77 | |
78 | ret = blk_set_perm(blk, perm, shared_perm, errp); | |
79 | if (ret < 0) { | |
9d3b1551 | 80 | return false; |
a17c17a2 | 81 | } |
f6166a06 KW |
82 | |
83 | switch (conf->wce) { | |
84 | case ON_OFF_AUTO_ON: wce = true; break; | |
85 | case ON_OFF_AUTO_OFF: wce = false; break; | |
86 | case ON_OFF_AUTO_AUTO: wce = blk_enable_write_cache(blk); break; | |
87 | default: | |
88 | abort(); | |
89 | } | |
90 | ||
8c398252 KW |
91 | rerror = conf->rerror; |
92 | if (rerror == BLOCKDEV_ON_ERROR_AUTO) { | |
93 | rerror = blk_get_on_error(blk, true); | |
94 | } | |
95 | ||
96 | werror = conf->werror; | |
97 | if (werror == BLOCKDEV_ON_ERROR_AUTO) { | |
98 | werror = blk_get_on_error(blk, false); | |
99 | } | |
100 | ||
f6166a06 | 101 | blk_set_enable_write_cache(blk, wce); |
8c398252 | 102 | blk_set_on_error(blk, rerror, werror); |
9d3b1551 MZ |
103 | |
104 | return true; | |
f6166a06 KW |
105 | } |
106 | ||
9d3b1551 | 107 | bool blkconf_geometry(BlockConf *conf, int *ptrans, |
5ff5efb4 FZ |
108 | unsigned cyls_max, unsigned heads_max, unsigned secs_max, |
109 | Error **errp) | |
b7eb0c9f MA |
110 | { |
111 | DriveInfo *dinfo; | |
112 | ||
113 | if (!conf->cyls && !conf->heads && !conf->secs) { | |
114 | /* try to fall back to value set with legacy -drive cyls=... */ | |
4be74634 | 115 | dinfo = blk_legacy_dinfo(conf->blk); |
26f8b3a8 MA |
116 | if (dinfo) { |
117 | conf->cyls = dinfo->cyls; | |
118 | conf->heads = dinfo->heads; | |
119 | conf->secs = dinfo->secs; | |
120 | if (ptrans) { | |
121 | *ptrans = dinfo->trans; | |
122 | } | |
b7eb0c9f MA |
123 | } |
124 | } | |
125 | if (!conf->cyls && !conf->heads && !conf->secs) { | |
4be74634 | 126 | hd_geometry_guess(conf->blk, |
b7eb0c9f MA |
127 | &conf->cyls, &conf->heads, &conf->secs, |
128 | ptrans); | |
129 | } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) { | |
130 | *ptrans = hd_bios_chs_auto_trans(conf->cyls, conf->heads, conf->secs); | |
131 | } | |
132 | if (conf->cyls || conf->heads || conf->secs) { | |
133 | if (conf->cyls < 1 || conf->cyls > cyls_max) { | |
5ff5efb4 | 134 | error_setg(errp, "cyls must be between 1 and %u", cyls_max); |
9d3b1551 | 135 | return false; |
b7eb0c9f MA |
136 | } |
137 | if (conf->heads < 1 || conf->heads > heads_max) { | |
5ff5efb4 | 138 | error_setg(errp, "heads must be between 1 and %u", heads_max); |
9d3b1551 | 139 | return false; |
b7eb0c9f MA |
140 | } |
141 | if (conf->secs < 1 || conf->secs > secs_max) { | |
5ff5efb4 | 142 | error_setg(errp, "secs must be between 1 and %u", secs_max); |
9d3b1551 | 143 | return false; |
b7eb0c9f MA |
144 | } |
145 | } | |
9d3b1551 | 146 | return true; |
b7eb0c9f | 147 | } |