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