Beispiel #1
0
/**
 * Writes data from the given S/G buffer into the I/O log.
 *
 * @returns VBox status code.
 * @param   pIoLogger    The I/O logger to use.
 * @param   off          The start offset in the log to write to.
 * @param   pSgBuf       The S/G buffer to write.
 * @param   cbSgBuf      How much data to write.
 */
static int vddbgIoLogWriteSgBuf(PVDIOLOGGERINT pIoLogger, uint64_t off, PCRTSGBUF pSgBuf, size_t cbSgBuf)
{
    int rc = VINF_SUCCESS;
    RTSGBUF SgBuf;

    RTSgBufClone(&SgBuf, pSgBuf);

    while (cbSgBuf)
    {
        void *pvSeg;
        size_t cbSeg = cbSgBuf;

        pvSeg = RTSgBufGetNextSegment(&SgBuf, &cbSeg);
        AssertPtrBreakStmt(pvSeg, rc = VERR_INTERNAL_ERROR);

        rc = RTFileWriteAt(pIoLogger->hFile, off, pvSeg, cbSeg, NULL);
        if (RT_FAILURE(rc))
            break;

        cbSgBuf -= cbSeg;
        off += cbSeg;
    }

    return rc;
}
/**
 * Write bytes from a S/G buffer to a file at a given offset.
 * This function may modify the file position.
 *
 * @returns iprt status code.
 * @param   hFile       Handle to the file.
 * @param   off         Where to write.
 * @param   pSgBuf      What to write.
 * @param   cbToWrite   How much to write.
 * @param   pcbWritten  How much we actually wrote.
 *                      If NULL an error will be returned for a partial write.
 */
RTR3DECL(int)  RTFileSgWriteAt(RTFILE hFile, RTFOFF off, PRTSGBUF pSgBuf, size_t cbToWrite, size_t *pcbWritten)
{
    int rc = VINF_SUCCESS;
    size_t cbWritten = 0;

    while (cbToWrite)
    {
        size_t cbThisWritten = 0;
        size_t cbBuf = cbToWrite;
        void *pvBuf = RTSgBufGetNextSegment(pSgBuf, &cbBuf);

        rc = RTFileWriteAt(hFile, off, pvBuf, cbBuf, pcbWritten ? &cbThisWritten : NULL);
        if (RT_SUCCESS(rc))
            cbWritten += cbThisWritten;

        if (   RT_FAILURE(rc)
            || (   cbThisWritten < cbBuf
                && pcbWritten))
            break;

        cbToWrite -= cbBuf;
        off += cbBuf;
    }

    if (pcbWritten)
        *pcbWritten = cbWritten;

    return rc;
}
Beispiel #3
0
/**
 * Writes a segment to the given file.
 *
 * @returns IPRT status code.
 *
 * @param pNode    The disk segment to write to the file.
 * @param pvParam  Opaque user data containing the pointer to
 *                 the file handle.
 */
