VirtualBox

Changeset 38876 in vbox for trunk/src/VBox/Storage/testcase


Ignore:
Timestamp:
Sep 27, 2011 9:03:15 AM (13 years ago)
Author:
vboxsync
Message:

Storage: Add async discard API

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/testcase/tstVDIo.cpp

    r38644 r38876  
    134134    VDIOREQTXDIR_READ = 0,
    135135    VDIOREQTXDIR_WRITE,
    136     VDIOREQTXDIR_FLUSH
     136    VDIOREQTXDIR_FLUSH,
     137    VDIOREQTXDIR_DISCARD
    137138} VDIOREQTXDIR;
    138139
     
    143144{
    144145    /** Transfer type. */
    145     VDIOREQTXDIR enmTxDir;
     146    VDIOREQTXDIR  enmTxDir;
    146147    /** slot index. */
    147     unsigned  idx;
     148    unsigned      idx;
    148149    /** Start offset. */
    149     uint64_t  off;
     150    uint64_t      off;
    150151    /** Size to transfer. */
    151     size_t    cbReq;
     152    size_t        cbReq;
    152153    /** S/G Buffer */
    153     RTSGBUF   SgBuf;
     154    RTSGBUF       SgBuf;
    154155    /** Data segment */
    155     RTSGSEG   DataSeg;
     156    RTSGSEG       DataSeg;
    156157    /** Flag whether the request is outstanding or not. */
    157158    volatile bool fOutstanding;
     
    385386    /* pcszName    chId enmType                          fFlags */
    386387    {"disk",       'd', VDSCRIPTARGTYPE_STRING,          VDSCRIPTARGDESC_FLAG_MANDATORY},
    387     {"off",        'o', VDSCRIPTARGTYPE_UNSIGNED_NUMBER, VDSCRIPTARGDESC_FLAG_MANDATORY},
    388     {"size",       's', VDSCRIPTARGTYPE_UNSIGNED_NUMBER, VDSCRIPTARGDESC_FLAG_MANDATORY},
     388    {"async",      'a', VDSCRIPTARGTYPE_BOOL,            0},
     389    {"ranges",     'r', VDSCRIPTARGTYPE_STRING, VDSCRIPTARGDESC_FLAG_MANDATORY}
    389390};
    390391
     
    955956                                            break;
    956957                                        }
     958                                        case VDIOREQTXDIR_DISCARD:
     959                                            AssertMsgFailed(("Invalid\n"));
    957960                                    }
    958961
     
    983986                                            break;
    984987                                        }
     988                                        case VDIOREQTXDIR_DISCARD:
     989                                            AssertMsgFailed(("Invalid\n"));
    985990                                    }
    986991
     
    10281033                                            case VDIOREQTXDIR_FLUSH:
    10291034                                                break;
     1035                                            case VDIOREQTXDIR_DISCARD:
     1036                                                AssertMsgFailed(("Invalid\n"));
    10301037                                        }
    10311038
     
    12641271    const char *pcszDisk = NULL;
    12651272    PVDDISK pDisk = NULL;
    1266     uint64_t off;
    1267     size_t cbDiscard;
     1273    bool fAsync = false;
     1274    const char *pcszRanges = NULL;
    12681275
    12691276    for (unsigned i = 0; i < cScriptArgs; i++)
     
    12761283                break;
    12771284            }
    1278             case 'o':
    1279             {
    1280                 off = paScriptArgs[i].u.u64;
    1281                 break;
    1282             }
    1283             case 's':
    1284             {
    1285                 cbDiscard = paScriptArgs[i].u.u64;
    1286                 break;
    1287             }
    1288 
     1285            case 'a':
     1286            {
     1287                fAsync = paScriptArgs[i].u.fFlag;
     1288                break;
     1289            }
     1290            case 'r':
     1291            {
     1292                pcszRanges = paScriptArgs[i].u.pcszString;
     1293                break;
     1294            }
    12891295            default:
    12901296                AssertMsgFailed(("Invalid argument given!\n"));
    12911297        }
    1292 
    1293         if (RT_FAILURE(rc))
    1294             break;
    1295     }
    1296 
    1297     if (RT_SUCCESS(rc))
    1298     {
    1299         pDisk = tstVDIoGetDiskByName(pGlob, pcszDisk);
    1300         if (!pDisk)
    1301             rc = VERR_NOT_FOUND;
    1302         else
    1303         {
    1304             VDRANGE Range;
    1305 
    1306             Range.offStart = off;
    1307             Range.cbRange = cbDiscard;
    1308 
    1309             rc = VDDiscardRanges(pDisk->pVD, &Range, 1);
     1298    }
     1299
     1300    pDisk = tstVDIoGetDiskByName(pGlob, pcszDisk);
     1301    if (!pDisk)
     1302        rc = VERR_NOT_FOUND;
     1303    else
     1304    {
     1305        unsigned cRanges = 0;
     1306        PRTRANGE paRanges = NULL;
     1307
     1308        /*
     1309         * Parse the range string which should look like this:
     1310         * n,off1,cb1,off2,cb2,...
     1311         *
     1312         * <n> gives the number of ranges in the string and every off<i>,cb<i>
     1313         * pair afterwards is a start offset + number of bytes to discard entry.
     1314         */
     1315        do
     1316        {
     1317            rc = RTStrToUInt32Ex(pcszRanges, (char **)&pcszRanges, 10, &cRanges);
     1318            if (RT_FAILURE(rc) && (rc != VWRN_TRAILING_CHARS))
     1319                break;
     1320
     1321            if (!cRanges)
     1322            {
     1323                rc = VERR_INVALID_PARAMETER;
     1324                break;
     1325            }
     1326
     1327            paRanges = (PRTRANGE)RTMemAllocZ(cRanges * sizeof(RTRANGE));
     1328            if (!paRanges)
     1329            {
     1330                rc = VERR_NO_MEMORY;
     1331                break;
     1332            }
     1333
     1334            if (*pcszRanges != ',')
     1335            {
     1336                rc = VERR_INVALID_PARAMETER;
     1337                break;
     1338            }
     1339
     1340            pcszRanges++;
     1341
     1342            /* Retrieve each pair from the string. */
     1343            for (unsigned i = 0; i < cRanges; i++)
     1344            {
     1345                uint64_t off;
     1346                uint32_t cb;
     1347
     1348                rc = RTStrToUInt64Ex(pcszRanges, (char **)&pcszRanges, 10, &off);
     1349                if (RT_FAILURE(rc) && (rc != VWRN_TRAILING_CHARS))
     1350                    break;
     1351
     1352                if (*pcszRanges != ',')
     1353                {
     1354                    switch (*pcszRanges)
     1355                    {
     1356                        case 'k':
     1357                        case 'K':
     1358                        {
     1359                            off *= _1K;
     1360                            break;
     1361                        }
     1362                        case 'm':
     1363                        case 'M':
     1364                        {
     1365                            off *= _1M;
     1366                            break;
     1367                        }
     1368                        case 'g':
     1369                        case 'G':
     1370                        {
     1371                            off *= _1G;
     1372                            break;
     1373                        }
     1374                        default:
     1375                        {
     1376                            RTPrintf("Invalid size suffix '%s'\n", pcszRanges);
     1377                            rc = VERR_INVALID_PARAMETER;
     1378                        }
     1379                    }
     1380                    if (RT_SUCCESS(rc))
     1381                        pcszRanges++;
     1382                }
     1383
     1384                if (*pcszRanges != ',')
     1385                {
     1386                    rc = VERR_INVALID_PARAMETER;
     1387                    break;
     1388                }
     1389
     1390                pcszRanges++;
     1391
     1392                rc = RTStrToUInt32Ex(pcszRanges, (char **)&pcszRanges, 10, &cb);
     1393                if (RT_FAILURE(rc) && (rc != VWRN_TRAILING_CHARS))
     1394                    break;
     1395
     1396                if (*pcszRanges != ',')
     1397                {
     1398                    switch (*pcszRanges)
     1399                    {
     1400                        case 'k':
     1401                        case 'K':
     1402                        {
     1403                            cb *= _1K;
     1404                            break;
     1405                        }
     1406                        case 'm':
     1407                        case 'M':
     1408                        {
     1409                            cb *= _1M;
     1410                            break;
     1411                        }
     1412                        case 'g':
     1413                        case 'G':
     1414                        {
     1415                            cb *= _1G;
     1416                            break;
     1417                        }
     1418                        default:
     1419                        {
     1420                            RTPrintf("Invalid size suffix '%s'\n", pcszRanges);
     1421                            rc = VERR_INVALID_PARAMETER;
     1422                        }
     1423                    }
     1424                    if (RT_SUCCESS(rc))
     1425                        pcszRanges++;
     1426                }
     1427
     1428                if (   *pcszRanges != ','
     1429                    && !(i == cRanges - 1 && *pcszRanges == '\0'))
     1430                {
     1431                    rc = VERR_INVALID_PARAMETER;
     1432                    break;
     1433                }
     1434
     1435                pcszRanges++;
     1436
     1437                paRanges[i].offStart = off;
     1438                paRanges[i].cbRange  = cb;
     1439            }
     1440        } while (0);
     1441
     1442        if (RT_SUCCESS(rc))
     1443        {
     1444            if (!fAsync)
     1445                rc = VDDiscardRanges(pDisk->pVD, paRanges, cRanges);
     1446            else
     1447            {
     1448                VDIOREQ IoReq;
     1449                RTSEMEVENT EventSem;
     1450
     1451                rc = RTSemEventCreate(&EventSem);
     1452                if (RT_SUCCESS(rc))
     1453                {
     1454                    memset(&IoReq, 0, sizeof(VDIOREQ));
     1455                    IoReq.enmTxDir = VDIOREQTXDIR_FLUSH;
     1456                    IoReq.pvUser   = pDisk;
     1457                    IoReq.idx      = 0;
     1458                    rc = VDAsyncDiscardRanges(pDisk->pVD, paRanges, cRanges, tstVDIoTestReqComplete, &IoReq, EventSem);
     1459                    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     1460                    {
     1461                        rc = RTSemEventWait(EventSem, RT_INDEFINITE_WAIT);
     1462                        AssertRC(rc);
     1463                    }
     1464                    else if (rc == VINF_VD_ASYNC_IO_FINISHED)
     1465                        rc = VINF_SUCCESS;
     1466
     1467                    RTSemEventDestroy(EventSem);
     1468                }
     1469            }
     1470
    13101471            if (   RT_SUCCESS(rc)
    13111472                && pDisk->pMemDiskVerify)
    13121473            {
    1313                 void *pv = RTMemAllocZ(cbDiscard);
    1314                 if (pv)
     1474                for (unsigned i = 0; i < cRanges; i++)
    13151475                {
    1316                     RTSGSEG SgSeg;
    1317                     RTSGBUF SgBuf;
    1318 
    1319                     SgSeg.pvSeg = pv;
    1320                     SgSeg.cbSeg = cbDiscard;
    1321                     RTSgBufInit(&SgBuf, &SgSeg, 1);
    1322                     rc = VDMemDiskWrite(pDisk->pMemDiskVerify, off, cbDiscard, &SgBuf);
    1323                     RTMemFree(pv);
     1476                    void *pv = RTMemAllocZ(paRanges[i].cbRange);
     1477                    if (pv)
     1478                    {
     1479                        RTSGSEG SgSeg;
     1480                        RTSGBUF SgBuf;
     1481
     1482                        SgSeg.pvSeg = pv;
     1483                        SgSeg.cbSeg = paRanges[i].cbRange;
     1484                        RTSgBufInit(&SgBuf, &SgSeg, 1);
     1485                        rc = VDMemDiskWrite(pDisk->pMemDiskVerify, paRanges[i].offStart, paRanges[i].cbRange, &SgBuf);
     1486                        RTMemFree(pv);
     1487                    }
     1488                    else
     1489                    {
     1490                        rc = VERR_NO_MEMORY;
     1491                        break;
     1492                    }
    13241493                }
    1325                 else
    1326                     rc = VERR_NO_MEMORY;
    1327             }
    1328         }
     1494            }
     1495        }
     1496
     1497        if (paRanges)
     1498            RTMemFree(paRanges);
    13291499    }
    13301500
     
    16471817                    case VDDBGIOLOGREQ_DISCARD:
    16481818                    {
    1649                         PVDRANGE paRanges = NULL;
     1819                        PRTRANGE paRanges = NULL;
    16501820                        unsigned cRanges = 0;
    16511821
     
    27262896            }
    27272897            case VDIOREQTXDIR_FLUSH:
     2898            case VDIOREQTXDIR_DISCARD:
    27282899                break;
    27292900        }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette