Revision 453f9a16
b/block.c | ||
---|---|---|
2183 | 2183 |
// Check for mergable requests |
2184 | 2184 |
num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb); |
2185 | 2185 |
|
2186 |
// Run the aio requests |
|
2186 |
/* |
|
2187 |
* Run the aio requests. As soon as one request can't be submitted |
|
2188 |
* successfully, fail all requests that are not yet submitted (we must |
|
2189 |
* return failure for all requests anyway) |
|
2190 |
* |
|
2191 |
* num_requests cannot be set to the right value immediately: If |
|
2192 |
* bdrv_aio_writev fails for some request, num_requests would be too high |
|
2193 |
* and therefore multiwrite_cb() would never recognize the multiwrite |
|
2194 |
* request as completed. We also cannot use the loop variable i to set it |
|
2195 |
* when the first request fails because the callback may already have been |
|
2196 |
* called for previously submitted requests. Thus, num_requests must be |
|
2197 |
* incremented for each request that is submitted. |
|
2198 |
* |
|
2199 |
* The problem that callbacks may be called early also means that we need |
|
2200 |
* to take care that num_requests doesn't become 0 before all requests are |
|
2201 |
* submitted - multiwrite_cb() would consider the multiwrite request |
|
2202 |
* completed. A dummy request that is "completed" by a manual call to |
|
2203 |
* multiwrite_cb() takes care of this. |
|
2204 |
*/ |
|
2205 |
mcb->num_requests = 1; |
|
2206 |
|
|
2187 | 2207 |
for (i = 0; i < num_reqs; i++) { |
2208 |
mcb->num_requests++; |
|
2188 | 2209 |
acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov, |
2189 | 2210 |
reqs[i].nb_sectors, multiwrite_cb, mcb); |
2190 | 2211 |
|
... | ... | |
2192 | 2213 |
// We can only fail the whole thing if no request has been |
2193 | 2214 |
// submitted yet. Otherwise we'll wait for the submitted AIOs to |
2194 | 2215 |
// complete and report the error in the callback. |
2195 |
if (mcb->num_requests == 0) { |
|
2196 |
reqs[i].error = -EIO; |
|
2216 |
if (i == 0) { |
|
2197 | 2217 |
goto fail; |
2198 | 2218 |
} else { |
2199 |
mcb->num_requests++; |
|
2200 | 2219 |
multiwrite_cb(mcb, -EIO); |
2201 | 2220 |
break; |
2202 | 2221 |
} |
2203 |
} else { |
|
2204 |
mcb->num_requests++; |
|
2205 | 2222 |
} |
2206 | 2223 |
} |
2207 | 2224 |
|
2225 |
/* Complete the dummy request */ |
|
2226 |
multiwrite_cb(mcb, 0); |
|
2227 |
|
|
2208 | 2228 |
return 0; |
2209 | 2229 |
|
2210 | 2230 |
fail: |
2231 |
for (i = 0; i < mcb->num_callbacks; i++) { |
|
2232 |
reqs[i].error = -EIO; |
|
2233 |
} |
|
2211 | 2234 |
qemu_free(mcb); |
2212 | 2235 |
return -1; |
2213 | 2236 |
} |
Also available in: Unified diff