static DECLCALLBACK(int) vdMemDiskSegmentWriteToFile(PAVLRU64NODECORE pNode, void *pvParam)
{
    PVDMEMDISKSEG pSeg = (PVDMEMDISKSEG)pNode;
    RTFILE hFile = *(PRTFILE)pvParam;

    return RTFileWriteAt(hFile, pSeg->Core.Key, pSeg->pvSeg, pSeg->Core.KeyLast - pSeg->Core.Key + 1, NULL);
}
static int dvmDiskWrite(void *pvUser, uint64_t off, const void *pvBuf, size_t cbWrite)
{
    PTSTRTDVMDISK pDisk = (PTSTRTDVMDISK)pvUser;

    if (pDisk->fUseImage)
        return RTFileWriteAt(pDisk->hImage, off, pvBuf, cbWrite, NULL);
    return RTDvmVolumeWrite(pDisk->hVol, off, pvBuf, cbWrite);
}
Beispiel #5
0
static int fileWriteSyncCallback(void * /* pvUser */, void *pvStorage, uint64_t uOffset,
                                   const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
{
    /* Validate input. */
    AssertPtrReturn(pvStorage, VERR_INVALID_POINTER);

    PFILESTORAGEINTERNAL pInt = (PFILESTORAGEINTERNAL)pvStorage;

    return RTFileWriteAt(pInt->file, uOffset, pvBuf, cbWrite, pcbWritten);
}
Beispiel #6
0
/**
 * Update the header of the I/O logger to the current state.
 *
 * @returns VBox status code.
 * @param   pIoLogger    The I/O logger to update.
 */
static int vddbgIoLoggerHeaderUpdate(PVDIOLOGGERINT pIoLogger)
{
    int rc = VINF_SUCCESS;
    IoLogHeader Hdr;

    memcpy(Hdr.szMagic, VDIOLOG_MAGIC, sizeof(Hdr.szMagic));
    Hdr.fFlags = RT_H2LE_U32(pIoLogger->fFlags);
    Hdr.u64Id  = RT_H2LE_U64(pIoLogger->idNext);
    rc = RTFileWriteAt(pIoLogger->hFile, 0, &Hdr, sizeof(Hdr), NULL);

    return rc;
}
/**
 * Close and remove an open PID File.
 *
 * @param  pszPath  The path to the PID File,
 * @param  hFile    The handle for the file. NIL_RTFILE is ignored as usual.
 */
VBGLR3DECL(void) VbglR3ClosePidFile(const char *pszPath, RTFILE hFile)
{
    AssertPtrReturnVoid(pszPath);
    if (hFile != NIL_RTFILE)
    {
#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
        RTFileWriteAt(hFile, 0, "-1", 2, NULL);
#else
        RTFileDelete(pszPath);
#endif
        RTFileClose(hFile);
    }
}
Beispiel #8
0
RTR3DECL(int) RTTarFileWriteAt(RTTARFILE hFile, uint64_t off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
{
    PRTTARFILEINTERNAL pFileInt = hFile;
    RTTARFILE_VALID_RETURN(pFileInt);

    if ((pFileInt->fOpenMode & RTFILE_O_WRITE) != RTFILE_O_WRITE)
        return VERR_ACCESS_DENIED;

    size_t cbTmpWritten = 0;
    int rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->offStart + 512 + off, pvBuf, cbToWrite, &cbTmpWritten);
    pFileInt->cbSize += cbTmpWritten;
    pFileInt->offCurrent = off + cbTmpWritten;
    if (pcbWritten)
        *pcbWritten = cbTmpWritten;

    return rc;
}
Beispiel #9
0
VBOXDDU_DECL(int) VDDbgIoLogComplete(VDIOLOGGER hIoLogger, VDIOLOGENT hIoLogEntry, int rcReq, PCRTSGBUF pSgBuf)
{
    int rc = VINF_SUCCESS;
    PVDIOLOGGERINT pIoLogger = hIoLogger;
    PVDIOLOGENTINT pIoLogEntry = hIoLogEntry;

    AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
    AssertPtrReturn(pIoLogEntry, VERR_INVALID_HANDLE);

    rc = RTSemFastMutexRequest(pIoLogger->hMtx);
    AssertRCReturn(rc, rc);

    IoLogEntryComplete Entry;

    Entry.u32Type     = VDIOLOG_EVENT_COMPLETE;
    Entry.u64Id       = RT_H2LE_U64(pIoLogEntry->idStart);
    Entry.msDuration  = RTTimeProgramMilliTS() - RT_H2LE_U64(pIoLogEntry->tsStart);
    Entry.i32Rc       = (int32_t)RT_H2LE_U32((uint32_t)rcReq);
    Entry.u64IoBuffer = RT_H2LE_U64(pIoLogEntry->cbIo);

    /* Write new entry. */
    rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
    if (RT_SUCCESS(rc))
    {
        pIoLogger->offWriteNext += sizeof(Entry);

        if (pIoLogEntry->cbIo)
        {
            rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, pIoLogEntry->cbIo);
            if (RT_SUCCESS(rc))
                pIoLogger->offWriteNext += pIoLogEntry->cbIo;
            else
            {
                pIoLogger->offWriteNext -= sizeof(Entry);
                rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
            }
        }
    }

    RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
    RTSemFastMutexRelease(pIoLogger->hMtx);
    return rc;
}
DECLHIDDEN(int) drvHostBaseWriteOs(PDRVHOSTBASE pThis, uint64_t off, const void *pvBuf, size_t cbWrite)
{
    return RTFileWriteAt(pThis->Os.hFileDevice, off, pvBuf, cbWrite, NULL);
}
Beispiel #11
0
RTR3DECL(int) RTTarFileClose(RTTARFILE hFile)
{
    /* Already closed? */
    if (hFile == NIL_RTTARFILE)
        return VINF_SUCCESS;

    PRTTARFILEINTERNAL pFileInt = hFile;
    RTTARFILE_VALID_RETURN(pFileInt);

    int rc = VINF_SUCCESS;

    /* In write mode: */
    if ((pFileInt->fOpenMode & (RTFILE_O_WRITE | RTFILE_O_READ)) == RTFILE_O_WRITE)
    {
        pFileInt->pTar->fFileOpenForWrite = false;
        do
        {
            /* If the user has called RTTarFileSetSize in the meantime, we have
               to make sure the file has the right size. */
            if (pFileInt->cbSetSize > pFileInt->cbSize)
            {
                rc = rtTarAppendZeros(pFileInt, pFileInt->cbSetSize - pFileInt->cbSize);
                if (RT_FAILURE(rc))
                    break;
            }

            /* If the written size isn't 512 byte aligned, we need to fix this. */
            RTTARRECORD record;
            RT_ZERO(record);
            uint64_t cbSizeAligned = RT_ALIGN(pFileInt->cbSize, sizeof(RTTARRECORD));
            if (cbSizeAligned != pFileInt->cbSize)
            {
                /* Note the RTFile method. We didn't increase the cbSize or cbCurrentPos here. */
                rc = RTFileWriteAt(pFileInt->pTar->hTarFile,
                                   pFileInt->offStart + sizeof(RTTARRECORD) + pFileInt->cbSize,
                                   &record,
                                   cbSizeAligned - pFileInt->cbSize,
                                   NULL);
                if (RT_FAILURE(rc))
                    break;
            }

            /* Create a header record for the file */
            /* Todo: mode, gid, uid, mtime should be setable (or detected myself) */
            RTTIMESPEC time;
            RTTimeNow(&time);
            rc = rtTarCreateHeaderRecord(&record, pFileInt->pszFilename, pFileInt->cbSize,
                                         0, 0, 0600, RTTimeSpecGetSeconds(&time));
            if (RT_FAILURE(rc))
                break;

            /* Write this at the start of the file data */
            rc = RTFileWriteAt(pFileInt->pTar->hTarFile, pFileInt->offStart, &record, sizeof(RTTARRECORD), NULL);
            if (RT_FAILURE(rc))
                break;
        }
        while (0);
    }

    /*
     * Now cleanup and delete the handle.
     */
    if (pFileInt->pszFilename)
        RTStrFree(pFileInt->pszFilename);
    if (pFileInt->hVfsIos != NIL_RTVFSIOSTREAM)
    {
        RTVfsIoStrmRelease(pFileInt->hVfsIos);
        pFileInt->hVfsIos = NIL_RTVFSIOSTREAM;
    }
    pFileInt->u32Magic = RTTARFILE_MAGIC_DEAD;
    RTMemFree(pFileInt);

    return rc;
}
Beispiel #12
0
/**
 * Processes a given task list for assigned to the given endpoint.
 */
