Revision f141eafe block-qcow2.c

b/block-qcow2.c
1264 1264
typedef struct QCowAIOCB {
1265 1265
    BlockDriverAIOCB common;
1266 1266
    int64_t sector_num;
1267
    QEMUIOVector *qiov;
1267 1268
    uint8_t *buf;
1269
    void *orig_buf;
1268 1270
    int nb_sectors;
1269 1271
    int n;
1270 1272
    uint64_t cluster_offset;
......
1307 1309
    int index_in_cluster, n1;
1308 1310

  
1309 1311
    acb->hd_aiocb = NULL;
1310
    if (ret < 0) {
1311
fail:
1312
        acb->common.cb(acb->common.opaque, ret);
1313
        qemu_aio_release(acb);
1314
        return;
1315
    }
1312
    if (ret < 0)
1313
        goto done;
1316 1314

  
1317 1315
    /* post process the read buffer */
1318 1316
    if (!acb->cluster_offset) {
......
1333 1331

  
1334 1332
    if (acb->nb_sectors == 0) {
1335 1333
        /* request completed */
1336
        acb->common.cb(acb->common.opaque, 0);
1337
        qemu_aio_release(acb);
1338
        return;
1334
        ret = 0;
1335
        goto done;
1339 1336
    }
1340 1337

  
1341 1338
    /* prepare next AIO request */
......
1356 1353
                                    &acb->hd_qiov, acb->n,
1357 1354
				    qcow_aio_read_cb, acb);
1358 1355
                if (acb->hd_aiocb == NULL)
1359
                    goto fail;
1356
                    goto done;
1360 1357
            } else {
1361 1358
                ret = qcow_schedule_bh(qcow_aio_read_bh, acb);
1362 1359
                if (ret < 0)
1363
                    goto fail;
1360
                    goto done;
1364 1361
            }
1365 1362
        } else {
1366 1363
            /* Note: in this case, no need to wait */
1367 1364
            memset(acb->buf, 0, 512 * acb->n);
1368 1365
            ret = qcow_schedule_bh(qcow_aio_read_bh, acb);
1369 1366
            if (ret < 0)
1370
                goto fail;
1367
                goto done;
1371 1368
        }
1372 1369
    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
1373 1370
        /* add AIO support for compressed blocks ? */
1374 1371
        if (decompress_cluster(s, acb->cluster_offset) < 0)
1375
            goto fail;
1372
            goto done;
1376 1373
        memcpy(acb->buf,
1377 1374
               s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
1378 1375
        ret = qcow_schedule_bh(qcow_aio_read_bh, acb);
1379 1376
        if (ret < 0)
1380
            goto fail;
1377
            goto done;
1381 1378
    } else {
1382 1379
        if ((acb->cluster_offset & 511) != 0) {
1383 1380
            ret = -EIO;
1384
            goto fail;
1381
            goto done;
1385 1382
        }
1386 1383

  
1387 1384
        acb->hd_iov.iov_base = acb->buf;
......
1391 1388
                            (acb->cluster_offset >> 9) + index_in_cluster,
1392 1389
                            &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
1393 1390
        if (acb->hd_aiocb == NULL)
1394
            goto fail;
1391
            goto done;
1392
    }
1393

  
1394
    return;
1395
done:
1396
    if (acb->qiov->niov > 1) {
1397
        qemu_iovec_from_buffer(acb->qiov, acb->orig_buf, acb->qiov->size);
1398
        qemu_vfree(acb->orig_buf);
1395 1399
    }
1400
    acb->common.cb(acb->common.opaque, ret);
1401
    qemu_aio_release(acb);
1396 1402
}
1397 1403

  
1398 1404
static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
1399
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1400
        BlockDriverCompletionFunc *cb, void *opaque)
1405
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
1406
        BlockDriverCompletionFunc *cb, void *opaque, int is_write)
