提交 7b6badb6 编写于 作者: S Stefan Hajnoczi

Merge remote-tracking branch 'jtc/tags/block-pull-request' into staging

# gpg: Signature made Fri 26 May 2017 08:22:27 PM BST
# gpg:                using RSA key 0xBDBE7B27C0DE3057
# gpg: Good signature from "Jeffrey Cody <jcody@redhat.com>"
# gpg:                 aka "Jeffrey Cody <jeff@codyprime.org>"
# gpg:                 aka "Jeffrey Cody <codyprime@gmail.com>"
# Primary key fingerprint: 9957 4B4D 3474 90E7 9D98  D624 BDBE 7B27 C0DE 3057

* jtc/tags/block-pull-request:
  block/gluster: glfs_lseek() workaround
  blockjob: use deferred_to_main_loop to indicate the coroutine has ended
  blockjob: reorganize block_job_completed_txn_abort
  blockjob: strengthen a bit test-blockjob-txn
  blockjob: group BlockJob transaction functions together
  blockjob: introduce block_job_cancel_async, check iostatus invariants
  blockjob: move iostatus reset inside block_job_user_resume
  blockjob: separate monitor and blockjob APIs
  blockjob: introduce block_job_pause/resume_all
  blockjob: introduce block_job_early_fail
  blockjob: remove iostatus_reset callback
  blockjob: remove unnecessary check