static int pdmacFileAioMgrFailsafeProcessEndpointTaskList(PPDMACEPFILEMGR pAioMgr,
                                                          PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
                                                          PPDMACTASKFILE pTasks)
{
    int rc = VINF_SUCCESS;

    while (pTasks)
    {
        RTMSINTERVAL msWhenNext;
        PPDMACTASKFILE pCurr = pTasks;

        if (!pdmacEpIsTransferAllowed(&pEndpoint->Core, (uint32_t)pCurr->DataSeg.cbSeg, &msWhenNext))
        {
            pAioMgr->msBwLimitExpired = RT_MIN(pAioMgr->msBwLimitExpired, msWhenNext);
            break;
        }

        pTasks = pTasks->pNext;

        switch (pCurr->enmTransferType)
        {
            case PDMACTASKFILETRANSFER_FLUSH:
            {
                rc = RTFileFlush(pEndpoint->hFile);
                break;
            }
            case PDMACTASKFILETRANSFER_READ:
            case PDMACTASKFILETRANSFER_WRITE:
            {
                if (pCurr->enmTransferType == PDMACTASKFILETRANSFER_READ)
                {
                    rc = RTFileReadAt(pEndpoint->hFile, pCurr->Off,
                                      pCurr->DataSeg.pvSeg,
                                      pCurr->DataSeg.cbSeg,
                                      NULL);
                }
                else
                {
                    if (RT_UNLIKELY((uint64_t)pCurr->Off + pCurr->DataSeg.cbSeg > pEndpoint->cbFile))
                    {
                        ASMAtomicWriteU64(&pEndpoint->cbFile, pCurr->Off + pCurr->DataSeg.cbSeg);
                        RTFileSetSize(pEndpoint->hFile, pCurr->Off + pCurr->DataSeg.cbSeg);
                    }

                    rc = RTFileWriteAt(pEndpoint->hFile, pCurr->Off,
                                       pCurr->DataSeg.pvSeg,
                                       pCurr->DataSeg.cbSeg,
                                       NULL);
                }

                break;
            }
            default:
                AssertMsgFailed(("Invalid transfer type %d\n", pTasks->enmTransferType));
        }

        pCurr->pfnCompleted(pCurr, pCurr->pvUser, rc);
        pdmacFileTaskFree(pEndpoint, pCurr);
    }

    if (pTasks)
    {
        /* Add the rest of the tasks to the pending list */
        pdmacFileAioMgrEpAddTaskList(pEndpoint, pTasks);
    }

    return VINF_SUCCESS;
}
Beispiel #13
0
VBOXDDU_DECL(int) VDDbgIoLogStartDiscard(VDIOLOGGER hIoLogger, bool fAsync, PCRTRANGE paRanges, unsigned cRanges,
                                         PVDIOLOGENT phIoLogEntry)
{
    int rc = VINF_SUCCESS;
    PVDIOLOGGERINT pIoLogger = hIoLogger;
    PVDIOLOGENTINT pIoLogEntry = NULL;

    AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
    AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER);

    rc = RTSemFastMutexRequest(pIoLogger->hMtx);
    AssertRCReturn(rc, rc);

    pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries);
    if (pIoLogEntry)
    {
        IoLogEntryStart Entry;

        pIoLogEntry->idStart = pIoLogger->idNext++;

        Entry.u32Type         = VDIOLOG_EVENT_START;
        Entry.u8AsyncIo       = fAsync ? 1 : 0;
        Entry.u32ReqType      = VDDBGIOLOGREQ_DISCARD;
        Entry.u64Id           = RT_H2LE_U64(pIoLogEntry->idStart);
        Entry.Discard.cRanges = RT_H2LE_U32(cRanges);

        /* Write new entry. */
        rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
        if (RT_SUCCESS(rc))
        {
            pIoLogger->offWriteNext += sizeof(Entry);

            IoLogEntryDiscard DiscardRange;

            for (unsigned i = 0; i < cRanges; i++)
            {
                DiscardRange.u64Off = RT_H2LE_U64(paRanges[i].offStart);
                DiscardRange.u32Discard = RT_H2LE_U32((uint32_t)paRanges[i].cbRange);
                rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext + i*sizeof(DiscardRange),
                                   &DiscardRange, sizeof(DiscardRange), NULL);
                if (RT_FAILURE(rc))
                    break;
            }

            if (RT_FAILURE(rc))
            {
                pIoLogger->offWriteNext -= sizeof(Entry);
                rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
            }
            else
                pIoLogger->offWriteNext += cRanges * sizeof(DiscardRange);
        }

        if (RT_SUCCESS(rc))
        {
            pIoLogEntry->tsStart = RTTimeProgramMilliTS();
            pIoLogEntry->cbIo = 0;

            *phIoLogEntry = pIoLogEntry;
        }
        else
        {
            pIoLogger->idNext--;
            RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
        }
    }
    else
        rc = VERR_NO_MEMORY;

    RTSemFastMutexRelease(pIoLogger->hMtx);
    return rc;
}
Beispiel #14
0
VBOXDDU_DECL(int) VDDbgIoLogStart(VDIOLOGGER hIoLogger, bool fAsync, VDDBGIOLOGREQ enmTxDir, uint64_t off, size_t cbIo, PCRTSGBUF pSgBuf,
                                  PVDIOLOGENT phIoLogEntry)
{
    int rc = VINF_SUCCESS;
    PVDIOLOGGERINT pIoLogger = hIoLogger;
    PVDIOLOGENTINT pIoLogEntry = NULL;

    AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
    AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER);
    AssertReturn(enmTxDir > VDDBGIOLOGREQ_INVALID && enmTxDir <= VDDBGIOLOGREQ_FLUSH, VERR_INVALID_PARAMETER);

    rc = RTSemFastMutexRequest(pIoLogger->hMtx);
    AssertRCReturn(rc, rc);

    pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries);
    if (pIoLogEntry)
    {
        IoLogEntryStart Entry;

        pIoLogEntry->idStart = pIoLogger->idNext++;

        Entry.u32Type       = VDIOLOG_EVENT_START;
        Entry.u8AsyncIo    = fAsync ? 1 : 0;
        Entry.u32ReqType   = enmTxDir;
        Entry.u64Id        = RT_H2LE_U64(pIoLogEntry->idStart);
        Entry.Io.u64Off    = RT_H2LE_U64(off);
        Entry.Io.u64IoSize = RT_H2LE_U64(cbIo);

        /* Write new entry. */
        rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
        if (RT_SUCCESS(rc))
        {
            pIoLogger->offWriteNext += sizeof(Entry);

            if (   enmTxDir == VDDBGIOLOGREQ_WRITE
                && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_WRITTEN))
            {
                /* Write data. */
                rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, cbIo);
                if (RT_FAILURE(rc))
                {
                    pIoLogger->offWriteNext -= sizeof(Entry);
                    rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
                }
                else
                    pIoLogger->offWriteNext += cbIo;
            }
        }

        if (RT_SUCCESS(rc))
        {
            pIoLogEntry->tsStart = RTTimeProgramMilliTS();

            if (   enmTxDir == VDDBGIOLOGREQ_READ
                && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_READ))
                pIoLogEntry->cbIo = cbIo;
            else
                pIoLogEntry->cbIo = 0;

            *phIoLogEntry = pIoLogEntry;
        }
        else
        {
            pIoLogger->idNext--;
            RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
        }
    }
    else
        rc = VERR_NO_MEMORY;

    RTSemFastMutexRelease(pIoLogger->hMtx);
    return rc;
}
/**
 * Modifies the autostart database.
 *
 * @returns VBox status code.
 * @param   fAutostart    Flag whether the autostart or autostop database is modified.
 * @param   fAddVM        Flag whether a VM is added or removed from the database.
 */
