Merge remote-tracking branch 'stefanha/block' into staging

# By Fam Zheng (2) and Stefan Hajnoczi (1)
# Via Stefan Hajnoczi
* stefanha/block:
  block: fix bdrv_flush() ordering in bdrv_close()
  curl: refuse to open URL from HTTP server without range support
  vmdk: Implement .bdrv_has_zero_init

Message-id: 1373023972-3587-1-git-send-email-stefanha@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2013-07-07 11:28:01 -05:00
commit 9b4abb4677
3 changed files with 53 additions and 22 deletions

View File

@ -1358,11 +1358,12 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state)
void bdrv_close(BlockDriverState *bs)
{
bdrv_flush(bs);
if (bs->job) {
block_job_cancel_sync(bs->job);
}
bdrv_drain_all();
bdrv_drain_all(); /* complete I/O */
bdrv_flush(bs);
bdrv_drain_all(); /* in case flush left pending I/O */
notifier_list_notify(&bs->close_notifiers, bs);
if (bs->drv) {

View File

@ -81,6 +81,7 @@ typedef struct BDRVCURLState {
CURLState states[CURL_NUM_STATES];
char *url;
size_t readahead_size;
bool accept_range;
} BDRVCURLState;
static void curl_clean_state(CURLState *s);
@ -110,14 +111,15 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
return 0;
}
static size_t curl_size_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
{
CURLState *s = ((CURLState*)opaque);
BDRVCURLState *s = opaque;
size_t realsize = size * nmemb;
size_t fsize;
const char *accept_line = "Accept-Ranges: bytes";
if(sscanf(ptr, "Content-Length: %zd", &fsize) == 1) {
s->s->len = fsize;
if (realsize >= strlen(accept_line)
&& strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) {
s->accept_range = true;
}
return realsize;
@ -447,8 +449,11 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags)
// Get file size
s->accept_range = false;
curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1);
curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_size_cb);
curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION,
curl_header_cb);
curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s);
if (curl_easy_perform(state->curl))
goto out;
curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
@ -456,6 +461,13 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags)
s->len = (size_t)d;
else if(!s->len)
goto out;
if ((!strncasecmp(s->url, "http://", strlen("http://"))
|| !strncasecmp(s->url, "https://", strlen("https://")))
&& !s->accept_range) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Server does not support 'range' (byte ranges).");
goto out;
}
DPRINTF("CURL: Size = %zd\n", s->len);
curl_clean_state(state);

View File

@ -1724,6 +1724,23 @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
return ret;
}
static int vmdk_has_zero_init(BlockDriverState *bs)
{
int i;
BDRVVmdkState *s = bs->opaque;
/* If has a flat extent and its underlying storage doesn't have zero init,
* return 0. */
for (i = 0; i < s->num_extents; i++) {
if (s->extents[i].flat) {
if (!bdrv_has_zero_init(s->extents[i].file)) {
return 0;
}
}
}
return 1;
}
static QEMUOptionParameter vmdk_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
@ -1775,6 +1792,7 @@ static BlockDriver bdrv_vmdk = {
.bdrv_co_flush_to_disk = vmdk_co_flush,
.bdrv_co_is_allocated = vmdk_co_is_allocated,
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
.bdrv_has_zero_init = vmdk_has_zero_init,
.create_options = vmdk_create_options,
};