Signed-off-by: NStefan Hajnoczi <stefanha@redhat.com>
...@@ -692,7 +692,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, ...@@ -692,7 +692,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
} }
if (job) { if (job) {
backup_clean(&job->common); backup_clean(&job->common);
block_job_unref(&job->common); block_job_early_fail(&job->common);
} }
return NULL; return NULL;
......
...@@ -426,7 +426,7 @@ fail: ...@@ -426,7 +426,7 @@ fail:
if (commit_top_bs) { if (commit_top_bs) {
bdrv_set_backing_hd(overlay_bs, top, &error_abort); bdrv_set_backing_hd(overlay_bs, top, &error_abort);
} }
block_job_unref(&s->common); block_job_early_fail(&s->common);
} }
......
...@@ -1275,7 +1275,14 @@ static int find_allocation(BlockDriverState *bs, off_t start, ...@@ -1275,7 +1275,14 @@ static int find_allocation(BlockDriverState *bs, off_t start,
if (offs < 0) { if (offs < 0) {
return -errno; /* D3 or D4 */ return -errno; /* D3 or D4 */
} }
assert(offs >= start);
if (offs < start) {
/* This is not a valid return by lseek(). We are safe to just return
* -EIO in this case, and we'll treat it like D4. Unfortunately some
* versions of gluster server will return offs < start, so an assert
* here will unnecessarily abort QEMU. */
return -EIO;
}
if (offs > start) { if (offs > start) {
/* D2: in hole, next data at offs */ /* D2: in hole, next data at offs */
...@@ -1307,7 +1314,14 @@ static int find_allocation(BlockDriverState *bs, off_t start, ...@@ -1307,7 +1314,14 @@ static int find_allocation(BlockDriverState *bs, off_t start,
if (offs < 0) { if (offs < 0) {
return -errno; /* D1 and (H3 or H4) */ return -errno; /* D1 and (H3 or H4) */
} }
assert(offs >= start);
if (offs < start) {
/* This is not a valid return by lseek(). We are safe to just return
* -EIO in this case, and we'll treat it like H4. Unfortunately some
* versions of gluster server will return offs < start, so an assert
* here will unnecessarily abort QEMU. */
return -EIO;
}
if (offs > start) { if (offs > start) {
/* /*
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "trace.h" #include "trace.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "block/blockjob.h" #include "block/blockjob.h"
#include "block/blockjob_int.h"
#include "block/block_int.h" #include "block/block_int.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qapi/error.h" #include "qapi/error.h"
...@@ -301,16 +302,9 @@ void bdrv_drain_all_begin(void) ...@@ -301,16 +302,9 @@ void bdrv_drain_all_begin(void)
bool waited = true; bool waited = true;
BlockDriverState *bs; BlockDriverState *bs;
BdrvNextIterator it; BdrvNextIterator it;
BlockJob *job = NULL;
GSList *aio_ctxs = NULL, *ctx; GSList *aio_ctxs = NULL, *ctx;
while ((job = block_job_next(job))) { block_job_pause_all();
AioContext *aio_context = blk_get_aio_context(job->blk);
aio_context_acquire(aio_context);
block_job_pause(job);
aio_context_release(aio_context);
}
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
AioContext *aio_context = bdrv_get_aio_context(bs); AioContext *aio_context = bdrv_get_aio_context(bs);
...@@ -354,7 +348,6 @@ void bdrv_drain_all_end(void) ...@@ -354,7 +348,6 @@ void bdrv_drain_all_end(void)
{ {
BlockDriverState *bs; BlockDriverState *bs;
BdrvNextIterator it; BdrvNextIterator it;
BlockJob *job = NULL;
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
AioContext *aio_context = bdrv_get_aio_context(bs); AioContext *aio_context = bdrv_get_aio_context(bs);
...@@ -365,13 +358,7 @@ void bdrv_drain_all_end(void) ...@@ -365,13 +358,7 @@ void bdrv_drain_all_end(void)
aio_context_release(aio_context); aio_context_release(aio_context);
} }
while ((job = block_job_next(job))) { block_job_resume_all();
AioContext *aio_context = blk_get_aio_context(job->blk);
aio_context_acquire(aio_context);
block_job_resume(job);
aio_context_release(aio_context);
}
} }
void bdrv_drain_all(void) void bdrv_drain_all(void)
......
...@@ -1252,7 +1252,7 @@ fail: ...@@ -1252,7 +1252,7 @@ fail:
g_free(s->replaces); g_free(s->replaces);
blk_unref(s->target); blk_unref(s->target);
block_job_unref(&s->common); block_job_early_fail(&s->common);
} }
bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL, bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL,
......
...@@ -3715,7 +3715,6 @@ void qmp_block_job_resume(const char *device, Error **errp) ...@@ -3715,7 +3715,6 @@ void qmp_block_job_resume(const char *device, Error **errp)
} }
trace_qmp_block_job_resume(job); trace_qmp_block_job_resume(job);
block_job_iostatus_reset(job);
block_job_user_resume(job); block_job_user_resume(job);
aio_context_release(aio_context); aio_context_release(aio_context);
} }
......
此差异已折叠。
...@@ -234,14 +234,6 @@ void block_job_complete(BlockJob *job, Error **errp); ...@@ -234,14 +234,6 @@ void block_job_complete(BlockJob *job, Error **errp);
*/ */
BlockJobInfo *block_job_query(BlockJob *job, Error **errp); BlockJobInfo *block_job_query(BlockJob *job, Error **errp);
/**
* block_job_pause:
* @job: The job to be paused.
*
* Asynchronously pause the specified job.
*/
void block_job_pause(BlockJob *job);
/** /**
* block_job_user_pause: * block_job_user_pause:
* @job: The job to be paused. * @job: The job to be paused.
...@@ -259,14 +251,6 @@ void block_job_user_pause(BlockJob *job); ...@@ -259,14 +251,6 @@ void block_job_user_pause(BlockJob *job);
*/ */
bool block_job_user_paused(BlockJob *job); bool block_job_user_paused(BlockJob *job);
/**
* block_job_resume:
* @job: The job to be resumed.
*
* Resume the specified job. Must be paired with a preceding block_job_pause.
*/
void block_job_resume(BlockJob *job);
/** /**
* block_job_user_resume: * block_job_user_resume:
* @job: The job to be resumed. * @job: The job to be resumed.
......
...@@ -44,9 +44,6 @@ struct BlockJobDriver { ...@@ -44,9 +44,6 @@ struct BlockJobDriver {
/** Optional callback for job types that support setting a speed limit */ /** Optional callback for job types that support setting a speed limit */
void (*set_speed)(BlockJob *job, int64_t speed, Error **errp); void (*set_speed)(BlockJob *job, int64_t speed, Error **errp);
/** Optional callback for job types that need to forward I/O status reset */
void (*iostatus_reset)(BlockJob *job);
/** Mandatory: Entrypoint for the Coroutine. */ /** Mandatory: Entrypoint for the Coroutine. */
CoroutineEntry *start; CoroutineEntry *start;
...@@ -159,21 +156,26 @@ void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns); ...@@ -159,21 +156,26 @@ void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns);
void block_job_yield(BlockJob *job); void block_job_yield(BlockJob *job);
/** /**
* block_job_ref: * block_job_pause_all:
* @bs: The block device. *
* Asynchronously pause all jobs.
*/
void block_job_pause_all(void);
/**
* block_job_resume_all:
* *
* Grab a reference to the block job. Should be paired with block_job_unref. * Resume all block jobs. Must be paired with a preceding block_job_pause_all.
*/ */
void block_job_ref(BlockJob *job); void block_job_resume_all(void);
/** /**
* block_job_unref: * block_job_early_fail:
* @bs: The block device. * @bs: The block device.
* *
* Release reference to the block job and release resources if it is the last * The block job could not be started, free it.
* reference.
*/ */
void block_job_unref(BlockJob *job); void block_job_early_fail(BlockJob *job);
/** /**
* block_job_completed: * block_job_completed:
...@@ -239,7 +241,8 @@ typedef void BlockJobDeferToMainLoopFn(BlockJob *job, void *opaque); ...@@ -239,7 +241,8 @@ typedef void BlockJobDeferToMainLoopFn(BlockJob *job, void *opaque);
* @fn: The function to run in the main loop * @fn: The function to run in the main loop
* @opaque: The opaque value that is passed to @fn * @opaque: The opaque value that is passed to @fn
* *
* Execute a given function in the main loop with the BlockDriverState * This function must be called by the main job coroutine just before it
* returns. @fn is executed in the main loop with the BlockDriverState
* AioContext acquired. Block jobs must call bdrv_unref(), bdrv_close(), and * AioContext acquired. Block jobs must call bdrv_unref(), bdrv_close(), and
* anything that uses bdrv_drain_all() in the main loop. * anything that uses bdrv_drain_all() in the main loop.
* *
......
...@@ -167,6 +167,11 @@ static void test_pair_jobs(int expected1, int expected2) ...@@ -167,6 +167,11 @@ static void test_pair_jobs(int expected1, int expected2)
block_job_start(job1); block_job_start(job1);
block_job_start(job2); block_job_start(job2);
/* Release our reference now to trigger as many nice
* use-after-free bugs as possible.
*/
block_job_txn_unref(txn);
if (expected1 == -ECANCELED) { if (expected1 == -ECANCELED) {
block_job_cancel(job1); block_job_cancel(job1);
} }
...@@ -187,8 +192,6 @@ static void test_pair_jobs(int expected1, int expected2) ...@@ -187,8 +192,6 @@ static void test_pair_jobs(int expected1, int expected2)
g_assert_cmpint(result1, ==, expected1); g_assert_cmpint(result1, ==, expected1);
g_assert_cmpint(result2, ==, expected2); g_assert_cmpint(result2, ==, expected2);
block_job_txn_unref(txn);
} }
static void test_pair_jobs_success(void) static void test_pair_jobs_success(void)
......
...@@ -116,11 +116,11 @@ static void test_job_ids(void) ...@@ -116,11 +116,11 @@ static void test_job_ids(void)
job[1] = do_test_id(blk[1], "id0", false); job[1] = do_test_id(blk[1], "id0", false);
/* But once job[0] finishes we can reuse its ID */ /* But once job[0] finishes we can reuse its ID */
block_job_unref(job[0]); block_job_early_fail(job[0]);
job[1] = do_test_id(blk[1], "id0", true); job[1] = do_test_id(blk[1], "id0", true);
/* No job ID specified, defaults to the backend name ('drive1') */ /* No job ID specified, defaults to the backend name ('drive1') */
block_job_unref(job[1]); block_job_early_fail(job[1]);
job[1] = do_test_id(blk[1], NULL, true); job[1] = do_test_id(blk[1], NULL, true);
/* Duplicate job ID */ /* Duplicate job ID */
...@@ -133,9 +133,9 @@ static void test_job_ids(void) ...@@ -133,9 +133,9 @@ static void test_job_ids(void)
/* This one is valid */ /* This one is valid */
job[2] = do_test_id(blk[2], "id_2", true); job[2] = do_test_id(blk[2], "id_2", true);
block_job_unref(job[0]); block_job_early_fail(job[0]);
block_job_unref(job[1]); block_job_early_fail(job[1]);
block_job_unref(job[2]); block_job_early_fail(job[2]);
destroy_blk(blk[0]); destroy_blk(blk[0]);
destroy_blk(blk[1]); destroy_blk(blk[1]);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册