int AutostartDb::autostartModifyDb(bool fAutostart, bool fAddVM)
{
    int rc = VINF_SUCCESS;
    char *pszUser = NULL;

    /* Check if the path is set. */
    if (!m_pszAutostartDbPath)
        return VERR_PATH_NOT_FOUND;

    rc = RTProcQueryUsernameA(RTProcSelf(), &pszUser);
    if (RT_SUCCESS(rc))
    {
        char *pszFile;
        uint64_t fOpen = RTFILE_O_DENY_ALL | RTFILE_O_READWRITE;
        RTFILE hAutostartFile;

        AssertPtr(pszUser);

        if (fAddVM)
            fOpen |= RTFILE_O_OPEN_CREATE;
        else
            fOpen |= RTFILE_O_OPEN;

        rc = RTStrAPrintf(&pszFile, "%s/%s.%s",
                          m_pszAutostartDbPath, pszUser, fAutostart ? "start" : "stop");
        if (RT_SUCCESS(rc))
        {
            rc = RTFileOpen(&hAutostartFile, pszFile, fOpen);
            if (RT_SUCCESS(rc))
            {
                uint64_t cbFile;

                /*
                 * Files with more than 16 bytes are rejected because they just contain
                 * a number of the amount of VMs with autostart configured, so they
                 * should be really really small. Anything else is bogus.
                 */
                rc = RTFileGetSize(hAutostartFile, &cbFile);
                if (   RT_SUCCESS(rc)
                    && cbFile <= 16)
                {
                    char abBuf[16 + 1]; /* trailing \0 */
                    uint32_t cAutostartVms = 0;

                    RT_ZERO(abBuf);

                    /* Check if the file was just created. */
                    if (cbFile)
                    {
                        rc = RTFileRead(hAutostartFile, abBuf, cbFile, NULL);
                        if (RT_SUCCESS(rc))
                        {
                            rc = RTStrToUInt32Ex(abBuf, NULL, 10 /* uBase */, &cAutostartVms);
                            if (   rc == VWRN_TRAILING_CHARS
                                || rc == VWRN_TRAILING_SPACES)
                                rc = VINF_SUCCESS;
                        }
                    }

                    if (RT_SUCCESS(rc))
                    {
                        size_t cbBuf;

                        /* Modify VM counter and write back. */
                        if (fAddVM)
                            cAutostartVms++;
                        else
                            cAutostartVms--;

                        if (cAutostartVms > 0)
                        {
                            cbBuf = RTStrPrintf(abBuf, sizeof(abBuf), "%u", cAutostartVms);
                            rc = RTFileSetSize(hAutostartFile, cbBuf);
                            if (RT_SUCCESS(rc))
                                rc = RTFileWriteAt(hAutostartFile, 0, abBuf, cbBuf, NULL);
                        }
                        else
                        {
                            /* Just delete the file if there are no VMs left. */
                            RTFileClose(hAutostartFile);
                            RTFileDelete(pszFile);
                            hAutostartFile = NIL_RTFILE;
                        }
                    }
                }
                else if (RT_SUCCESS(rc))
                    rc = VERR_FILE_TOO_BIG;

                if (hAutostartFile != NIL_RTFILE)
                    RTFileClose(hAutostartFile);
            }
            RTStrFree(pszFile);
        }

        RTStrFree(pszUser);
    }

    return rc;
}