2131 |
2131 |
}
|
2132 |
2132 |
|
2133 |
2133 |
/*
|
2134 |
|
* Process a synchronous request using coroutines
|
|
2134 |
* Process a vectored synchronous request using coroutines
|
2135 |
2135 |
*/
|
2136 |
|
static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
2137 |
|
int nb_sectors, bool is_write)
|
|
2136 |
static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num,
|
|
2137 |
QEMUIOVector *qiov, bool is_write)
|
2138 |
2138 |
{
|
2139 |
|
QEMUIOVector qiov;
|
2140 |
|
struct iovec iov = {
|
2141 |
|
.iov_base = (void *)buf,
|
2142 |
|
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
2143 |
|
};
|
2144 |
2139 |
Coroutine *co;
|
2145 |
2140 |
RwCo rwco = {
|
2146 |
2141 |
.bs = bs,
|
2147 |
2142 |
.sector_num = sector_num,
|
2148 |
|
.nb_sectors = nb_sectors,
|
2149 |
|
.qiov = &qiov,
|
|
2143 |
.nb_sectors = qiov->size >> BDRV_SECTOR_BITS,
|
|
2144 |
.qiov = qiov,
|
2150 |
2145 |
.is_write = is_write,
|
2151 |
2146 |
.ret = NOT_DONE,
|
2152 |
2147 |
};
|
2153 |
|
|
2154 |
|
qemu_iovec_init_external(&qiov, &iov, 1);
|
|
2148 |
assert((qiov->size & (BDRV_SECTOR_SIZE - 1)) == 0);
|
2155 |
2149 |
|
2156 |
2150 |
/**
|
2157 |
2151 |
* In sync call context, when the vcpu is blocked, this throttling timer
|
... | ... | |
2177 |
2171 |
return rwco.ret;
|
2178 |
2172 |
}
|
2179 |
2173 |
|
|
2174 |
/*
|
|
2175 |
* Process a synchronous request using coroutines
|
|
2176 |
*/
|
|
2177 |
static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf,
|
|
2178 |
int nb_sectors, bool is_write)
|
|
2179 |
{
|
|
2180 |
QEMUIOVector qiov;
|
|
2181 |
struct iovec iov = {
|
|
2182 |
.iov_base = (void *)buf,
|
|
2183 |
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
|
2184 |
};
|
|
2185 |
|
|
2186 |
qemu_iovec_init_external(&qiov, &iov, 1);
|
|
2187 |
return bdrv_rwv_co(bs, sector_num, &qiov, is_write);
|
|
2188 |
}
|
|
2189 |
|
2180 |
2190 |
/* return < 0 if error. See bdrv_write() for the return codes */
|
2181 |
2191 |
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
|
2182 |
2192 |
uint8_t *buf, int nb_sectors)
|
... | ... | |
2210 |
2220 |
return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true);
|
2211 |
2221 |
}
|
2212 |
2222 |
|
|
2223 |
int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov)
|
|
2224 |
{
|
|
2225 |
return bdrv_rwv_co(bs, sector_num, qiov, true);
|
|
2226 |
}
|
|
2227 |
|
2213 |
2228 |
int bdrv_pread(BlockDriverState *bs, int64_t offset,
|
2214 |
2229 |
void *buf, int count1)
|
2215 |
2230 |
{
|
... | ... | |
2255 |
2270 |
return count1;
|
2256 |
2271 |
}
|
2257 |
2272 |
|
2258 |
|
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
2259 |
|
const void *buf, int count1)
|
|
2273 |
int bdrv_pwritev(BlockDriverState *bs, int64_t offset, QEMUIOVector *qiov)
|
2260 |
2274 |
{
|
2261 |
2275 |
uint8_t tmp_buf[BDRV_SECTOR_SIZE];
|
2262 |
2276 |
int len, nb_sectors, count;
|
2263 |
2277 |
int64_t sector_num;
|
2264 |
2278 |
int ret;
|
2265 |
2279 |
|
2266 |
|
count = count1;
|
|
2280 |
count = qiov->size;
|
|
2281 |
|
2267 |
2282 |
/* first write to align to sector start */
|
2268 |
2283 |
len = (BDRV_SECTOR_SIZE - offset) & (BDRV_SECTOR_SIZE - 1);
|
2269 |
2284 |
if (len > count)
|
... | ... | |
2272 |
2287 |
if (len > 0) {
|
2273 |
2288 |
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
|
2274 |
2289 |
return ret;
|
2275 |
|
memcpy(tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), buf, len);
|
|
2290 |
qemu_iovec_to_buf(qiov, 0, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)),
|
|
2291 |
len);
|
2276 |
2292 |
if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
|
2277 |
2293 |
return ret;
|
2278 |
2294 |
count -= len;
|
2279 |
2295 |
if (count == 0)
|
2280 |
|
return count1;
|
|
2296 |
return qiov->size;
|
2281 |
2297 |
sector_num++;
|
2282 |
|
buf += len;
|
2283 |
2298 |
}
|
2284 |
2299 |
|
2285 |
2300 |
/* write the sectors "in place" */
|
2286 |
2301 |
nb_sectors = count >> BDRV_SECTOR_BITS;
|
2287 |
2302 |
if (nb_sectors > 0) {
|
2288 |
|
if ((ret = bdrv_write(bs, sector_num, buf, nb_sectors)) < 0)
|
|
2303 |
QEMUIOVector qiov_inplace;
|
|
2304 |
|
|
2305 |
qemu_iovec_init(&qiov_inplace, qiov->niov);
|
|
2306 |
qemu_iovec_concat(&qiov_inplace, qiov, len,
|
|
2307 |
nb_sectors << BDRV_SECTOR_BITS);
|
|
2308 |
ret = bdrv_writev(bs, sector_num, &qiov_inplace);
|
|
2309 |
qemu_iovec_destroy(&qiov_inplace);
|
|
2310 |
if (ret < 0) {
|
2289 |
2311 |
return ret;
|
|
2312 |
}
|
|
2313 |
|
2290 |
2314 |
sector_num += nb_sectors;
|
2291 |
2315 |
len = nb_sectors << BDRV_SECTOR_BITS;
|
2292 |
|
buf += len;
|
2293 |
2316 |
count -= len;
|
2294 |
2317 |
}
|
2295 |
2318 |
|
... | ... | |
2297 |
2320 |
if (count > 0) {
|
2298 |
2321 |
if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
|
2299 |
2322 |
return ret;
|
2300 |
|
memcpy(tmp_buf, buf, count);
|
|
2323 |
qemu_iovec_to_buf(qiov, qiov->size - count, tmp_buf, count);
|
2301 |
2324 |
if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
|
2302 |
2325 |
return ret;
|
2303 |
2326 |
}
|
2304 |
|
return count1;
|
|
2327 |
return qiov->size;
|
|
2328 |
}
|
|
2329 |
|
|
2330 |
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
|
|
2331 |
const void *buf, int count1)
|
|
2332 |
{
|
|
2333 |
QEMUIOVector qiov;
|
|
2334 |
struct iovec iov = {
|
|
2335 |
.iov_base = (void *) buf,
|
|
2336 |
.iov_len = count1,
|
|
2337 |
};
|
|
2338 |
|
|
2339 |
qemu_iovec_init_external(&qiov, &iov, 1);
|
|
2340 |
return bdrv_pwritev(bs, offset, &qiov);
|
2305 |
2341 |
}
|
2306 |
2342 |
|
2307 |
2343 |
/*
|