1 /* 2 * Blockjob tests 3 * 4 * Copyright Igalia, S.L. 2016 5 * 6 * Authors: 7 * Alberto Garcia <berto@igalia.com> 8 * 9 * This work is licensed under the terms of the GNU LGPL, version 2 or later. 10 * See the COPYING.LIB file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "qapi/error.h" 15 #include "qemu/main-loop.h" 16 #include "block/blockjob_int.h" 17 #include "sysemu/block-backend.h" 18 #include "qapi/qmp/qdict.h" 19 #include "iothread.h" 20 21 static const BlockJobDriver test_block_job_driver = { 22 .job_driver = { 23 .instance_size = sizeof(BlockJob), 24 .free = block_job_free, 25 .user_resume = block_job_user_resume, 26 }, 27 }; 28 29 static void block_job_cb(void *opaque, int ret) 30 { 31 } 32 33 static BlockJob *mk_job(BlockBackend *blk, const char *id, 34 const BlockJobDriver *drv, bool should_succeed, 35 int flags) 36 { 37 BlockJob *job; 38 Error *err = NULL; 39 40 job = block_job_create(id, drv, NULL, blk_bs(blk), 41 0, BLK_PERM_ALL, 0, flags, block_job_cb, 42 NULL, &err); 43 if (should_succeed) { 44 g_assert_null(err); 45 g_assert_nonnull(job); 46 if (id) { 47 g_assert_cmpstr(job->job.id, ==, id); 48 } else { 49 g_assert_cmpstr(job->job.id, ==, blk_name(blk)); 50 } 51 } else { 52 error_free_or_abort(&err); 53 g_assert_null(job); 54 } 55 56 return job; 57 } 58 59 static BlockJob *do_test_id(BlockBackend *blk, const char *id, 60 bool should_succeed) 61 { 62 return mk_job(blk, id, &test_block_job_driver, 63 should_succeed, JOB_DEFAULT); 64 } 65 66 /* This creates a BlockBackend (optionally with a name) with a 67 * BlockDriverState inserted. */ 68 static BlockBackend *create_blk(const char *name) 69 { 70 /* No I/O is performed on this device */ 71 BlockBackend *blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); 72 BlockDriverState *bs; 73 74 QDict *opt = qdict_new(); 75 qdict_put_str(opt, "file.read-zeroes", "on"); 76 bs = bdrv_open("null-co://", NULL, opt, 0, &error_abort); 77 g_assert_nonnull(bs); 78 79 blk_insert_bs(blk, bs, &error_abort); 80 bdrv_unref(bs); 81 82 if (name) { 83 Error *err = NULL; 84 monitor_add_blk(blk, name, &err); 85 g_assert_null(err); 86 } 87 88 return blk; 89 } 90 91 /* This destroys the backend */ 92 static void destroy_blk(BlockBackend *blk) 93 { 94 if (blk_name(blk)[0] != '\0') { 95 monitor_remove_blk(blk); 96 } 97 98 blk_remove_bs(blk); 99 blk_unref(blk); 100 } 101 102 static void test_job_ids(void) 103 { 104 BlockBackend *blk[3]; 105 BlockJob *job[3]; 106 107 blk[0] = create_blk(NULL); 108 blk[1] = create_blk("drive1"); 109 blk[2] = create_blk("drive2"); 110 111 /* No job ID provided and the block backend has no name */ 112 job[0] = do_test_id(blk[0], NULL, false); 113 114 /* These are all invalid job IDs */ 115 job[0] = do_test_id(blk[0], "0id", false); 116 job[0] = do_test_id(blk[0], "", false); 117 job[0] = do_test_id(blk[0], " ", false); 118 job[0] = do_test_id(blk[0], "123", false); 119 job[0] = do_test_id(blk[0], "_id", false); 120 job[0] = do_test_id(blk[0], "-id", false); 121 job[0] = do_test_id(blk[0], ".id", false); 122 job[0] = do_test_id(blk[0], "#id", false); 123 124 /* This one is valid */ 125 job[0] = do_test_id(blk[0], "id0", true); 126 127 /* We can have two jobs in the same BDS */ 128 job[1] = do_test_id(blk[0], "id1", true); 129 job_early_fail(&job[1]->job); 130 131 /* Duplicate job IDs are not allowed */ 132 job[1] = do_test_id(blk[1], "id0", false); 133 134 /* But once job[0] finishes we can reuse its ID */ 135 job_early_fail(&job[0]->job); 136 job[1] = do_test_id(blk[1], "id0", true); 137 138 /* No job ID specified, defaults to the backend name ('drive1') */ 139 job_early_fail(&job[1]->job); 140 job[1] = do_test_id(blk[1], NULL, true); 141 142 /* Duplicate job ID */ 143 job[2] = do_test_id(blk[2], "drive1", false); 144 145 /* The ID of job[2] would default to 'drive2' but it is already in use */ 146 job[0] = do_test_id(blk[0], "drive2", true); 147 job[2] = do_test_id(blk[2], NULL, false); 148 149 /* This one is valid */ 150 job[2] = do_test_id(blk[2], "id_2", true); 151 152 job_early_fail(&job[0]->job); 153 job_early_fail(&job[1]->job); 154 job_early_fail(&job[2]->job); 155 156 destroy_blk(blk[0]); 157 destroy_blk(blk[1]); 158 destroy_blk(blk[2]); 159 } 160 161 typedef struct CancelJob { 162 BlockJob common; 163 BlockBackend *blk; 164 bool should_converge; 165 bool should_complete; 166 } CancelJob; 167 168 static void cancel_job_complete(Job *job, Error **errp) 169 { 170 CancelJob *s = container_of(job, CancelJob, common.job); 171 s->should_complete = true; 172 } 173 174 static int coroutine_fn cancel_job_run(Job *job, Error **errp) 175 { 176 CancelJob *s = container_of(job, CancelJob, common.job); 177 178 while (!s->should_complete) { 179 if (job_is_cancelled(&s->common.job)) { 180 return 0; 181 } 182 183 if (!job_is_ready(&s->common.job) && s->should_converge) { 184 job_transition_to_ready(&s->common.job); 185 } 186 187 job_sleep_ns(&s->common.job, 100000); 188 } 189 190 return 0; 191 } 192 193 static const BlockJobDriver test_cancel_driver = { 194 .job_driver = { 195 .instance_size = sizeof(CancelJob), 196 .free = block_job_free, 197 .user_resume = block_job_user_resume, 198 .run = cancel_job_run, 199 .complete = cancel_job_complete, 200 }, 201 }; 202 203 static CancelJob *create_common(Job **pjob) 204 { 205 BlockBackend *blk; 206 Job *job; 207 BlockJob *bjob; 208 CancelJob *s; 209 210 blk = create_blk(NULL); 211 bjob = mk_job(blk, "Steve", &test_cancel_driver, true, 212 JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS); 213 job = &bjob->job; 214 WITH_JOB_LOCK_GUARD() { 215 job_ref_locked(job); 216 assert(job->status == JOB_STATUS_CREATED); 217 } 218 219 s = container_of(bjob, CancelJob, common); 220 s->blk = blk; 221 222 *pjob = job; 223 return s; 224 } 225 226 static void cancel_common(CancelJob *s) 227 { 228 BlockJob *job = &s->common; 229 BlockBackend *blk = s->blk; 230 JobStatus sts = job->job.status; 231 AioContext *ctx = job->job.aio_context; 232 233 job_cancel_sync(&job->job, true); 234 WITH_JOB_LOCK_GUARD() { 235 if (sts != JOB_STATUS_CREATED && sts != JOB_STATUS_CONCLUDED) { 236 Job *dummy = &job->job; 237 job_dismiss_locked(&dummy, &error_abort); 238 } 239 assert(job->job.status == JOB_STATUS_NULL); 240 job_unref_locked(&job->job); 241 } 242 243 aio_context_acquire(ctx); 244 destroy_blk(blk); 245 aio_context_release(ctx); 246 247 } 248 249 static void test_cancel_created(void) 250 { 251 Job *job; 252 CancelJob *s; 253 254 s = create_common(&job); 255 cancel_common(s); 256 } 257 258 static void assert_job_status_is(Job *job, int status) 259 { 260 WITH_JOB_LOCK_GUARD() { 261 assert(job->status == status); 262 } 263 } 264 265 static void test_cancel_running(void) 266 { 267 Job *job; 268 CancelJob *s; 269 270 s = create_common(&job); 271 272 job_start(job); 273 assert_job_status_is(job, JOB_STATUS_RUNNING); 274 275 cancel_common(s); 276 } 277 278 static void test_cancel_paused(void) 279 { 280 Job *job; 281 CancelJob *s; 282 283 s = create_common(&job); 284 285 job_start(job); 286 WITH_JOB_LOCK_GUARD() { 287 assert(job->status == JOB_STATUS_RUNNING); 288 job_user_pause_locked(job, &error_abort); 289 } 290 job_enter(job); 291 assert_job_status_is(job, JOB_STATUS_PAUSED); 292 293 cancel_common(s); 294 } 295 296 static void test_cancel_ready(void) 297 { 298 Job *job; 299 CancelJob *s; 300 301 s = create_common(&job); 302 303 job_start(job); 304 assert_job_status_is(job, JOB_STATUS_RUNNING); 305 306 s->should_converge = true; 307 job_enter(job); 308 assert_job_status_is(job, JOB_STATUS_READY); 309 310 cancel_common(s); 311 } 312 313 static void test_cancel_standby(void) 314 { 315 Job *job; 316 CancelJob *s; 317 318 s = create_common(&job); 319 320 job_start(job); 321 assert_job_status_is(job, JOB_STATUS_RUNNING); 322 323 s->should_converge = true; 324 job_enter(job); 325 WITH_JOB_LOCK_GUARD() { 326 assert(job->status == JOB_STATUS_READY); 327 job_user_pause_locked(job, &error_abort); 328 } 329 job_enter(job); 330 assert_job_status_is(job, JOB_STATUS_STANDBY); 331 332 cancel_common(s); 333 } 334 335 static void test_cancel_pending(void) 336 { 337 Job *job; 338 CancelJob *s; 339 340 s = create_common(&job); 341 342 job_start(job); 343 assert_job_status_is(job, JOB_STATUS_RUNNING); 344 345 s->should_converge = true; 346 job_enter(job); 347 WITH_JOB_LOCK_GUARD() { 348 assert(job->status == JOB_STATUS_READY); 349 job_complete_locked(job, &error_abort); 350 } 351 job_enter(job); 352 while (!job->deferred_to_main_loop) { 353 aio_poll(qemu_get_aio_context(), true); 354 } 355 assert_job_status_is(job, JOB_STATUS_READY); 356 aio_poll(qemu_get_aio_context(), true); 357 assert_job_status_is(job, JOB_STATUS_PENDING); 358 359 cancel_common(s); 360 } 361 362 static void test_cancel_concluded(void) 363 { 364 Job *job; 365 CancelJob *s; 366 367 s = create_common(&job); 368 369 job_start(job); 370 assert_job_status_is(job, JOB_STATUS_RUNNING); 371 372 s->should_converge = true; 373 job_enter(job); 374 WITH_JOB_LOCK_GUARD() { 375 assert(job->status == JOB_STATUS_READY); 376 job_complete_locked(job, &error_abort); 377 } 378 job_enter(job); 379 while (!job->deferred_to_main_loop) { 380 aio_poll(qemu_get_aio_context(), true); 381 } 382 assert_job_status_is(job, JOB_STATUS_READY); 383 aio_poll(qemu_get_aio_context(), true); 384 assert_job_status_is(job, JOB_STATUS_PENDING); 385 386 WITH_JOB_LOCK_GUARD() { 387 job_finalize_locked(job, &error_abort); 388 assert(job->status == JOB_STATUS_CONCLUDED); 389 } 390 391 cancel_common(s); 392 } 393 394 /* (See test_yielding_driver for the job description) */ 395 typedef struct YieldingJob { 396 BlockJob common; 397 bool should_complete; 398 } YieldingJob; 399 400 static void yielding_job_complete(Job *job, Error **errp) 401 { 402 YieldingJob *s = container_of(job, YieldingJob, common.job); 403 s->should_complete = true; 404 job_enter(job); 405 } 406 407 static int coroutine_fn yielding_job_run(Job *job, Error **errp) 408 { 409 YieldingJob *s = container_of(job, YieldingJob, common.job); 410 411 job_transition_to_ready(job); 412 413 while (!s->should_complete) { 414 job_yield(job); 415 } 416 417 return 0; 418 } 419 420 /* 421 * This job transitions immediately to the READY state, and then 422 * yields until it is to complete. 423 */ 424 static const BlockJobDriver test_yielding_driver = { 425 .job_driver = { 426 .instance_size = sizeof(YieldingJob), 427 .free = block_job_free, 428 .user_resume = block_job_user_resume, 429 .run = yielding_job_run, 430 .complete = yielding_job_complete, 431 }, 432 }; 433 434 /* 435 * Test that job_complete_locked() works even on jobs that are in a paused 436 * state (i.e., STANDBY). 437 * 438 * To do this, run YieldingJob in an IO thread, get it into the READY 439 * state, then have a drained section. Before ending the section, 440 * acquire the context so the job will not be entered and will thus 441 * remain on STANDBY. 442 * 443 * job_complete_locked() should still work without error. 444 * 445 * Note that on the QMP interface, it is impossible to lock an IO 446 * thread before a drained section ends. In practice, the 447 * bdrv_drain_all_end() and the aio_context_acquire() will be 448 * reversed. However, that makes for worse reproducibility here: 449 * Sometimes, the job would no longer be in STANDBY then but already 450 * be started. We cannot prevent that, because the IO thread runs 451 * concurrently. We can only prevent it by taking the lock before 452 * ending the drained section, so we do that. 453 * 454 * (You can reverse the order of operations and most of the time the 455 * test will pass, but sometimes the assert(status == STANDBY) will 456 * fail.) 457 */ 458 static void test_complete_in_standby(void) 459 { 460 BlockBackend *blk; 461 IOThread *iothread; 462 AioContext *ctx; 463 Job *job; 464 BlockJob *bjob; 465 466 /* Create a test drive, move it to an IO thread */ 467 blk = create_blk(NULL); 468 iothread = iothread_new(); 469 470 ctx = iothread_get_aio_context(iothread); 471 blk_set_aio_context(blk, ctx, &error_abort); 472 473 /* Create our test job */ 474 bjob = mk_job(blk, "job", &test_yielding_driver, true, 475 JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS); 476 job = &bjob->job; 477 assert_job_status_is(job, JOB_STATUS_CREATED); 478 479 /* Wait for the job to become READY */ 480 job_start(job); 481 /* 482 * Here we are waiting for the status to change, so don't bother 483 * protecting the read every time. 484 */ 485 AIO_WAIT_WHILE_UNLOCKED(ctx, job->status != JOB_STATUS_READY); 486 487 /* Begin the drained section, pausing the job */ 488 bdrv_drain_all_begin(); 489 assert_job_status_is(job, JOB_STATUS_STANDBY); 490 491 /* Lock the IO thread to prevent the job from being run */ 492 aio_context_acquire(ctx); 493 /* This will schedule the job to resume it */ 494 bdrv_drain_all_end(); 495 aio_context_release(ctx); 496 497 WITH_JOB_LOCK_GUARD() { 498 /* But the job cannot run, so it will remain on standby */ 499 assert(job->status == JOB_STATUS_STANDBY); 500 501 /* Even though the job is on standby, this should work */ 502 job_complete_locked(job, &error_abort); 503 504 /* The test is done now, clean up. */ 505 job_finish_sync_locked(job, NULL, &error_abort); 506 assert(job->status == JOB_STATUS_PENDING); 507 508 job_finalize_locked(job, &error_abort); 509 assert(job->status == JOB_STATUS_CONCLUDED); 510 511 job_dismiss_locked(&job, &error_abort); 512 } 513 514 aio_context_acquire(ctx); 515 destroy_blk(blk); 516 aio_context_release(ctx); 517 iothread_join(iothread); 518 } 519 520 int main(int argc, char **argv) 521 { 522 qemu_init_main_loop(&error_abort); 523 bdrv_init(); 524 525 g_test_init(&argc, &argv, NULL); 526 g_test_add_func("/blockjob/ids", test_job_ids); 527 g_test_add_func("/blockjob/cancel/created", test_cancel_created); 528 g_test_add_func("/blockjob/cancel/running", test_cancel_running); 529 g_test_add_func("/blockjob/cancel/paused", test_cancel_paused); 530 g_test_add_func("/blockjob/cancel/ready", test_cancel_ready); 531 g_test_add_func("/blockjob/cancel/standby", test_cancel_standby); 532 g_test_add_func("/blockjob/cancel/pending", test_cancel_pending); 533 g_test_add_func("/blockjob/cancel/concluded", test_cancel_concluded); 534 g_test_add_func("/blockjob/complete_in_standby", test_complete_in_standby); 535 return g_test_run(); 536 } 537