1401 1407
{
1402 1408
    QCowAIOCB *acb;
1403 1409

  
......
1406 1412
        return NULL;
1407 1413
    acb->hd_aiocb = NULL;
1408 1414
    acb->sector_num = sector_num;
1409
    acb->buf = buf;
1415
    acb->qiov = qiov;
1416
    if (qiov->niov > 1) {
1417
        acb->buf = acb->orig_buf = qemu_memalign(512, qiov->size);
1418
        if (is_write)
1419
            qemu_iovec_to_buffer(qiov, acb->buf);
1420
    } else
1421
        acb->buf = qiov->iov->iov_base;
1410 1422
    acb->nb_sectors = nb_sectors;
1411 1423
    acb->n = 0;
1412 1424
    acb->cluster_offset = 0;
......
1414 1426
    return acb;
1415 1427
}
1416 1428

  
1417
static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
1418
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1429
static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs,
1430
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
1419 1431
        BlockDriverCompletionFunc *cb, void *opaque)
1420 1432
{
1421 1433
    QCowAIOCB *acb;
1422 1434

  
1423
    acb = qcow_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
1435
    acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
1424 1436
    if (!acb)
1425 1437
        return NULL;
1426 1438

  
......
1439 1451

  
1440 1452
    acb->hd_aiocb = NULL;
1441 1453

  
1442
    if (ret < 0) {
1443
    fail:
1444
        acb->common.cb(acb->common.opaque, ret);
1445
        qemu_aio_release(acb);
1446
        return;
1447
    }
1454
    if (ret < 0)
1455
        goto done;
1448 1456

  
1449 1457
    if (alloc_cluster_link_l2(bs, acb->cluster_offset, &acb->l2meta) < 0) {
1450 1458
        free_any_clusters(bs, acb->cluster_offset, acb->l2meta.nb_clusters);
1451
        goto fail;
1459
        goto done;
1452 1460
    }
1453 1461

  
1454 1462
    acb->nb_sectors -= acb->n;
......
1457 1465

  
1458 1466
    if (acb->nb_sectors == 0) {
1459 1467
        /* request completed */
1460
        acb->common.cb(acb->common.opaque, 0);
1461
        qemu_aio_release(acb);
1462
        return;
1468
        ret = 0;
1469
        goto done;
1463 1470
    }
1464 1471

  
1465 1472
    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
......
1473 1480
                                          n_end, &acb->n, &acb->l2meta);
1474 1481
    if (!acb->cluster_offset || (acb->cluster_offset & 511) != 0) {
1475 1482
        ret = -EIO;
1476
        goto fail;
1483
        goto done;
1477 1484
    }
1478 1485
    if (s->crypt_method) {
1479 1486
        if (!acb->cluster_data) {
......
1494 1501
                                    &acb->hd_qiov, acb->n,
1495 1502
                                    qcow_aio_write_cb, acb);
1496 1503
    if (acb->hd_aiocb == NULL)
1497
        goto fail;
1504
        goto done;
1505

  
1506
    return;
1507

  
1508
done:
1509
    if (acb->qiov->niov > 1)
1510
        qemu_vfree(acb->orig_buf);
1511
    acb->common.cb(acb->common.opaque, ret);
1512
    qemu_aio_release(acb);
1498 1513
}
1499 1514

  
1500
static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
1501
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
1515
static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
1516
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
1502 1517
        BlockDriverCompletionFunc *cb, void *opaque)
1503 1518
{
1504 1519
    BDRVQcowState *s = bs->opaque;
......
1506 1521

  
1507 1522
    s->cluster_cache_offset = -1; /* disable compressed cache */
1508 1523

  
1509
    acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
1524
    acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
1510 1525
    if (!acb)
1511 1526
        return NULL;
1512 1527

  
......
2771 2786
    .bdrv_set_key	= qcow_set_key,
2772 2787
    .bdrv_make_empty	= qcow_make_empty,
2773 2788

  
2774
    .bdrv_aio_read	= qcow_aio_read,
2775
    .bdrv_aio_write	= qcow_aio_write,
2789
    .bdrv_aio_readv	= qcow_aio_readv,
2790
    .bdrv_aio_writev	= qcow_aio_writev,
2776 2791
    .bdrv_aio_cancel	= qcow_aio_cancel,
2777 2792
    .aiocb_size		= sizeof(QCowAIOCB),
2778 2793
    .bdrv_write_compressed = qcow_write_compressed,

Also available in: Unified diff