]>
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" |
e2c1c34f | 11 | #include "block/block_int-common.h" |
9c17d615 | 12 | #include "sysemu/blockdev.h" |
4be74634 | 13 | #include "sysemu/block-backend.h" |
0d09e41a | 14 | #include "hw/block/block.h" |
da34e65c | 15 | #include "qapi/error.h" |
9af23989 | 16 | #include "qapi/qapi-types-block.h" |
06f15217 | 17 | |
a4b15a8b XZ |
18 | /* |
19 | * Read the non-zeroes parts of @blk into @buf | |
20 | * Reading all of the @blk is expensive if the zeroes parts of @blk | |
21 | * is large enough. Therefore check the block status and only write | |
22 | * the non-zeroes block into @buf. | |
23 | * | |
24 | * Return 0 on success, non-zero on error. | |
25 | */ | |
26 | static int blk_pread_nonzeroes(BlockBackend *blk, hwaddr size, void *buf) | |
27 | { | |
28 | int ret; | |
29 | int64_t bytes, offset = 0; | |
30 | BlockDriverState *bs = blk_bs(blk); | |
31 | ||
32 | for (;;) { | |
33 | bytes = MIN(size - offset, BDRV_REQUEST_MAX_SECTORS); | |
34 | if (bytes <= 0) { | |
35 | return 0; | |
36 | } | |
37 | ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL); | |
38 | if (ret < 0) { | |
39 | return ret; | |
40 | } | |
41 | if (!(ret & BDRV_BLOCK_ZERO)) { | |
3c6f3f65 | 42 | ret = blk_pread(blk, offset, bytes, (uint8_t *) buf + offset, 0); |
a4b15a8b XZ |
43 | if (ret < 0) { |
44 | return ret; | |
45 | } | |
46 | } | |
47 | offset += bytes; | |
48 | } | |
49 | } | |
50 | ||
06f15217 MA |
51 | /* |
52 | * Read the entire contents of @blk into @buf. | |
53 | * @blk's contents must be @size bytes, and @size must be at most | |
54 | * BDRV_REQUEST_MAX_BYTES. | |
55 | * On success, return true. | |
56 | * On failure, store an error through @errp and return false. | |
57 | * Note that the error messages do not identify the block backend. | |
58 | * TODO Since callers don't either, this can result in confusing | |
59 | * errors. | |
60 | * This function not intended for actual block devices, which read on | |
61 | * demand. It's for things like memory devices that (ab)use a block | |
62 | * backend to provide persistence. | |
63 | */ | |
64 | bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size, | |
65 | Error **errp) | |
66 | { | |
67 | int64_t blk_len; | |
68 | int ret; | |
69 | ||
70 | blk_len = blk_getlength(blk); | |
71 | if (blk_len < 0) { | |
72 | error_setg_errno(errp, -blk_len, | |
73 | "can't get size of block backend"); | |
74 | return false; | |
75 | } | |
76 | if (blk_len != size) { | |
77 | error_setg(errp, "device requires %" HWADDR_PRIu " bytes, " | |
78 | "block backend provides %" PRIu64 " bytes", | |
79 | size, blk_len); | |
80 | return false; | |
81 | } | |
82 | ||
83 | /* | |
84 | * We could loop for @size > BDRV_REQUEST_MAX_BYTES, but if we | |
85 | * ever get to the point we want to read *gigabytes* here, we | |
86 | * should probably rework the device to be more like an actual | |
87 | * block device and read only on demand. | |
88 | */ | |
89 | assert(size <= BDRV_REQUEST_MAX_BYTES); | |
a4b15a8b | 90 | ret = blk_pread_nonzeroes(blk, size, buf); |
06f15217 MA |
91 | if (ret < 0) { |
92 | error_setg_errno(errp, -ret, "can't read block backend"); | |
93 | return false; | |
94 | } | |
95 | return true; | |
96 | } | |
911525db | 97 | |
c56ee92f | 98 | bool blkconf_blocksizes(BlockConf *conf, Error **errp) |
0eb28a42 ET |
99 | { |
100 | BlockBackend *blk = conf->blk; | |
101 | BlockSizes blocksizes; | |
12a521b5 AO |
102 | BlockDriverState *bs; |
103 | bool use_blocksizes; | |
104 | bool use_bs; | |
105 | ||
106 | switch (conf->backend_defaults) { | |
107 | case ON_OFF_AUTO_AUTO: | |
108 | use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes); | |
109 | use_bs = false; | |
110 | break; | |
111 | ||
112 | case ON_OFF_AUTO_ON: | |
113 | use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes); | |
114 | bs = blk_bs(blk); | |
115 | use_bs = bs; | |
116 | break; | |
117 | ||
118 | case ON_OFF_AUTO_OFF: | |
119 | use_blocksizes = false; | |
120 | use_bs = false; | |
121 | break; | |
122 | ||
123 | default: | |
124 | abort(); | |
125 | } | |
0eb28a42 | 126 | |
0eb28a42 ET |
127 | /* fill in detected values if they are not defined via qemu command line */ |
128 | if (!conf->physical_block_size) { | |
12a521b5 | 129 | if (use_blocksizes) { |
0eb28a42 ET |
130 | conf->physical_block_size = blocksizes.phys; |
131 | } else { | |
132 | conf->physical_block_size = BDRV_SECTOR_SIZE; | |
133 | } | |
134 | } | |
135 | if (!conf->logical_block_size) { | |
12a521b5 | 136 | if (use_blocksizes) { |
0eb28a42 ET |
137 | conf->logical_block_size = blocksizes.log; |
138 | } else { | |
139 | conf->logical_block_size = BDRV_SECTOR_SIZE; | |
140 | } | |
141 | } | |
12a521b5 AO |
142 | if (use_bs) { |
143 | if (!conf->opt_io_size) { | |
144 | conf->opt_io_size = bs->bl.opt_transfer; | |
145 | } | |
146 | if (conf->discard_granularity == -1) { | |
147 | if (bs->bl.pdiscard_alignment) { | |
148 | conf->discard_granularity = bs->bl.pdiscard_alignment; | |
149 | } else if (bs->bl.request_alignment != 1) { | |
150 | conf->discard_granularity = bs->bl.request_alignment; | |
151 | } | |
152 | } | |
153 | } | |
c56ee92f RK |
154 | |
155 | if (conf->logical_block_size > conf->physical_block_size) { | |
156 | error_setg(errp, | |
157 | "logical_block_size > physical_block_size not supported"); | |
158 | return false; | |
159 | } | |
160 | ||
161 | if (!QEMU_IS_ALIGNED(conf->min_io_size, conf->logical_block_size)) { | |
162 | error_setg(errp, | |
163 | "min_io_size must be a multiple of logical_block_size"); | |
164 | return false; | |
165 | } | |
166 | ||
4f44bbc5 RK |
167 | /* |
168 | * all devices which support min_io_size (scsi and virtio-blk) expose it to | |
169 | * the guest as a uint16_t in units of logical blocks | |
170 | */ | |
171 | if (conf->min_io_size / conf->logical_block_size > UINT16_MAX) { | |
172 | error_setg(errp, "min_io_size must not exceed %u logical blocks", | |
173 | UINT16_MAX); | |
174 | return false; | |
175 | } | |
176 | ||
c56ee92f RK |
177 | if (!QEMU_IS_ALIGNED(conf->opt_io_size, conf->logical_block_size)) { |
178 | error_setg(errp, | |
179 | "opt_io_size must be a multiple of logical_block_size"); | |
180 | return false; | |
181 | } | |
182 | ||
183 | if (conf->discard_granularity != -1 && | |
184 | !QEMU_IS_ALIGNED(conf->discard_granularity, | |
185 | conf->logical_block_size)) { | |
186 | error_setg(errp, "discard_granularity must be " | |
187 | "a multiple of logical_block_size"); | |
188 | return false; | |
189 | } | |
190 | ||
191 | return true; | |
0eb28a42 ET |
192 | } |
193 | ||
9d3b1551 | 194 | bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, |
a17c17a2 | 195 | bool resizable, Error **errp) |
f6166a06 KW |
196 | { |
197 | BlockBackend *blk = conf->blk; | |
8c398252 | 198 | BlockdevOnError rerror, werror; |
a17c17a2 | 199 | uint64_t perm, shared_perm; |
f6166a06 | 200 | bool wce; |
a17c17a2 KW |
201 | int ret; |
202 | ||
203 | perm = BLK_PERM_CONSISTENT_READ; | |
204 | if (!readonly) { | |
205 | perm |= BLK_PERM_WRITE; | |
206 | } | |
207 | ||
64631f36 | 208 | shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED; |
a17c17a2 KW |
209 | if (resizable) { |
210 | shared_perm |= BLK_PERM_RESIZE; | |
211 | } | |
dabd18f6 KW |
212 | if (conf->share_rw) { |
213 | shared_perm |= BLK_PERM_WRITE; | |
214 | } | |
a17c17a2 KW |
215 | |
216 | ret = blk_set_perm(blk, perm, shared_perm, errp); | |
217 | if (ret < 0) { | |
9d3b1551 | 218 | return false; |
a17c17a2 | 219 | } |
f6166a06 KW |
220 | |
221 | switch (conf->wce) { | |
222 | case ON_OFF_AUTO_ON: wce = true; break; | |
223 | case ON_OFF_AUTO_OFF: wce = false; break; | |
224 | case ON_OFF_AUTO_AUTO: wce = blk_enable_write_cache(blk); break; | |
225 | default: | |
226 | abort(); | |
227 | } | |
228 | ||
8c398252 KW |
229 | rerror = conf->rerror; |
230 | if (rerror == BLOCKDEV_ON_ERROR_AUTO) { | |
231 | rerror = blk_get_on_error(blk, true); | |
232 | } | |
233 | ||
234 | werror = conf->werror; | |
235 | if (werror == BLOCKDEV_ON_ERROR_AUTO) { | |
236 | werror = blk_get_on_error(blk, false); | |
237 | } | |
238 | ||
f6166a06 | 239 | blk_set_enable_write_cache(blk, wce); |
8c398252 | 240 | blk_set_on_error(blk, rerror, werror); |
9d3b1551 | 241 | |
62a6c300 DL |
242 | block_acct_setup(blk_get_stats(blk), conf->account_invalid, |
243 | conf->account_failed); | |
9d3b1551 | 244 | return true; |
f6166a06 KW |
245 | } |
246 | ||
9d3b1551 | 247 | bool blkconf_geometry(BlockConf *conf, int *ptrans, |
5ff5efb4 FZ |
248 | unsigned cyls_max, unsigned heads_max, unsigned secs_max, |
249 | Error **errp) | |
b7eb0c9f | 250 | { |
b7eb0c9f | 251 | if (!conf->cyls && !conf->heads && !conf->secs) { |
4be74634 | 252 | hd_geometry_guess(conf->blk, |
b7eb0c9f MA |
253 | &conf->cyls, &conf->heads, &conf->secs, |
254 | ptrans); | |
255 | } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) { | |
256 | *ptrans = hd_bios_chs_auto_trans(conf->cyls, conf->heads, conf->secs); | |
257 | } | |
258 | if (conf->cyls || conf->heads || conf->secs) { | |
259 | if (conf->cyls < 1 || conf->cyls > cyls_max) { | |
5ff5efb4 | 260 | error_setg(errp, "cyls must be between 1 and %u", cyls_max); |
9d3b1551 | 261 | return false; |
b7eb0c9f MA |
262 | } |
263 | if (conf->heads < 1 || conf->heads > heads_max) { | |
5ff5efb4 | 264 | error_setg(errp, "heads must be between 1 and %u", heads_max); |
9d3b1551 | 265 | return false; |
b7eb0c9f MA |
266 | } |
267 | if (conf->secs < 1 || conf->secs > secs_max) { | |
5ff5efb4 | 268 | error_setg(errp, "secs must be between 1 and %u", secs_max); |
9d3b1551 | 269 | return false; |
b7eb0c9f MA |
270 | } |
271 | } | |
9d3b1551 | 272 | return true; |
b7eb0c9f | 273 | } |