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) void bdrv_close(BlockDriverState *bs)
{ {
bdrv_flush(bs);
if (bs->job) { if (bs->job) {
block_job_cancel_sync(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); notifier_list_notify(&bs->close_notifiers, bs);
if (bs->drv) { if (bs->drv) {

View File

@ -81,6 +81,7 @@ typedef struct BDRVCURLState {
CURLState states[CURL_NUM_STATES]; CURLState states[CURL_NUM_STATES];
char *url; char *url;
size_t readahead_size; size_t readahead_size;
bool accept_range;
} BDRVCURLState; } BDRVCURLState;
static void curl_clean_state(CURLState *s); 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; 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 realsize = size * nmemb;
size_t fsize; const char *accept_line = "Accept-Ranges: bytes";
if(sscanf(ptr, "Content-Length: %zd", &fsize) == 1) { if (realsize >= strlen(accept_line)
s->s->len = fsize; && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) {
s->accept_range = true;
} }
return realsize; return realsize;
@ -447,8 +449,11 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags)
// Get file size // Get file size
s->accept_range = false;
curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); 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)) if (curl_easy_perform(state->curl))
goto out; goto out;
curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d); 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; s->len = (size_t)d;
else if(!s->len) else if(!s->len)
goto out; 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); DPRINTF("CURL: Size = %zd\n", s->len);
curl_clean_state(state); curl_clean_state(state);

View File

@ -1724,6 +1724,23 @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs)
return ret; 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[] = { static QEMUOptionParameter vmdk_create_options[] = {
{ {
.name = BLOCK_OPT_SIZE, .name = BLOCK_OPT_SIZE,
@ -1762,21 +1779,22 @@ static QEMUOptionParameter vmdk_create_options[] = {
}; };
static BlockDriver bdrv_vmdk = { static BlockDriver bdrv_vmdk = {
.format_name = "vmdk", .format_name = "vmdk",
.instance_size = sizeof(BDRVVmdkState), .instance_size = sizeof(BDRVVmdkState),
.bdrv_probe = vmdk_probe, .bdrv_probe = vmdk_probe,
.bdrv_open = vmdk_open, .bdrv_open = vmdk_open,
.bdrv_reopen_prepare = vmdk_reopen_prepare, .bdrv_reopen_prepare = vmdk_reopen_prepare,
.bdrv_read = vmdk_co_read, .bdrv_read = vmdk_co_read,
.bdrv_write = vmdk_co_write, .bdrv_write = vmdk_co_write,
.bdrv_co_write_zeroes = vmdk_co_write_zeroes, .bdrv_co_write_zeroes = vmdk_co_write_zeroes,
.bdrv_close = vmdk_close, .bdrv_close = vmdk_close,
.bdrv_create = vmdk_create, .bdrv_create = vmdk_create,
.bdrv_co_flush_to_disk = vmdk_co_flush, .bdrv_co_flush_to_disk = vmdk_co_flush,
.bdrv_co_is_allocated = vmdk_co_is_allocated, .bdrv_co_is_allocated = vmdk_co_is_allocated,
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
.bdrv_has_zero_init = vmdk_has_zero_init,
.create_options = vmdk_create_options, .create_options = vmdk_create_options,
}; };
static void bdrv_vmdk_init(void) static void bdrv_vmdk_init(void)