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
10 #include "qemu/osdep.h"
11 #include "block/block_int-common.h"
12 #include "sysemu/blockdev.h"
13 #include "sysemu/block-backend.h"
14 #include "hw/block/block.h"
15 #include "qapi/error.h"
16 #include "qapi/qapi-types-block.h"
17
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 */
blk_pread_nonzeroes(BlockBackend * blk,hwaddr size,void * buf)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_BYTES);
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)) {
42 ret = blk_pread(blk, offset, bytes, (uint8_t *) buf + offset, 0);
43 if (ret < 0) {
44 return ret;
45 }
46 }
47 offset += bytes;
48 }
49 }
50
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 *
58 * This function not intended for actual block devices, which read on
59 * demand. It's for things like memory devices that (ab)use a block
60 * backend to provide persistence.
61 */
blk_check_size_and_read_all(BlockBackend * blk,DeviceState * dev,void * buf,hwaddr size,Error ** errp)62 bool blk_check_size_and_read_all(BlockBackend *blk, DeviceState *dev,
63 void *buf, hwaddr size, Error **errp)
64 {
65 int64_t blk_len;
66 int ret;
67 g_autofree char *dev_id = NULL;
68
69 blk_len = blk_getlength(blk);
70 if (blk_len < 0) {
71 error_setg_errno(errp, -blk_len,
72 "can't get size of %s block backend", blk_name(blk));
73 return false;
74 }
75 if (blk_len != size) {
76 dev_id = qdev_get_human_name(dev);
77 error_setg(errp, "%s device '%s' requires %" HWADDR_PRIu
78 " bytes, %s block backend provides %" PRIu64 " bytes",
79 object_get_typename(OBJECT(dev)), dev_id, size,
80 blk_name(blk), blk_len);
81 return false;
82 }
83
84 /*
85 * We could loop for @size > BDRV_REQUEST_MAX_BYTES, but if we
86 * ever get to the point we want to read *gigabytes* here, we
87 * should probably rework the device to be more like an actual
88 * block device and read only on demand.
89 */
90 assert(size <= BDRV_REQUEST_MAX_BYTES);
91 ret = blk_pread_nonzeroes(blk, size, buf);
92 if (ret < 0) {
93 dev_id = qdev_get_human_name(dev);
94 error_setg_errno(errp, -ret, "can't read %s block backend"
95 " for %s device '%s'",
96 blk_name(blk), object_get_typename(OBJECT(dev)),
97 dev_id);
98 return false;
99 }
100 return true;
101 }
102
blkconf_blocksizes(BlockConf * conf,Error ** errp)103 bool blkconf_blocksizes(BlockConf *conf, Error **errp)
104 {
105 BlockBackend *blk = conf->blk;
106 BlockSizes blocksizes;
107 BlockDriverState *bs;
108 bool use_blocksizes;
109 bool use_bs;
110
111 switch (conf->backend_defaults) {
112 case ON_OFF_AUTO_AUTO:
113 use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes);
114 use_bs = false;
115 break;
116
117 case ON_OFF_AUTO_ON:
118 use_blocksizes = !blk_probe_blocksizes(blk, &blocksizes);
119 bs = blk_bs(blk);
120 use_bs = bs;
121 break;
122
123 case ON_OFF_AUTO_OFF:
124 use_blocksizes = false;
125 use_bs = false;
126 break;
127
128 default:
129 abort();
130 }
131
132 /* fill in detected values if they are not defined via qemu command line */
133 if (!conf->physical_block_size) {
134 if (use_blocksizes) {
135 conf->physical_block_size = blocksizes.phys;
136 } else {
137 conf->physical_block_size = BDRV_SECTOR_SIZE;
138 }
139 }
140 if (!conf->logical_block_size) {
141 if (use_blocksizes) {
142 conf->logical_block_size = blocksizes.log;
143 } else {
144 conf->logical_block_size = BDRV_SECTOR_SIZE;
145 }
146 }
147 if (use_bs) {
148 if (!conf->opt_io_size) {
149 conf->opt_io_size = bs->bl.opt_transfer;
150 }
151 if (conf->discard_granularity == -1) {
152 if (bs->bl.pdiscard_alignment) {
153 conf->discard_granularity = bs->bl.pdiscard_alignment;
154 } else if (bs->bl.request_alignment != 1) {
155 conf->discard_granularity = bs->bl.request_alignment;
156 }
157 }
158 }
159
160 if (conf->logical_block_size > conf->physical_block_size) {
161 error_setg(errp,
162 "logical_block_size > physical_block_size not supported");
163 return false;
164 }
165
166 if (!QEMU_IS_ALIGNED(conf->min_io_size, conf->logical_block_size)) {
167 error_setg(errp,
168 "min_io_size must be a multiple of logical_block_size");
169 return false;
170 }
171
172 /*
173 * all devices which support min_io_size (scsi and virtio-blk) expose it to
174 * the guest as a uint16_t in units of logical blocks
175 */
176 if (conf->min_io_size / conf->logical_block_size > UINT16_MAX) {
177 error_setg(errp, "min_io_size must not exceed %u logical blocks",
178 UINT16_MAX);
179 return false;
180 }
181
182 if (!QEMU_IS_ALIGNED(conf->opt_io_size, conf->logical_block_size)) {
183 error_setg(errp,
184 "opt_io_size must be a multiple of logical_block_size");
185 return false;
186 }
187
188 if (conf->discard_granularity != -1 &&
189 !QEMU_IS_ALIGNED(conf->discard_granularity,
190 conf->logical_block_size)) {
191 error_setg(errp, "discard_granularity must be "
192 "a multiple of logical_block_size");
193 return false;
194 }
195
196 return true;
197 }
198
blkconf_apply_backend_options(BlockConf * conf,bool readonly,bool resizable,Error ** errp)199 bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
200 bool resizable, Error **errp)
201 {
202 BlockBackend *blk = conf->blk;
203 BlockdevOnError rerror, werror;
204 uint64_t perm, shared_perm;
205 bool wce;
206 int ret;
207
208 perm = BLK_PERM_CONSISTENT_READ;
209 if (!readonly) {
210 perm |= BLK_PERM_WRITE;
211 }
212
213 shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
214 if (resizable) {
215 shared_perm |= BLK_PERM_RESIZE;
216 }
217 if (conf->share_rw) {
218 shared_perm |= BLK_PERM_WRITE;
219 }
220
221 ret = blk_set_perm(blk, perm, shared_perm, errp);
222 if (ret < 0) {
223 return false;
224 }
225
226 switch (conf->wce) {
227 case ON_OFF_AUTO_ON: wce = true; break;
228 case ON_OFF_AUTO_OFF: wce = false; break;
229 case ON_OFF_AUTO_AUTO: wce = blk_enable_write_cache(blk); break;
230 default:
231 abort();
232 }
233
234 rerror = conf->rerror;
235 if (rerror == BLOCKDEV_ON_ERROR_AUTO) {
236 rerror = blk_get_on_error(blk, true);
237 }
238
239 werror = conf->werror;
240 if (werror == BLOCKDEV_ON_ERROR_AUTO) {
241 werror = blk_get_on_error(blk, false);
242 }
243
244 blk_set_enable_write_cache(blk, wce);
245 blk_set_on_error(blk, rerror, werror);
246
247 block_acct_setup(blk_get_stats(blk), conf->account_invalid,
248 conf->account_failed);
249 return true;
250 }
251
blkconf_geometry(BlockConf * conf,int * ptrans,unsigned cyls_max,unsigned heads_max,unsigned secs_max,Error ** errp)252 bool blkconf_geometry(BlockConf *conf, int *ptrans,
253 unsigned cyls_max, unsigned heads_max, unsigned secs_max,
254 Error **errp)
255 {
256 if (!conf->cyls && !conf->heads && !conf->secs) {
257 hd_geometry_guess(conf->blk,
258 &conf->cyls, &conf->heads, &conf->secs,
259 ptrans);
260 } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) {
261 *ptrans = hd_bios_chs_auto_trans(conf->cyls, conf->heads, conf->secs);
262 }
263 if (conf->cyls || conf->heads || conf->secs) {
264 if (conf->cyls < 1 || conf->cyls > cyls_max) {
265 error_setg(errp, "cyls must be between 1 and %u", cyls_max);
266 return false;
267 }
268 if (conf->heads < 1 || conf->heads > heads_max) {
269 error_setg(errp, "heads must be between 1 and %u", heads_max);
270 return false;
271 }
272 if (conf->secs < 1 || conf->secs > secs_max) {
273 error_setg(errp, "secs must be between 1 and %u", secs_max);
274 return false;
275 }
276 }
277 return true;
278 }
279